From fb8741aaf351a6492d7e9dd8a3c1d59080c42768 Mon Sep 17 00:00:00 2001 From: Rik Veenboer Date: Mon, 28 May 2012 21:04:04 +0200 Subject: [PATCH] pull vendor --- vendor/JXInput/0.3.4/c/JXInputManager.cpp | 175 ++ vendor/JXInput/0.3.4/c/JXInputManager.h | 47 + vendor/JXInput/0.3.4/c/ReadMe.txt | 37 + vendor/JXInput/0.3.4/c/StdAfx.cpp | 9 + vendor/JXInput/0.3.4/c/StdAfx.h | 32 + ..._jxinput_directinput_DirectInputDriver.cpp | 279 ++ ...de_jxinput_directinput_DirectInputDriver.h | 183 ++ vendor/JXInput/0.3.4/c/dllmain.cpp | 24 + vendor/JXInput/0.3.4/c/jxinput.cpp | 600 ++++ vendor/JXInput/0.3.4/c/jxinput.dsp | 175 ++ vendor/JXInput/0.3.4/c/jxinput.dsw | 29 + vendor/JXInput/0.3.4/c/jxinput.h | 183 ++ vendor/JXInput/0.3.4/c/jxinput.sln | 20 + vendor/JXInput/0.3.4/c/jxinput.vcproj | 367 +++ .../0.3.4/java/de/hardcode/jxinput/Axis.java | 72 + .../java/de/hardcode/jxinput/Button.java | 35 + .../java/de/hardcode/jxinput/Directional.java | 45 + .../java/de/hardcode/jxinput/Feature.java | 38 + .../de/hardcode/jxinput/JXInputDevice.java | 71 + .../de/hardcode/jxinput/JXInputManager.java | 233 ++ .../hardcode/jxinput/directinput/DIAxis.java | 70 + .../jxinput/directinput/DIButton.java | 55 + .../jxinput/directinput/DIDirectional.java | 78 + .../directinput/DirectInputDevice.java | 170 ++ .../directinput/DirectInputDriver.java | 184 ++ .../de/hardcode/jxinput/directinput/Log.java | 34 + .../jxinput/event/JXInputAxisEvent.java | 48 + .../event/JXInputAxisEventListener.java | 19 + .../jxinput/event/JXInputButtonEvent.java | 38 + .../event/JXInputButtonEventListener.java | 19 + .../event/JXInputDirectionalEvent.java | 56 + .../JXInputDirectionalEventListener.java | 19 + .../jxinput/event/JXInputEventManager.java | 284 ++ .../jxinput/j3d/DeviceConfiguration.java | 95 + .../jxinput/j3d/IsActiveCondition.java | 25 + .../j3d/IsActiveOnButtonCondition.java | 39 + .../jxinput/j3d/IsAlwaysActiveCondition.java | 38 + .../hardcode/jxinput/j3d/J3DInputDevice.java | 171 ++ .../java/de/hardcode/jxinput/j3d/package.html | 11 + .../jxinput/j3d/test/HelloUniverse.java | 205 ++ .../jxinput/j3d/test/SensorBehavior.java | 70 + .../keyboard/InvalidKeyCodeException.java | 35 + .../keyboard/JXKeyboardInputDevice.java | 175 ++ .../hardcode/jxinput/keyboard/KeyButton.java | 94 + .../jxinput/keyboard/KeyboardDriver.java | 141 + .../de/hardcode/jxinput/keyboard/package.html | 10 + .../hardcode/jxinput/test/AxisListener.java | 39 + .../hardcode/jxinput/test/ButtonListener.java | 38 + .../jxinput/test/DirectionalListener.java | 37 + .../jxinput/test/JXInputDevicePanel.form | 97 + .../jxinput/test/JXInputDevicePanel.java | 296 ++ .../jxinput/test/JXInputTestDialog.form | 79 + .../jxinput/test/JXInputTestDialog.java | 286 ++ .../jxinput/util/LatestChangedValueAxis.java | 98 + .../de/hardcode/jxinput/util/OrButton.java | 52 + .../jxinput/virtual/JXVirtualInputDevice.java | 140 + .../hardcode/jxinput/virtual/VirtualAxis.java | 207 ++ .../jxinput/virtual/VirtualDriver.java | 95 + .../de/hardcode/jxinput/virtual/package.html | 11 + vendor/JXInput/0.3.4/jxinput.dll | Bin 0 -> 94208 bytes vendor/JXInput/0.3.4/jxinput.jar | Bin 0 -> 73232 bytes vendor/JavaWinampApi/1.1/cpp/Makefile.win | 34 + vendor/JavaWinampApi/1.1/cpp/WINAMPCMD.H | 62 + .../JavaWinampApi/1.1/cpp/WinampController.c | 587 ++++ .../JavaWinampApi/1.1/cpp/WinampController.h | 285 ++ vendor/JavaWinampApi/1.1/cpp/cpy.bat | 1 + vendor/JavaWinampApi/1.1/cpp/libwpcom.def | 58 + vendor/JavaWinampApi/1.1/cpp/wa_ipc.h | 1620 +++++++++++ vendor/JavaWinampApi/1.1/cpp/wpcom.dev | 69 + vendor/JavaWinampApi/1.1/cpp/wpcom.layout | 17 + .../com/qotsa/exception/InvalidHandle.java | 40 + .../com/qotsa/exception/InvalidParameter.java | 40 + .../1.1/java/com/qotsa/exception/package.html | 20 + .../com/qotsa/jni/controller/JNIWinamp.java | 227 ++ .../jni/controller/WinampController.java | 592 ++++ .../com/qotsa/jni/controller/package.html | 20 + .../1.1.1/commons-logging-1.1.1.jar | Bin 0 -> 60841 bytes .../1.1.1/commons-logging-adapters-1.1.1.jar | Bin 0 -> 26520 bytes .../1.1.1/commons-logging-api-1.1.1.jar | Bin 0 -> 52313 bytes .../java/org/apache/commons/logging/Log.java | 246 ++ .../logging/LogConfigurationException.java | 98 + .../apache/commons/logging/LogFactory.java | 1824 ++++++++++++ .../org/apache/commons/logging/LogSource.java | 262 ++ .../commons/logging/impl/AvalonLogger.java | 292 ++ .../logging/impl/Jdk13LumberjackLogger.java | 335 +++ .../commons/logging/impl/Jdk14Logger.java | 304 ++ .../commons/logging/impl/Log4JLogger.java | 342 +++ .../commons/logging/impl/LogFactoryImpl.java | 1500 ++++++++++ .../commons/logging/impl/LogKitLogger.java | 294 ++ .../apache/commons/logging/impl/NoOpLog.java | 107 + .../logging/impl/ServletContextCleaner.java | 138 + .../commons/logging/impl/SimpleLog.java | 721 +++++ .../commons/logging/impl/WeakHashtable.java | 478 ++++ .../apache/commons/logging/impl/package.html | 22 + .../org/apache/commons/logging/package.html | 255 ++ .../com/dt/iTunesController/ITArtwork.java | 55 + .../iTunesController/ITArtworkCollection.java | 55 + .../dt/iTunesController/ITArtworkFormat.java | 13 + .../iTunesController/ITAudioCDPlaylist.java | 76 + .../dt/iTunesController/ITBrowserWindow.java | 45 + .../iTunesController/ITCOMDisabledReason.java | 12 + .../com/dt/iTunesController/ITEQPreset.java | 236 ++ .../dt/iTunesController/ITFileOrCDTrack.java | 39 + .../iTunesController/ITLibraryPlaylist.java | 20 + .../0.2/com/dt/iTunesController/ITObject.java | 112 + .../ITObjectPersistentID.java | 53 + .../iTunesController/ITOperationStatus.java | 62 + .../dt/iTunesController/ITPlayerState.java | 13 + .../com/dt/iTunesController/ITPlaylist.java | 154 + .../ITPlaylistCollection.java | 67 + .../dt/iTunesController/ITPlaylistKind.java | 15 + .../iTunesController/ITPlaylistPrintKind.java | 14 + .../ITPlaylistRepeatMode.java | 14 + .../ITPlaylistSearchField.java | 16 + .../com/dt/iTunesController/ITRatingKind.java | 11 + .../0.2/com/dt/iTunesController/ITSource.java | 51 + .../iTunesController/ITSourceCollection.java | 66 + .../com/dt/iTunesController/ITSourceKind.java | 17 + .../0.2/com/dt/iTunesController/ITTrack.java | 492 ++++ .../iTunesController/ITTrackCollection.java | 91 + .../com/dt/iTunesController/ITTrackKind.java | 15 + .../com/dt/iTunesController/ITURLTrack.java | 175 ++ .../dt/iTunesController/ITUserPlaylist.java | 60 + .../com/dt/iTunesController/ITVideoKind.java | 13 + .../0.2/com/dt/iTunesController/ITWindow.java | 32 + .../iTunesController/ITWindowCollection.java | 55 + .../0.2/com/dt/iTunesController/iTunes.java | 488 ++++ .../com/dt/iTunesController/iTunesEvents.java | 62 + .../iTunesEventsInterface.java | 115 + .../com/jacob/activeX/ActiveXComponent.java | 479 ++++ .../jacob/activeX/ActiveXDispatchEvents.java | 106 + .../jacob/activeX/ActiveXInvocationProxy.java | 183 ++ .../java/com/jacob/com/ComException.java | 141 + .../java/com/jacob/com/ComFailException.java | 88 + .../1.15-M4/java/com/jacob/com/ComThread.java | 169 ++ .../1.15-M4/java/com/jacob/com/Currency.java | 91 + .../java/com/jacob/com/DateUtilities.java | 105 + .../1.15-M4/java/com/jacob/com/Dispatch.java | 872 ++++++ .../java/com/jacob/com/DispatchEvents.java | 219 ++ .../com/jacob/com/DispatchIdentifier.java | 82 + .../java/com/jacob/com/DispatchProxy.java | 92 + .../java/com/jacob/com/EnumVariant.java | 156 + .../java/com/jacob/com/InvocationProxy.java | 108 + .../jacob/com/InvocationProxyAllVariants.java | 123 + .../java/com/jacob/com/JacobException.java | 49 + .../java/com/jacob/com/JacobObject.java | 110 + .../java/com/jacob/com/JacobReleaseInfo.java | 96 + .../java/com/jacob/com/LibraryLoader.java | 230 ++ .../1.15-M4/java/com/jacob/com/MainSTA.java | 29 + .../jacob/com/NotImplementedException.java | 41 + .../jacob/1.15-M4/java/com/jacob/com/ROT.java | 279 ++ .../jacob/1.15-M4/java/com/jacob/com/STA.java | 101 + .../1.15-M4/java/com/jacob/com/SafeArray.java | 1172 ++++++++ .../1.15-M4/java/com/jacob/com/Variant.java | 2235 +++++++++++++++ .../java/com/jacob/com/VariantUtilities.java | 502 ++++ .../java/com/jacob/com/VariantViaEvent.java | 34 + .../com/jacob/com/WrongThreadException.java | 47 + .../1.6.0_23/include/classfile_constants.h | 523 ++++ vendor/jdk/1.6.0_23/include/jawt.h | 278 ++ vendor/jdk/1.6.0_23/include/jdwpTransport.h | 237 ++ vendor/jdk/1.6.0_23/include/jni.h | 1944 +++++++++++++ vendor/jdk/1.6.0_23/include/jvmti.h | 2504 +++++++++++++++++ vendor/jdk/1.6.0_23/include/win32/jawt_md.h | 41 + vendor/jdk/1.6.0_23/include/win32/jni_md.h | 19 + .../jintellitype/1.3.6/cpp/JIntellitype.cpp | 157 ++ .../jintellitype/1.3.6/cpp/JIntellitype.dev | 149 + .../1.3.6/cpp/JIntellitype.layout | 76 + .../1.3.6/cpp/JIntellitypeHandler.cpp | 279 ++ .../1.3.6/cpp/JIntellitypeHandler.h | 93 + .../1.3.6/cpp/JIntellitypeThread.cpp | 133 + .../1.3.6/cpp/JIntellitypeThread.h | 55 + .../1.3.6/cpp/JIntellitype_private.h | 23 + .../1.3.6/cpp/JIntellitype_private.rc | 35 + vendor/jintellitype/1.3.6/cpp/Makefile.win | 46 + vendor/jintellitype/1.3.6/cpp/StdAfx.cpp | 8 + vendor/jintellitype/1.3.6/cpp/StdAfx.h | 24 + .../com_melloware_jintellitype_JIntellitype.h | 53 + .../jintellitype/HotkeyListener.java | 46 + .../jintellitype/IntellitypeListener.java | 51 + .../melloware/jintellitype/JIntellitype.java | 665 +++++ .../jintellitype/JIntellitypeConstants.java | 182 ++ .../jintellitype/JIntellitypeException.java | 55 + .../java/com/melloware/jintellitype/Main.java | 80 + vendor/jlgui/3.0/lib/basicplayer3.0.jar | Bin 0 -> 11093 bytes vendor/jlgui/3.0/lib/commons-logging-api.jar | Bin 0 -> 26202 bytes vendor/jlgui/3.0/lib/jflac-1.2.jar | Bin 0 -> 103640 bytes vendor/jlgui/3.0/lib/jl1.0.jar | Bin 0 -> 105446 bytes vendor/jlgui/3.0/lib/jmactritonusspi1.74.jar | Bin 0 -> 138975 bytes vendor/jlgui/3.0/lib/jogg-0.0.7.jar | Bin 0 -> 6839 bytes vendor/jlgui/3.0/lib/jorbis-0.0.15.jar | Bin 0 -> 58917 bytes vendor/jlgui/3.0/lib/jspeex0.9.7.jar | Bin 0 -> 99833 bytes vendor/jlgui/3.0/lib/kj_dsp1.1.jar | Bin 0 -> 12578 bytes vendor/jlgui/3.0/lib/mp3spi1.9.4.jar | Bin 0 -> 24538 bytes vendor/jlgui/3.0/lib/tritonus_share.jar | Bin 0 -> 102723 bytes vendor/jlgui/3.0/lib/vorbisspi1.0.2.jar | Bin 0 -> 13776 bytes .../org.apache.commons.logging.LogFactory | 1 + .../jlgui/basicplayer/BasicController.java | 102 + .../jlgui/basicplayer/BasicPlayer.java | 1038 +++++++ .../jlgui/basicplayer/BasicPlayerEvent.java | 121 + .../basicplayer/BasicPlayerEventLauncher.java | 73 + .../basicplayer/BasicPlayerException.java | 107 + .../basicplayer/BasicPlayerListener.java | 72 + .../src/javazoom/jlgui/player/amp/Loader.java | 40 + .../jlgui/player/amp/PlayerActionEvent.java | 99 + .../javazoom/jlgui/player/amp/PlayerUI.java | 1827 ++++++++++++ .../jlgui/player/amp/StandalonePlayer.java | 500 ++++ .../player/amp/equalizer/ui/ControlCurve.java | 139 + .../jlgui/player/amp/equalizer/ui/Cubic.java | 46 + .../player/amp/equalizer/ui/EqualizerUI.java | 441 +++ .../amp/equalizer/ui/NaturalSpline.java | 108 + .../player/amp/equalizer/ui/SplinePanel.java | 133 + .../javazoom/jlgui/player/amp/jlguiicon.gif | Bin 0 -> 566 bytes .../src/javazoom/jlgui/player/amp/metrix.wsz | Bin 0 -> 188618 bytes .../player/amp/playlist/BasePlaylist.java | 586 ++++ .../jlgui/player/amp/playlist/Playlist.java | 138 + .../player/amp/playlist/PlaylistFactory.java | 107 + .../player/amp/playlist/PlaylistItem.java | 302 ++ .../player/amp/playlist/ui/PlaylistUI.java | 882 ++++++ .../player/amp/skin/AbsoluteConstraints.java | 151 + .../jlgui/player/amp/skin/AbsoluteLayout.java | 196 ++ .../jlgui/player/amp/skin/ActiveFont.java | 88 + .../jlgui/player/amp/skin/ActiveJBar.java | 45 + .../jlgui/player/amp/skin/ActiveJButton.java | 48 + .../jlgui/player/amp/skin/ActiveJIcon.java | 62 + .../jlgui/player/amp/skin/ActiveJLabel.java | 104 + .../player/amp/skin/ActiveJNumberLabel.java | 61 + .../jlgui/player/amp/skin/ActiveJPopup.java | 70 + .../jlgui/player/amp/skin/ActiveJSlider.java | 58 + .../player/amp/skin/ActiveJToggleButton.java | 47 + .../jlgui/player/amp/skin/ActiveSliderUI.java | 146 + .../jlgui/player/amp/skin/DragAdapter.java | 68 + .../player/amp/skin/DropTargetAdapter.java | 163 ++ .../jlgui/player/amp/skin/ImageBorder.java | 65 + .../player/amp/skin/PlaylistUIDelegate.java | 276 ++ .../jlgui/player/amp/skin/PopupAdapter.java | 61 + .../javazoom/jlgui/player/amp/skin/Skin.java | 1493 ++++++++++ .../jlgui/player/amp/skin/SkinLoader.java | 124 + .../javazoom/jlgui/player/amp/skin/Taftb.java | 153 + .../jlgui/player/amp/skin/UrlDialog.java | 148 + .../jlgui/player/amp/skin/skin.properties | 65 + .../jlgui/player/amp/tag/APEInfo.java | 340 +++ .../jlgui/player/amp/tag/FlacInfo.java | 189 ++ .../jlgui/player/amp/tag/MpegInfo.java | 315 +++ .../jlgui/player/amp/tag/OggVorbisInfo.java | 307 ++ .../jlgui/player/amp/tag/TagInfo.java | 120 + .../jlgui/player/amp/tag/TagInfoFactory.java | 399 +++ .../jlgui/player/amp/tag/ui/APEDialog.java | 187 ++ .../jlgui/player/amp/tag/ui/EmptyDialog.java | 75 + .../jlgui/player/amp/tag/ui/FlacDialog.java | 165 ++ .../jlgui/player/amp/tag/ui/MpegDialog.java | 194 ++ .../player/amp/tag/ui/OggVorbisDialog.java | 196 ++ .../player/amp/tag/ui/TagInfoDialog.java | 60 + .../jlgui/player/amp/tag/ui/TagSearch.java | 434 +++ .../jlgui/player/amp/tag/ui/tag.properties | 8 + .../jlgui/player/amp/util/BMPLoader.java | 301 ++ .../jlgui/player/amp/util/Config.java | 711 +++++ .../jlgui/player/amp/util/FileNameFilter.java | 108 + .../jlgui/player/amp/util/FileSelector.java | 156 + .../jlgui/player/amp/util/FileUtil.java | 167 ++ .../player/amp/util/ini/Alphabetizer.java | 79 + .../jlgui/player/amp/util/ini/Array.java | 114 + .../amp/util/ini/CRC32OutputStream.java | 50 + .../player/amp/util/ini/Configuration.java | 441 +++ .../player/amp/util/ini/SortedStrings.java | 338 +++ .../player/amp/util/ui/DevicePreference.java | 120 + .../player/amp/util/ui/EmptyPreference.java | 52 + .../jlgui/player/amp/util/ui/NodeItem.java | 46 + .../player/amp/util/ui/OutputPreference.java | 54 + .../player/amp/util/ui/PreferenceItem.java | 78 + .../jlgui/player/amp/util/ui/Preferences.java | 279 ++ .../player/amp/util/ui/SkinPreference.java | 185 ++ .../player/amp/util/ui/SystemPreference.java | 91 + .../player/amp/util/ui/TypePreference.java | 129 + .../player/amp/util/ui/VisualPreference.java | 292 ++ .../amp/util/ui/VisualizationPreference.java | 54 + .../player/amp/util/ui/device.properties | 6 + .../player/amp/util/ui/output.properties | 2 + .../player/amp/util/ui/preferences.properties | 27 + .../jlgui/player/amp/util/ui/skin.properties | 4 + .../player/amp/util/ui/system.properties | 3 + .../jlgui/player/amp/util/ui/type.properties | 2 + .../player/amp/util/ui/visual.properties | 15 + .../amp/util/ui/visualization.properties | 2 + .../amp/visual/ui/SpectrumTimeAnalyzer.java | 775 +++++ vendor/log4j/1.2.16/log4j-1.2.16.jar | Bin 0 -> 481534 bytes vendor/nativecall/0.4.1/NativeCall.dll | Bin 0 -> 7680 bytes vendor/nativecall/0.4.1/cpp/Debug/IntCall.asm | 1766 ++++++++++++ vendor/nativecall/0.4.1/cpp/Debug/IntCall.obj | Bin 0 -> 27787 bytes .../nativecall/0.4.1/cpp/Debug/NativeCall.asm | 1492 ++++++++++ .../nativecall/0.4.1/cpp/Debug/NativeCall.dll | Bin 0 -> 233590 bytes .../nativecall/0.4.1/cpp/Debug/NativeCall.obj | Bin 0 -> 29095 bytes vendor/nativecall/0.4.1/cpp/Debug/RCa01372 | Bin 0 -> 4904 bytes vendor/nativecall/0.4.1/cpp/Debug/RCa01444 | Bin 0 -> 4904 bytes vendor/nativecall/0.4.1/cpp/Debug/RCa01468 | Bin 0 -> 4904 bytes .../nativecall/0.4.1/cpp/Debug/VoidCall.asm | 1743 ++++++++++++ .../nativecall/0.4.1/cpp/Debug/VoidCall.obj | Bin 0 -> 27719 bytes vendor/nativecall/0.4.1/cpp/IntCall.cpp | 236 ++ vendor/nativecall/0.4.1/cpp/NativeCall.cpp | 234 ++ vendor/nativecall/0.4.1/cpp/NativeCall.dsp | 132 + vendor/nativecall/0.4.1/cpp/NativeCall.dsw | 29 + .../nativecall/0.4.1/cpp/Release/IntCall.asm | 943 +++++++ .../nativecall/0.4.1/cpp/Release/IntCall.obj | Bin 0 -> 3896 bytes .../0.4.1/cpp/Release/NativeCall.asm | 859 ++++++ .../0.4.1/cpp/Release/NativeCall.dll | Bin 0 -> 7680 bytes .../0.4.1/cpp/Release/NativeCall.map | 101 + .../0.4.1/cpp/Release/NativeCall.obj | Bin 0 -> 6571 bytes vendor/nativecall/0.4.1/cpp/Release/RCa01380 | Bin 0 -> 4904 bytes .../nativecall/0.4.1/cpp/Release/VoidCall.asm | 919 ++++++ .../nativecall/0.4.1/cpp/Release/VoidCall.obj | Bin 0 -> 3885 bytes vendor/nativecall/0.4.1/cpp/VoidCall.cpp | 228 ++ .../0.4.1/cpp/com_eaio_nativecall_IntCall.h | 29 + .../cpp/com_eaio_nativecall_NativeCall.h | 45 + .../0.4.1/cpp/com_eaio_nativecall_VoidCall.h | 29 + vendor/nativecall/0.4.1/cpp/readme.txt | 25 + vendor/nativecall/0.4.1/cpp/resource.h | 15 + vendor/nativecall/0.4.1/cpp/version.rc | 104 + .../services/com.eaio.nativecall.Verifier | 1 + .../java/com/eaio/nativecall/Holder.java | 133 + .../java/com/eaio/nativecall/IntCall.java | 143 + .../java/com/eaio/nativecall/NativeCall.java | 355 +++ .../java/com/eaio/nativecall/Verifier.java | 101 + .../java/com/eaio/nativecall/Verifiers.java | 83 + .../java/com/eaio/nativecall/VoidCall.java | 99 + .../com/eaio/nativecall/Win32Verifier.java | 122 + .../java/com/eaio/nativecall/package.html | 15 + vendor/nativecall/0.4.1/nativecall-0.4.1.jar | Bin 0 -> 9414 bytes .../0.4.1/nativeloader-200505172341.jar | Bin 0 -> 4939 bytes .../1.5.6/org/wiigee/control/Wiigee.java | 46 + .../control/WiimoteDeviceDiscovery.java | 103 + .../org/wiigee/control/WiimoteWiigee.java | 210 ++ .../1.5.6/org/wiigee/device/Device.java | 234 ++ .../1.5.6/org/wiigee/device/Wiimote.java | 602 ++++ .../org/wiigee/device/WiimoteStreamer.java | 400 +++ .../org/wiigee/event/AccelerationEvent.java | 79 + .../wiigee/event/AccelerationListener.java | 65 + .../org/wiigee/event/ActionStartEvent.java | 84 + .../org/wiigee/event/ActionStopEvent.java | 43 + .../org/wiigee/event/ButtonListener.java | 54 + .../org/wiigee/event/ButtonPressedEvent.java | 80 + .../org/wiigee/event/ButtonReleasedEvent.java | 49 + .../1.5.6/org/wiigee/event/GestureEvent.java | 71 + .../org/wiigee/event/GestureListener.java | 47 + .../1.5.6/org/wiigee/event/InfraredEvent.java | 69 + .../org/wiigee/event/InfraredListener.java | 40 + .../org/wiigee/event/MotionStartEvent.java | 63 + .../org/wiigee/event/MotionStopEvent.java | 42 + .../1.5.6/org/wiigee/event/RotationEvent.java | 65 + .../org/wiigee/event/RotationListener.java | 43 + .../org/wiigee/event/RotationSpeedEvent.java | 60 + .../filter/DirectionalEquivalenceFilter.java | 70 + .../1.5.6/org/wiigee/filter/Filter.java | 62 + .../org/wiigee/filter/HighPassFilter.java | 71 + .../org/wiigee/filter/IdleStateFilter.java | 86 + .../org/wiigee/filter/LowPassFilter.java | 67 + .../org/wiigee/filter/MotionDetectFilter.java | 102 + .../wiigee/filter/RotationResetFilter.java | 68 + .../filter/RotationThresholdFilter.java | 71 + .../1.5.6/org/wiigee/logic/Classifier.java | 109 + .../1.5.6/org/wiigee/logic/Gesture.java | 155 + .../1.5.6/org/wiigee/logic/GestureModel.java | 205 ++ vendor/wiigee/1.5.6/org/wiigee/logic/HMM.java | 314 +++ .../1.5.6/org/wiigee/logic/PreciseHMM.java | 449 +++ .../org/wiigee/logic/ProcessingUnit.java | 72 + .../1.5.6/org/wiigee/logic/Quantizer.java | 309 ++ .../wiigee/logic/TriggeredProcessingUnit.java | 188 ++ .../wiigee/1.5.6/org/wiigee/logic/XHMM.java | 85 + .../wiigee/1.5.6/org/wiigee/util/FileIO.java | 233 ++ vendor/wiigee/1.5.6/org/wiigee/util/Log.java | 43 + vendor/wiiscan/0.90/Debug/DelcomDLL.dll | Bin 0 -> 90112 bytes vendor/wiiscan/0.90/Debug/USBm.dll | Bin 0 -> 60928 bytes vendor/wiiscan/0.90/Debug/WiimoteLib.dll | Bin 0 -> 28672 bytes vendor/wiiscan/0.90/Debug/bdi.out | Bin 0 -> 560 bytes vendor/wiiscan/0.90/Debug/wiimotelibpoll.exe | Bin 0 -> 8192 bytes vendor/wiiscan/0.90/Debug/wiiscan.exe | Bin 0 -> 981504 bytes vendor/wiiscan/0.90/Debug/wiiscan.ini | 81 + vendor/wiiscan/0.90/Debug/wiiuse.dll | Bin 0 -> 114688 bytes vendor/wiiscan/0.90/Doc/CHANGEINGBTSTACK.rtf | 57 + vendor/wiiscan/0.90/Doc/CHANGELOG.rtf | 59 + vendor/wiiscan/0.90/Doc/INSTALL.rtf | 153 + vendor/wiiscan/0.90/Doc/LICENSE.rtf | 674 +++++ vendor/wiiscan/0.90/Doc/MANUAL_wiiscan.rtf | 500 ++++ vendor/wiiscan/0.90/Doc/README.rtf | 25 + vendor/wiiscan/0.90/Doc/README_FIRST.rtf | 30 + vendor/wiiscan/0.90/Doc/wiiscan.1 | 358 +++ vendor/wiiscan/0.90/Lib/Debug/WiimoteLib.dll | Bin 0 -> 28672 bytes .../0.90/Lib/Debug/WiimoteWhiteboard.exe | Bin 0 -> 24576 bytes .../wiiscan/0.90/Lib/Debug/wiimotelibpoll.exe | Bin 0 -> 8192 bytes vendor/wiiscan/0.90/Lib/DelcomDLL.dll | Bin 0 -> 90112 bytes vendor/wiiscan/0.90/Lib/DelcomDLL.lib | Bin 0 -> 24654 bytes .../wiiscan/0.90/Lib/Release/WiimoteLib.dll | Bin 0 -> 27648 bytes .../0.90/Lib/Release/WiimoteWhiteboard.exe | Bin 0 -> 23552 bytes .../0.90/Lib/Release/wiimotelibpoll.exe | Bin 0 -> 7680 bytes vendor/wiiscan/0.90/Lib/USBm.dll | Bin 0 -> 60928 bytes vendor/wiiscan/0.90/Lib/wiiuse.dll | Bin 0 -> 114688 bytes vendor/wiiscan/0.90/Lib/wiiuse.lib | Bin 0 -> 8210 bytes vendor/wiiscan/0.90/Release/DelcomDLL.dll | Bin 0 -> 90112 bytes vendor/wiiscan/0.90/Release/USBm.dll | Bin 0 -> 60928 bytes vendor/wiiscan/0.90/Release/WiimoteLib.dll | Bin 0 -> 27648 bytes .../wiiscan/0.90/Release/wiimotelibpoll.exe | Bin 0 -> 7680 bytes vendor/wiiscan/0.90/Release/wiiscan.exe | Bin 0 -> 281088 bytes vendor/wiiscan/0.90/Release/wiiscan.ini | 81 + vendor/wiiscan/0.90/Release/wiiuse.dll | Bin 0 -> 114688 bytes vendor/wiiscan/0.90/Tools/disable_all_usb.sh | 2 + vendor/wiiscan/0.90/Tools/enable_all_usb.sh | 2 + vendor/wiiscan/0.90/Tools/no_error_report.reg | 10 + vendor/wiiscan/0.90/Tools/popup_disable.reg | Bin 0 -> 320 bytes vendor/wiiscan/0.90/Tools/popup_enable.reg | Bin 0 -> 320 bytes vendor/wiiscan/0.90/Tools/wiitest.sh | 49 + vendor/wiiscan/0.90/src/DelcomDLL.h | 128 + vendor/wiiscan/0.90/src/args.h | 143 + vendor/wiiscan/0.90/src/configfile.h | 143 + vendor/wiiscan/0.90/src/exception.h | 197 ++ vendor/wiiscan/0.90/src/file.h | 208 ++ vendor/wiiscan/0.90/src/funs.h | 413 +++ vendor/wiiscan/0.90/src/process.h | 282 ++ vendor/wiiscan/0.90/src/reg.h | 95 + vendor/wiiscan/0.90/src/stringfun.h | 284 ++ vendor/wiiscan/0.90/src/templatefun.h | 52 + vendor/wiiscan/0.90/src/toolsfun.h | 34 + vendor/wiiscan/0.90/src/usbm.h | 204 ++ vendor/wiiscan/0.90/src/wiiscan.cpp | 27 + vendor/wiiscan/0.90/src/wiiscan.h | 1108 ++++++++ vendor/wiiscan/0.90/src/wiiuse.h | 653 +++++ vendor/wiiscan/0.90/wiiscan.sln | 20 + vendor/wiiscan/0.90/wiiscan.test.h | 1662 +++++++++++ vendor/wiiscan/0.90/wiiscan.vcproj | 243 ++ vendor/wiiuse/0.12/classic.c | 190 ++ vendor/wiiuse/0.12/classic.h | 53 + vendor/wiiuse/0.12/definitions.h | 79 + vendor/wiiuse/0.12/dynamics.c | 228 ++ vendor/wiiuse/0.12/dynamics.h | 56 + vendor/wiiuse/0.12/events.c | 878 ++++++ vendor/wiiuse/0.12/events.h | 54 + vendor/wiiuse/0.12/guitar_hero_3.c | 172 ++ vendor/wiiuse/0.12/guitar_hero_3.h | 62 + vendor/wiiuse/0.12/io.c | 119 + vendor/wiiuse/0.12/io.h | 56 + vendor/wiiuse/0.12/io_nix.c | 270 ++ vendor/wiiuse/0.12/io_win.c | 247 ++ vendor/wiiuse/0.12/ir.c | 748 +++++ vendor/wiiuse/0.12/ir.h | 56 + vendor/wiiuse/0.12/nunchuk.c | 210 ++ vendor/wiiuse/0.12/nunchuk.h | 53 + vendor/wiiuse/0.12/os.h | 56 + vendor/wiiuse/0.12/wiiuse.c | 764 +++++ vendor/wiiuse/0.12/wiiuse.h | 653 +++++ vendor/wiiuse/0.12/wiiuse_internal.h | 226 ++ vendor/wiiusej/0.12b/c/wiiusej_WiiUseApi.c | 669 +++++ vendor/wiiusej/0.12b/c/wiiusej_WiiUseApi.def | 34 + vendor/wiiusej/0.12b/c/wiiusej_WiiUseApi.h | 277 ++ .../wiiusej/0.12b/java/wiiusej/WiiUseApi.java | 351 +++ .../0.12b/java/wiiusej/WiiUseApiManager.java | 664 +++++ .../wiiusej/0.12b/java/wiiusej/Wiimote.java | 495 ++++ .../test/ClassicControllerGuiTest.java | 179 ++ .../wiiusej/test/CloseGuiTestCleanly.java | 58 + .../java/wiiusej/test/GuitarHero3GuiTest.java | 168 ++ .../wiiusej/0.12b/java/wiiusej/test/Main.java | 45 + .../java/wiiusej/test/NunchukGuiTest.java | 450 +++ .../0.12b/java/wiiusej/test/Tests.java | 389 +++ .../java/wiiusej/test/WiiuseJGuiTest.java | 1379 +++++++++ .../AccelerationExpansionEventPanel.java | 39 + .../java/wiiusej/utils/AccelerationPanel.java | 303 ++ .../utils/AccelerationWiimoteEventPanel.java | 37 + .../java/wiiusej/utils/ButtonsEventPanel.java | 382 +++ .../ClassicControllerButtonsEventPanel.java | 500 ++++ .../utils/GForceExpansionEventPanel.java | 38 + .../0.12b/java/wiiusej/utils/GForcePanel.java | 304 ++ .../utils/GForceWiimoteEventPanel.java | 37 + .../utils/GuitarHero3ButtonsEventPanel.java | 274 ++ .../utils/GuitarHeroJoystickEventPanel.java | 39 + .../0.12b/java/wiiusej/utils/IRPanel.java | 275 ++ .../wiiusej/utils/JoystickEventPanel.java | 248 ++ .../utils/NunchukJoystickEventPanel.java | 38 + .../utils/OrientationExpansionEventPanel.java | 38 + .../java/wiiusej/utils/OrientationPanel.java | 305 ++ .../utils/OrientationWiimoteEventPanel.java | 38 + .../0.12b/java/wiiusej/values/GForce.java | 80 + .../0.12b/java/wiiusej/values/IRSource.java | 106 + .../java/wiiusej/values/Orientation.java | 117 + .../java/wiiusej/values/RawAcceleration.java | 81 + .../wiiusej/wiiusejevents/GenericEvent.java | 59 + .../physicalevents/ButtonsEvent.java | 128 + .../ClassicControllerButtonsEvent.java | 329 +++ .../ClassicControllerEvent.java | 177 ++ .../physicalevents/ExpansionEvent.java | 40 + .../GuitarHeroButtonsEvent.java | 214 ++ .../physicalevents/GuitarHeroEvent.java | 119 + .../wiiusejevents/physicalevents/IREvent.java | 319 +++ .../physicalevents/JoystickEvent.java | 135 + .../physicalevents/MotionSensingEvent.java | 203 ++ .../physicalevents/NunchukButtonsEvent.java | 89 + .../physicalevents/NunchukEvent.java | 169 ++ .../physicalevents/WiimoteButtonsEvent.java | 267 ++ .../wiiusejevents/utils/EventsGatherer.java | 509 ++++ .../utils/WiiUseApiListener.java | 37 + .../wiiusejevents/utils/WiimoteListener.java | 145 + .../ClassicControllerInsertedEvent.java | 46 + .../ClassicControllerRemovedEvent.java | 47 + .../wiiuseapievents/DisconnectionEvent.java | 45 + .../GuitarHeroInsertedEvent.java | 47 + .../GuitarHeroRemovedEvent.java | 47 + .../wiiuseapievents/NunchukInsertedEvent.java | 51 + .../wiiuseapievents/NunchukRemovedEvent.java | 50 + .../wiiuseapievents/StatusEvent.java | 293 ++ .../wiiuseapievents/WiiUseApiEvent.java | 66 + .../wiiuseapievents/WiimoteEvent.java | 441 +++ 506 files changed, 94940 insertions(+) create mode 100644 vendor/JXInput/0.3.4/c/JXInputManager.cpp create mode 100644 vendor/JXInput/0.3.4/c/JXInputManager.h create mode 100644 vendor/JXInput/0.3.4/c/ReadMe.txt create mode 100644 vendor/JXInput/0.3.4/c/StdAfx.cpp create mode 100644 vendor/JXInput/0.3.4/c/StdAfx.h create mode 100644 vendor/JXInput/0.3.4/c/de_hardcode_jxinput_directinput_DirectInputDriver.cpp create mode 100644 vendor/JXInput/0.3.4/c/de_hardcode_jxinput_directinput_DirectInputDriver.h create mode 100644 vendor/JXInput/0.3.4/c/dllmain.cpp create mode 100644 vendor/JXInput/0.3.4/c/jxinput.cpp create mode 100644 vendor/JXInput/0.3.4/c/jxinput.dsp create mode 100644 vendor/JXInput/0.3.4/c/jxinput.dsw create mode 100644 vendor/JXInput/0.3.4/c/jxinput.h create mode 100644 vendor/JXInput/0.3.4/c/jxinput.sln create mode 100644 vendor/JXInput/0.3.4/c/jxinput.vcproj create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Axis.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Button.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Directional.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Feature.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/JXInputDevice.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/JXInputManager.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIAxis.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIButton.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIDirectional.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DirectInputDevice.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DirectInputDriver.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/Log.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputAxisEvent.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputAxisEventListener.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputButtonEvent.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputButtonEventListener.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputDirectionalEvent.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputDirectionalEventListener.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputEventManager.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/DeviceConfiguration.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsActiveCondition.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsActiveOnButtonCondition.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsAlwaysActiveCondition.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/J3DInputDevice.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/package.html create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/test/HelloUniverse.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/test/SensorBehavior.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/InvalidKeyCodeException.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/JXKeyboardInputDevice.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/KeyButton.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/KeyboardDriver.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/package.html create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/AxisListener.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/ButtonListener.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/DirectionalListener.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputDevicePanel.form create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputDevicePanel.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputTestDialog.form create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputTestDialog.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/util/LatestChangedValueAxis.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/util/OrButton.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/JXVirtualInputDevice.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/VirtualAxis.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/VirtualDriver.java create mode 100644 vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/package.html create mode 100644 vendor/JXInput/0.3.4/jxinput.dll create mode 100644 vendor/JXInput/0.3.4/jxinput.jar create mode 100644 vendor/JavaWinampApi/1.1/cpp/Makefile.win create mode 100644 vendor/JavaWinampApi/1.1/cpp/WINAMPCMD.H create mode 100644 vendor/JavaWinampApi/1.1/cpp/WinampController.c create mode 100644 vendor/JavaWinampApi/1.1/cpp/WinampController.h create mode 100644 vendor/JavaWinampApi/1.1/cpp/cpy.bat create mode 100644 vendor/JavaWinampApi/1.1/cpp/libwpcom.def create mode 100644 vendor/JavaWinampApi/1.1/cpp/wa_ipc.h create mode 100644 vendor/JavaWinampApi/1.1/cpp/wpcom.dev create mode 100644 vendor/JavaWinampApi/1.1/cpp/wpcom.layout create mode 100644 vendor/JavaWinampApi/1.1/java/com/qotsa/exception/InvalidHandle.java create mode 100644 vendor/JavaWinampApi/1.1/java/com/qotsa/exception/InvalidParameter.java create mode 100644 vendor/JavaWinampApi/1.1/java/com/qotsa/exception/package.html create mode 100644 vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/JNIWinamp.java create mode 100644 vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/WinampController.java create mode 100644 vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/package.html create mode 100644 vendor/commons-logging/1.1.1/commons-logging-1.1.1.jar create mode 100644 vendor/commons-logging/1.1.1/commons-logging-adapters-1.1.1.jar create mode 100644 vendor/commons-logging/1.1.1/commons-logging-api-1.1.1.jar create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/Log.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogConfigurationException.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogFactory.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogSource.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/AvalonLogger.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Jdk14Logger.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Log4JLogger.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/LogFactoryImpl.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/LogKitLogger.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/NoOpLog.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/ServletContextCleaner.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/SimpleLog.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/WeakHashtable.java create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/package.html create mode 100644 vendor/commons-logging/1.1.1/java/org/apache/commons/logging/package.html create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITArtwork.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITArtworkCollection.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITArtworkFormat.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITAudioCDPlaylist.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITBrowserWindow.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITCOMDisabledReason.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITEQPreset.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITFileOrCDTrack.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITLibraryPlaylist.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITObject.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITObjectPersistentID.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITOperationStatus.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITPlayerState.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylist.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistCollection.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistKind.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistPrintKind.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistRepeatMode.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistSearchField.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITRatingKind.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITSource.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITSourceCollection.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITSourceKind.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITTrack.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITTrackCollection.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITTrackKind.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITURLTrack.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITUserPlaylist.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITVideoKind.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITWindow.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/ITWindowCollection.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/iTunes.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/iTunesEvents.java create mode 100644 vendor/iTunesController/0.2/com/dt/iTunesController/iTunesEventsInterface.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXComponent.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXDispatchEvents.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXInvocationProxy.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/ComException.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/ComFailException.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/ComThread.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/Currency.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/DateUtilities.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/Dispatch.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/DispatchEvents.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/DispatchIdentifier.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/DispatchProxy.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/EnumVariant.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/InvocationProxy.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/InvocationProxyAllVariants.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/JacobException.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/JacobObject.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/JacobReleaseInfo.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/LibraryLoader.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/MainSTA.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/NotImplementedException.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/ROT.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/STA.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/SafeArray.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/Variant.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/VariantUtilities.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/VariantViaEvent.java create mode 100644 vendor/jacob/1.15-M4/java/com/jacob/com/WrongThreadException.java create mode 100644 vendor/jdk/1.6.0_23/include/classfile_constants.h create mode 100644 vendor/jdk/1.6.0_23/include/jawt.h create mode 100644 vendor/jdk/1.6.0_23/include/jdwpTransport.h create mode 100644 vendor/jdk/1.6.0_23/include/jni.h create mode 100644 vendor/jdk/1.6.0_23/include/jvmti.h create mode 100644 vendor/jdk/1.6.0_23/include/win32/jawt_md.h create mode 100644 vendor/jdk/1.6.0_23/include/win32/jni_md.h create mode 100644 vendor/jintellitype/1.3.6/cpp/JIntellitype.cpp create mode 100644 vendor/jintellitype/1.3.6/cpp/JIntellitype.dev create mode 100644 vendor/jintellitype/1.3.6/cpp/JIntellitype.layout create mode 100644 vendor/jintellitype/1.3.6/cpp/JIntellitypeHandler.cpp create mode 100644 vendor/jintellitype/1.3.6/cpp/JIntellitypeHandler.h create mode 100644 vendor/jintellitype/1.3.6/cpp/JIntellitypeThread.cpp create mode 100644 vendor/jintellitype/1.3.6/cpp/JIntellitypeThread.h create mode 100644 vendor/jintellitype/1.3.6/cpp/JIntellitype_private.h create mode 100644 vendor/jintellitype/1.3.6/cpp/JIntellitype_private.rc create mode 100644 vendor/jintellitype/1.3.6/cpp/Makefile.win create mode 100644 vendor/jintellitype/1.3.6/cpp/StdAfx.cpp create mode 100644 vendor/jintellitype/1.3.6/cpp/StdAfx.h create mode 100644 vendor/jintellitype/1.3.6/cpp/com_melloware_jintellitype_JIntellitype.h create mode 100644 vendor/jintellitype/1.3.6/java/com/melloware/jintellitype/HotkeyListener.java create mode 100644 vendor/jintellitype/1.3.6/java/com/melloware/jintellitype/IntellitypeListener.java create mode 100644 vendor/jintellitype/1.3.6/java/com/melloware/jintellitype/JIntellitype.java create mode 100644 vendor/jintellitype/1.3.6/java/com/melloware/jintellitype/JIntellitypeConstants.java create mode 100644 vendor/jintellitype/1.3.6/java/com/melloware/jintellitype/JIntellitypeException.java create mode 100644 vendor/jintellitype/1.3.6/java/com/melloware/jintellitype/Main.java create mode 100644 vendor/jlgui/3.0/lib/basicplayer3.0.jar create mode 100644 vendor/jlgui/3.0/lib/commons-logging-api.jar create mode 100644 vendor/jlgui/3.0/lib/jflac-1.2.jar create mode 100644 vendor/jlgui/3.0/lib/jl1.0.jar create mode 100644 vendor/jlgui/3.0/lib/jmactritonusspi1.74.jar create mode 100644 vendor/jlgui/3.0/lib/jogg-0.0.7.jar create mode 100644 vendor/jlgui/3.0/lib/jorbis-0.0.15.jar create mode 100644 vendor/jlgui/3.0/lib/jspeex0.9.7.jar create mode 100644 vendor/jlgui/3.0/lib/kj_dsp1.1.jar create mode 100644 vendor/jlgui/3.0/lib/mp3spi1.9.4.jar create mode 100644 vendor/jlgui/3.0/lib/tritonus_share.jar create mode 100644 vendor/jlgui/3.0/lib/vorbisspi1.0.2.jar create mode 100644 vendor/jlgui/3.0/src/META-INF/services/org.apache.commons.logging.LogFactory create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/basicplayer/BasicController.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/basicplayer/BasicPlayer.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/basicplayer/BasicPlayerEvent.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/basicplayer/BasicPlayerEventLauncher.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/basicplayer/BasicPlayerException.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/basicplayer/BasicPlayerListener.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/Loader.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/PlayerActionEvent.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/PlayerUI.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/StandalonePlayer.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/equalizer/ui/ControlCurve.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/equalizer/ui/Cubic.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/equalizer/ui/EqualizerUI.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/equalizer/ui/NaturalSpline.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/equalizer/ui/SplinePanel.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/jlguiicon.gif create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/metrix.wsz create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/playlist/BasePlaylist.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/playlist/Playlist.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/playlist/PlaylistFactory.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/playlist/PlaylistItem.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/playlist/ui/PlaylistUI.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/AbsoluteConstraints.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/AbsoluteLayout.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ActiveFont.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ActiveJBar.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ActiveJButton.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ActiveJIcon.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ActiveJLabel.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ActiveJNumberLabel.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ActiveJPopup.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ActiveJSlider.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ActiveJToggleButton.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ActiveSliderUI.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/DragAdapter.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/DropTargetAdapter.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/ImageBorder.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/PlaylistUIDelegate.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/PopupAdapter.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/Skin.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/SkinLoader.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/Taftb.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/UrlDialog.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/skin/skin.properties create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/APEInfo.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/FlacInfo.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/MpegInfo.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/OggVorbisInfo.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/TagInfo.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/TagInfoFactory.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/ui/APEDialog.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/ui/EmptyDialog.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/ui/FlacDialog.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/ui/MpegDialog.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/ui/OggVorbisDialog.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/ui/TagInfoDialog.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/ui/TagSearch.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/tag/ui/tag.properties create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/BMPLoader.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/Config.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/FileNameFilter.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/FileSelector.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/FileUtil.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ini/Alphabetizer.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ini/Array.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ini/CRC32OutputStream.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ini/Configuration.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ini/SortedStrings.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/DevicePreference.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/EmptyPreference.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/NodeItem.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/OutputPreference.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/PreferenceItem.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/Preferences.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/SkinPreference.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/SystemPreference.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/TypePreference.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/VisualPreference.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/VisualizationPreference.java create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/device.properties create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/output.properties create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/preferences.properties create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/skin.properties create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/system.properties create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/type.properties create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/visual.properties create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/util/ui/visualization.properties create mode 100644 vendor/jlgui/3.0/src/javazoom/jlgui/player/amp/visual/ui/SpectrumTimeAnalyzer.java create mode 100644 vendor/log4j/1.2.16/log4j-1.2.16.jar create mode 100644 vendor/nativecall/0.4.1/NativeCall.dll create mode 100644 vendor/nativecall/0.4.1/cpp/Debug/IntCall.asm create mode 100644 vendor/nativecall/0.4.1/cpp/Debug/IntCall.obj create mode 100644 vendor/nativecall/0.4.1/cpp/Debug/NativeCall.asm create mode 100644 vendor/nativecall/0.4.1/cpp/Debug/NativeCall.dll create mode 100644 vendor/nativecall/0.4.1/cpp/Debug/NativeCall.obj create mode 100644 vendor/nativecall/0.4.1/cpp/Debug/RCa01372 create mode 100644 vendor/nativecall/0.4.1/cpp/Debug/RCa01444 create mode 100644 vendor/nativecall/0.4.1/cpp/Debug/RCa01468 create mode 100644 vendor/nativecall/0.4.1/cpp/Debug/VoidCall.asm create mode 100644 vendor/nativecall/0.4.1/cpp/Debug/VoidCall.obj create mode 100644 vendor/nativecall/0.4.1/cpp/IntCall.cpp create mode 100644 vendor/nativecall/0.4.1/cpp/NativeCall.cpp create mode 100644 vendor/nativecall/0.4.1/cpp/NativeCall.dsp create mode 100644 vendor/nativecall/0.4.1/cpp/NativeCall.dsw create mode 100644 vendor/nativecall/0.4.1/cpp/Release/IntCall.asm create mode 100644 vendor/nativecall/0.4.1/cpp/Release/IntCall.obj create mode 100644 vendor/nativecall/0.4.1/cpp/Release/NativeCall.asm create mode 100644 vendor/nativecall/0.4.1/cpp/Release/NativeCall.dll create mode 100644 vendor/nativecall/0.4.1/cpp/Release/NativeCall.map create mode 100644 vendor/nativecall/0.4.1/cpp/Release/NativeCall.obj create mode 100644 vendor/nativecall/0.4.1/cpp/Release/RCa01380 create mode 100644 vendor/nativecall/0.4.1/cpp/Release/VoidCall.asm create mode 100644 vendor/nativecall/0.4.1/cpp/Release/VoidCall.obj create mode 100644 vendor/nativecall/0.4.1/cpp/VoidCall.cpp create mode 100644 vendor/nativecall/0.4.1/cpp/com_eaio_nativecall_IntCall.h create mode 100644 vendor/nativecall/0.4.1/cpp/com_eaio_nativecall_NativeCall.h create mode 100644 vendor/nativecall/0.4.1/cpp/com_eaio_nativecall_VoidCall.h create mode 100644 vendor/nativecall/0.4.1/cpp/readme.txt create mode 100644 vendor/nativecall/0.4.1/cpp/resource.h create mode 100644 vendor/nativecall/0.4.1/cpp/version.rc create mode 100644 vendor/nativecall/0.4.1/java/META-INF/services/com.eaio.nativecall.Verifier create mode 100644 vendor/nativecall/0.4.1/java/com/eaio/nativecall/Holder.java create mode 100644 vendor/nativecall/0.4.1/java/com/eaio/nativecall/IntCall.java create mode 100644 vendor/nativecall/0.4.1/java/com/eaio/nativecall/NativeCall.java create mode 100644 vendor/nativecall/0.4.1/java/com/eaio/nativecall/Verifier.java create mode 100644 vendor/nativecall/0.4.1/java/com/eaio/nativecall/Verifiers.java create mode 100644 vendor/nativecall/0.4.1/java/com/eaio/nativecall/VoidCall.java create mode 100644 vendor/nativecall/0.4.1/java/com/eaio/nativecall/Win32Verifier.java create mode 100644 vendor/nativecall/0.4.1/java/com/eaio/nativecall/package.html create mode 100644 vendor/nativecall/0.4.1/nativecall-0.4.1.jar create mode 100644 vendor/nativecall/0.4.1/nativeloader-200505172341.jar create mode 100644 vendor/wiigee/1.5.6/org/wiigee/control/Wiigee.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/control/WiimoteDeviceDiscovery.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/control/WiimoteWiigee.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/device/Device.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/device/Wiimote.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/device/WiimoteStreamer.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/AccelerationEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/AccelerationListener.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/ActionStartEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/ActionStopEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/ButtonListener.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/ButtonPressedEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/ButtonReleasedEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/GestureEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/GestureListener.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/InfraredEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/InfraredListener.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/MotionStartEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/MotionStopEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/RotationEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/RotationListener.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/event/RotationSpeedEvent.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/filter/DirectionalEquivalenceFilter.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/filter/Filter.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/filter/HighPassFilter.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/filter/IdleStateFilter.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/filter/LowPassFilter.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/filter/MotionDetectFilter.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/filter/RotationResetFilter.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/filter/RotationThresholdFilter.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/logic/Classifier.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/logic/Gesture.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/logic/GestureModel.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/logic/HMM.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/logic/PreciseHMM.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/logic/ProcessingUnit.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/logic/Quantizer.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/logic/TriggeredProcessingUnit.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/logic/XHMM.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/util/FileIO.java create mode 100644 vendor/wiigee/1.5.6/org/wiigee/util/Log.java create mode 100644 vendor/wiiscan/0.90/Debug/DelcomDLL.dll create mode 100644 vendor/wiiscan/0.90/Debug/USBm.dll create mode 100644 vendor/wiiscan/0.90/Debug/WiimoteLib.dll create mode 100644 vendor/wiiscan/0.90/Debug/bdi.out create mode 100644 vendor/wiiscan/0.90/Debug/wiimotelibpoll.exe create mode 100644 vendor/wiiscan/0.90/Debug/wiiscan.exe create mode 100644 vendor/wiiscan/0.90/Debug/wiiscan.ini create mode 100644 vendor/wiiscan/0.90/Debug/wiiuse.dll create mode 100644 vendor/wiiscan/0.90/Doc/CHANGEINGBTSTACK.rtf create mode 100644 vendor/wiiscan/0.90/Doc/CHANGELOG.rtf create mode 100644 vendor/wiiscan/0.90/Doc/INSTALL.rtf create mode 100644 vendor/wiiscan/0.90/Doc/LICENSE.rtf create mode 100644 vendor/wiiscan/0.90/Doc/MANUAL_wiiscan.rtf create mode 100644 vendor/wiiscan/0.90/Doc/README.rtf create mode 100644 vendor/wiiscan/0.90/Doc/README_FIRST.rtf create mode 100644 vendor/wiiscan/0.90/Doc/wiiscan.1 create mode 100644 vendor/wiiscan/0.90/Lib/Debug/WiimoteLib.dll create mode 100644 vendor/wiiscan/0.90/Lib/Debug/WiimoteWhiteboard.exe create mode 100644 vendor/wiiscan/0.90/Lib/Debug/wiimotelibpoll.exe create mode 100644 vendor/wiiscan/0.90/Lib/DelcomDLL.dll create mode 100644 vendor/wiiscan/0.90/Lib/DelcomDLL.lib create mode 100644 vendor/wiiscan/0.90/Lib/Release/WiimoteLib.dll create mode 100644 vendor/wiiscan/0.90/Lib/Release/WiimoteWhiteboard.exe create mode 100644 vendor/wiiscan/0.90/Lib/Release/wiimotelibpoll.exe create mode 100644 vendor/wiiscan/0.90/Lib/USBm.dll create mode 100644 vendor/wiiscan/0.90/Lib/wiiuse.dll create mode 100644 vendor/wiiscan/0.90/Lib/wiiuse.lib create mode 100644 vendor/wiiscan/0.90/Release/DelcomDLL.dll create mode 100644 vendor/wiiscan/0.90/Release/USBm.dll create mode 100644 vendor/wiiscan/0.90/Release/WiimoteLib.dll create mode 100644 vendor/wiiscan/0.90/Release/wiimotelibpoll.exe create mode 100644 vendor/wiiscan/0.90/Release/wiiscan.exe create mode 100644 vendor/wiiscan/0.90/Release/wiiscan.ini create mode 100644 vendor/wiiscan/0.90/Release/wiiuse.dll create mode 100644 vendor/wiiscan/0.90/Tools/disable_all_usb.sh create mode 100644 vendor/wiiscan/0.90/Tools/enable_all_usb.sh create mode 100644 vendor/wiiscan/0.90/Tools/no_error_report.reg create mode 100644 vendor/wiiscan/0.90/Tools/popup_disable.reg create mode 100644 vendor/wiiscan/0.90/Tools/popup_enable.reg create mode 100644 vendor/wiiscan/0.90/Tools/wiitest.sh create mode 100644 vendor/wiiscan/0.90/src/DelcomDLL.h create mode 100644 vendor/wiiscan/0.90/src/args.h create mode 100644 vendor/wiiscan/0.90/src/configfile.h create mode 100644 vendor/wiiscan/0.90/src/exception.h create mode 100644 vendor/wiiscan/0.90/src/file.h create mode 100644 vendor/wiiscan/0.90/src/funs.h create mode 100644 vendor/wiiscan/0.90/src/process.h create mode 100644 vendor/wiiscan/0.90/src/reg.h create mode 100644 vendor/wiiscan/0.90/src/stringfun.h create mode 100644 vendor/wiiscan/0.90/src/templatefun.h create mode 100644 vendor/wiiscan/0.90/src/toolsfun.h create mode 100644 vendor/wiiscan/0.90/src/usbm.h create mode 100644 vendor/wiiscan/0.90/src/wiiscan.cpp create mode 100644 vendor/wiiscan/0.90/src/wiiscan.h create mode 100644 vendor/wiiscan/0.90/src/wiiuse.h create mode 100644 vendor/wiiscan/0.90/wiiscan.sln create mode 100644 vendor/wiiscan/0.90/wiiscan.test.h create mode 100644 vendor/wiiscan/0.90/wiiscan.vcproj create mode 100644 vendor/wiiuse/0.12/classic.c create mode 100644 vendor/wiiuse/0.12/classic.h create mode 100644 vendor/wiiuse/0.12/definitions.h create mode 100644 vendor/wiiuse/0.12/dynamics.c create mode 100644 vendor/wiiuse/0.12/dynamics.h create mode 100644 vendor/wiiuse/0.12/events.c create mode 100644 vendor/wiiuse/0.12/events.h create mode 100644 vendor/wiiuse/0.12/guitar_hero_3.c create mode 100644 vendor/wiiuse/0.12/guitar_hero_3.h create mode 100644 vendor/wiiuse/0.12/io.c create mode 100644 vendor/wiiuse/0.12/io.h create mode 100644 vendor/wiiuse/0.12/io_nix.c create mode 100644 vendor/wiiuse/0.12/io_win.c create mode 100644 vendor/wiiuse/0.12/ir.c create mode 100644 vendor/wiiuse/0.12/ir.h create mode 100644 vendor/wiiuse/0.12/nunchuk.c create mode 100644 vendor/wiiuse/0.12/nunchuk.h create mode 100644 vendor/wiiuse/0.12/os.h create mode 100644 vendor/wiiuse/0.12/wiiuse.c create mode 100644 vendor/wiiuse/0.12/wiiuse.h create mode 100644 vendor/wiiuse/0.12/wiiuse_internal.h create mode 100644 vendor/wiiusej/0.12b/c/wiiusej_WiiUseApi.c create mode 100644 vendor/wiiusej/0.12b/c/wiiusej_WiiUseApi.def create mode 100644 vendor/wiiusej/0.12b/c/wiiusej_WiiUseApi.h create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/WiiUseApi.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/WiiUseApiManager.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/Wiimote.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/test/ClassicControllerGuiTest.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/test/CloseGuiTestCleanly.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/test/GuitarHero3GuiTest.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/test/Main.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/test/NunchukGuiTest.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/test/Tests.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/test/WiiuseJGuiTest.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/AccelerationExpansionEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/AccelerationPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/AccelerationWiimoteEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/ButtonsEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/ClassicControllerButtonsEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/GForceExpansionEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/GForcePanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/GForceWiimoteEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/GuitarHero3ButtonsEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/GuitarHeroJoystickEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/IRPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/JoystickEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/NunchukJoystickEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/OrientationExpansionEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/OrientationPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/utils/OrientationWiimoteEventPanel.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/values/GForce.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/values/IRSource.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/values/Orientation.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/values/RawAcceleration.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/GenericEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/ButtonsEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/ClassicControllerButtonsEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/ClassicControllerEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/ExpansionEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/GuitarHeroButtonsEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/GuitarHeroEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/IREvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/JoystickEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/MotionSensingEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/NunchukButtonsEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/NunchukEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/physicalevents/WiimoteButtonsEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/utils/EventsGatherer.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/utils/WiiUseApiListener.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/utils/WiimoteListener.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/wiiuseapievents/ClassicControllerInsertedEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/wiiuseapievents/ClassicControllerRemovedEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/wiiuseapievents/DisconnectionEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/wiiuseapievents/GuitarHeroInsertedEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/wiiuseapievents/GuitarHeroRemovedEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/wiiuseapievents/NunchukInsertedEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/wiiuseapievents/NunchukRemovedEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/wiiuseapievents/StatusEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/wiiuseapievents/WiiUseApiEvent.java create mode 100644 vendor/wiiusej/0.12b/java/wiiusej/wiiusejevents/wiiuseapievents/WiimoteEvent.java diff --git a/vendor/JXInput/0.3.4/c/JXInputManager.cpp b/vendor/JXInput/0.3.4/c/JXInputManager.cpp new file mode 100644 index 0000000..3718a7f --- /dev/null +++ b/vendor/JXInput/0.3.4/c/JXInputManager.cpp @@ -0,0 +1,175 @@ + +#include "stdafx.h" +#include "JXInputManager.h" +#include "JXInput.h" + +// +// Globals +// +extern HINSTANCE g_hInst; + + +JXInputManager::JXInputManager( HWND hWnd ) : +mhWnd( hWnd ), +mDeviceCounter( 0 ) +{ + + for ( int i = 0; i < MAX_JXINPUTS; ++i ) + { + mDevices[ i ] = NULL; + } + + + if ( FAILED( InitDirectInput( hWnd ) ) ) + { + FreeDirectInput(); + } + +} + +JXInputManager::~JXInputManager() +{ + for ( int i = 0; i < getNumberOfJXInputs(); ++i ) + { + delete mDevices[ i ]; + mDevices[ i ] = NULL; + } + + FreeDirectInput(); +} + +int JXInputManager::getNumberOfJXInputs() const +{ + return mDeviceCounter; +} + +JXInput& JXInputManager::getJXInput( int idx ) const +{ + assert( idx < mDeviceCounter ); + return * mDevices[ idx ]; +} + + +int JXInputManager::getMaxNumberOfAxes() const +{ + return JXINPUT_MAX_AXES; +} + +int JXInputManager::getMaxNumberOfButtons() const +{ + return JXINPUT_MAX_BUTTONS; +} + +int JXInputManager::getMaxNumberOfDirectionals() const +{ + return JXINPUT_MAX_DIRECTIONALS; +} + + + +//----------------------------------------------------------------------------- +// Name: InitDirectInput() +// Desc: Initialize the DirectInput variables. +//----------------------------------------------------------------------------- +HRESULT JXInputManager::InitDirectInput( HWND hWnd ) +{ + HRESULT hr; + + // Register with the DirectInput subsystem and get a pointer + // to a IDirectInput interface we can use. + // Create a DInput object + if( FAILED( hr = DirectInput8Create( g_hInst, DIRECTINPUT_VERSION, + IID_IDirectInput8, (VOID**)&mpDI, NULL ) ) ) + return hr; + + // Look for a simple joystick we can use for this sample program. + if( FAILED( hr = mpDI->EnumDevices( DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + (VOID*)this, DIEDFL_ALLDEVICES /*| DIEDFL_INCLUDEPHANTOMS*/ ) ) ) + return hr; + + // Look for a other devices + if( FAILED( hr = mpDI->EnumDevices( DI8DEVCLASS_DEVICE, + EnumJoysticksCallback, + (VOID*)this, DIEDFL_ALLDEVICES /*| DIEDFL_INCLUDEPHANTOMS*/ ) ) ) + return hr; + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: FreeDirectInput() +// Desc: Initialize the DirectInput variables. +//----------------------------------------------------------------------------- +HRESULT JXInputManager::FreeDirectInput() +{ + + if ( NULL != mpDI ) + mpDI->Release(); + mpDI = NULL; + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: EnumJoysticksCallback() +// Desc: Called once for each enumerated joystick. If we find one, create a +// device interface on it so we can play with it. +//----------------------------------------------------------------------------- +BOOL CALLBACK JXInputManager::EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, + VOID* pContext ) +{ + HRESULT hr; + LPDIRECTINPUTDEVICE8 pJoystick; + + JXInputManager* pThis = (JXInputManager*)pContext; + + // + // if the maximum number of devices is already registered, + // issue a warning and stop enumeration. + // + if( MAX_JXINPUTS == pThis->mDeviceCounter ) + { + OutputDebugString( "Max. number of devices exceeded!" ); + return DIENUM_STOP; + } + + + + // Obtain an interface to the enumerated joystick. + hr = pThis->mpDI->CreateDevice( pdidInstance->guidInstance, &pJoystick, NULL ); + + // If it failed, then we can't use this joystick. (Maybe the user unplugged + // it while we were in the middle of enumerating it.) + if( FAILED(hr) ) + return DIENUM_CONTINUE; + + JXInput* pJ = new JXInput( pJoystick, pThis->mhWnd ); + + // + // only register useful devices + // + if( pJ->getNumberOfAxes() + pJ->getNumberOfButtons() + pJ->getNumberOfDirectionals() > 0 ) + { + pThis->addJXInput( pJ ); + } + else + { + delete pJ; + } + + return DIENUM_CONTINUE; +} + + +/** + * Register a JXInput device. + */ +void JXInputManager::addJXInput( JXInput* pJ ) +{ + assert( mDeviceCounter < MAX_JXINPUTS ); + + if( mDeviceCounter < MAX_JXINPUTS ) + mDevices[ mDeviceCounter++ ] = pJ; +} diff --git a/vendor/JXInput/0.3.4/c/JXInputManager.h b/vendor/JXInput/0.3.4/c/JXInputManager.h new file mode 100644 index 0000000..41b9da4 --- /dev/null +++ b/vendor/JXInput/0.3.4/c/JXInputManager.h @@ -0,0 +1,47 @@ +// JXInputManager.h: Schnittstelle für die Klasse JXInputManager. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_JXINPUTMANAGER_H__24862402_14C9_407D_8532_A16A6E3A7D64__INCLUDED_) +#define AFX_JXINPUTMANAGER_H__24862402_14C9_407D_8532_A16A6E3A7D64__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +#define MAX_JXINPUTS 10 + +class JXInput; + +class JXINPUT_API JXInputManager +{ +public: + JXInputManager( HWND hWnd ); + virtual ~JXInputManager(); + + int getNumberOfJXInputs() const; + JXInput& getJXInput( int idx ) const; + + // + // Numbering methods + // + int getMaxNumberOfAxes() const; + int getMaxNumberOfButtons() const; + int getMaxNumberOfDirectionals() const; + +private: + LPDIRECTINPUT8 mpDI; + HWND mhWnd; + JXInput* mDevices[ MAX_JXINPUTS ]; + int mDeviceCounter; + + HRESULT InitDirectInput( HWND hWnd = NULL ); + HRESULT FreeDirectInput(); + + static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, + VOID* pContext ); + void addJXInput( JXInput* pJ ); +}; + +#endif // !defined(AFX_JXINPUTMANAGER_H__24862402_14C9_407D_8532_A16A6E3A7D64__INCLUDED_) diff --git a/vendor/JXInput/0.3.4/c/ReadMe.txt b/vendor/JXInput/0.3.4/c/ReadMe.txt new file mode 100644 index 0000000..755cd4c --- /dev/null +++ b/vendor/JXInput/0.3.4/c/ReadMe.txt @@ -0,0 +1,37 @@ +======================================================================== + DYNAMIC LINK LIBRARY : jxinput +======================================================================== + + +Diese jxinput-DLL hat der Anwendungs-Assistent für Sie erstellt. + +Diese Datei enthält eine Zusammenfassung dessen, was Sie in jeder der Dateien +finden, die Ihre jxinput-Anwendung bilden. + +jxinput.dsp + Diese Datei (Projektdatei) enthält Informationen auf Projektebene und wird zur + Erstellung eines einzelnen Projekts oder Teilprojekts verwendet. Andere Benutzer können + die Projektdatei (.dsp) gemeinsam nutzen, sollten aber die Makefiles lokal exportieren. + +jxinput.cpp + Dies ist die Hauptquellcodedatei für die DLL. + +jxinput.h + Diese Datei enthält Ihre DLL-Exporte. + +///////////////////////////////////////////////////////////////////////////// +Weitere Standarddateien: + +StdAfx.h, StdAfx.cpp + Diese Dateien werden zum Erstellen einer vorkompilierten Header-Datei (PCH) namens + jxinput.pch und einer vorkompilierten Typdatei namens StdAfx.obj verwendet. + + +///////////////////////////////////////////////////////////////////////////// +Weitere Hinweise: + +Der Anwendungs-Assistent verwendet "ZU ERLEDIGEN:", um Bereiche des Quellcodes zu +kennzeichnen, die Sie hinzufügen oder anpassen sollten. + + +///////////////////////////////////////////////////////////////////////////// diff --git a/vendor/JXInput/0.3.4/c/StdAfx.cpp b/vendor/JXInput/0.3.4/c/StdAfx.cpp new file mode 100644 index 0000000..a144a09 --- /dev/null +++ b/vendor/JXInput/0.3.4/c/StdAfx.cpp @@ -0,0 +1,9 @@ +// stdafx.cpp : Quelltextdatei, die nur die Standard-Includes einbindet +// jxinput.pch ist die vorkompilierte Header-Datei +// stdafx.obj enthält die vorkompilierte Typinformation + +#include "stdafx.h" + +// ZU ERLEDIGEN: Verweis auf alle zusätzlichen Header-Dateien, die Sie in STDAFX.H +// und nicht in dieser Datei benötigen + diff --git a/vendor/JXInput/0.3.4/c/StdAfx.h b/vendor/JXInput/0.3.4/c/StdAfx.h new file mode 100644 index 0000000..e139c4c --- /dev/null +++ b/vendor/JXInput/0.3.4/c/StdAfx.h @@ -0,0 +1,32 @@ +// stdafx.h : Include-Datei für Standard-System-Include-Dateien, +// oder projektspezifische Include-Dateien, die häufig benutzt, aber +// in unregelmäßigen Abständen geändert werden. +// + +#if !defined(AFX_STDAFX_H__68E14C76_098F_47ED_932B_4C01E8E9EFFB__INCLUDED_) +#define AFX_STDAFX_H__68E14C76_098F_47ED_932B_4C01E8E9EFFB__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// Fügen Sie hier Ihre Header-Dateien ein +#define WIN32_LEAN_AND_MEAN // Selten benutzte Teile der Windows-Header nicht einbinden +#define STRICT +#include + +// ZU ERLEDIGEN: Verweisen Sie hier auf zusätzliche Header-Dateien, die Ihr Programm benötigt +#ifdef JXINPUT_EXPORTS +#define JXINPUT_API __declspec(dllexport) +#else +#define JXINPUT_API __declspec(dllimport) +#endif + +#include +#include + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fügt zusätzliche Deklarationen unmittelbar vor der vorherigen Zeile ein. + +#endif // !defined(AFX_STDAFX_H__68E14C76_098F_47ED_932B_4C01E8E9EFFB__INCLUDED_) diff --git a/vendor/JXInput/0.3.4/c/de_hardcode_jxinput_directinput_DirectInputDriver.cpp b/vendor/JXInput/0.3.4/c/de_hardcode_jxinput_directinput_DirectInputDriver.cpp new file mode 100644 index 0000000..077afe8 --- /dev/null +++ b/vendor/JXInput/0.3.4/c/de_hardcode_jxinput_directinput_DirectInputDriver.cpp @@ -0,0 +1,279 @@ +#include "stdafx.h" + +#include "de_hardcode_jxinput_directinput_DirectInputDriver.h" +#include "jxinput.h" +#include "JXInputManager.h" + + +// +// Globals +// +extern HINSTANCE g_hInst; + +static JXInputManager* pJXInputManager = NULL; +static JXInput* apJXInput[ MAX_JXINPUTS ]; +static HWND hWndJava; + +// +// IDs of the static Java arrays. +// +static jfieldID sAxesFieldID; +static jfieldID sButtonsFieldID; +static jfieldID sDirectionsFieldID; + + + +/** + * Remove all resources allocated by the Java binding. + */ +void shutdownJavaResources() +{ + if ( NULL != pJXInputManager ) + delete pJXInputManager; + + if ( NULL != hWndJava ) + DestroyWindow( hWndJava ); + + pJXInputManager = NULL; + + for( int i = 0; i < MAX_JXINPUTS; ++i ) + apJXInput[ i ] = NULL; + + hWndJava = NULL; +} + + + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) +{ + return JNI_VERSION_1_2; +} + + +JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) +{ + shutdownJavaResources(); +} + + +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeinit + (JNIEnv * penv, jclass pClazz ) +{ + + // + // Create a non-visible window as 'owner' of the DI device. + // + hWndJava = CreateWindowEx( + 0/*WS_EX_APPWINDOW*/, // DWORD dwExStyle, // extended window style + "STATIC", // LPCTSTR lpClassName, // pointer to registered class name + NULL, // LPCTSTR lpWindowName, // pointer to window name + 0/*WS_CAPTION*/, // DWORD dwStyle, // window style + 0, // int x, // horizontal position of window + 0, // int y, // vertical position of window + 0, // int nWidth, // window width + 0, // int nHeight, // window height + NULL, // HWND hWndParent, // handle to parent or owner window + NULL, // HMENU hMenu, // handle to menu, or child-window identifier + g_hInst, // HINSTANCE hInstance, // handle to application instance + NULL // LPVOID lpParam // pointer to window-creation data + ); + + + if ( NULL == pJXInputManager ) + { + pJXInputManager = new JXInputManager( hWndJava ); + + for( int i = 0; i < MAX_JXINPUTS; ++i ) + apJXInput[ i ] = NULL; + + for ( int i = 0; i < pJXInputManager->getNumberOfJXInputs(); ++i ) + { + apJXInput[ i ] = & pJXInputManager->getJXInput( i ); + } + } + + return true; +} + + + +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeexit + (JNIEnv *, jclass ) +{ + shutdownJavaResources(); +} + + +/** + * Bind my field IDs to the Java variables. + */ +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_bind + (JNIEnv * penv, jclass pClazz) +{ + // + // All fields are static. + // + sAxesFieldID = penv->GetStaticFieldID( pClazz, "sAxisValues", "[[D" ); + sButtonsFieldID = penv->GetStaticFieldID( pClazz, "sButtonStates", "[[Z" ); + sDirectionsFieldID = penv->GetStaticFieldID( pClazz, "sDirectionalValues", "[[I" ); +} + + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfDevices + (JNIEnv *penv, jclass) +{ + return pJXInputManager->getNumberOfJXInputs(); +} + + +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getName + (JNIEnv *penv, jclass, jint dev) +{ + return penv->NewStringUTF( apJXInput[ dev ]->getName() ); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfAxes + (JNIEnv *, jclass, jint dev) +{ + return apJXInput[ dev ]->getNumberOfAxes(); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfButtons + (JNIEnv *, jclass, jint dev) +{ + return apJXInput[ dev ]->getNumberOfButtons(); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfDirectionals + (JNIEnv *, jclass, jint dev) +{ + return apJXInput[ dev ]->getNumberOfDirectionals(); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfAxes + (JNIEnv *, jclass) +{ + return pJXInputManager->getMaxNumberOfAxes(); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfButtons + (JNIEnv *, jclass) +{ + return pJXInputManager->getMaxNumberOfButtons(); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfDirectionals + (JNIEnv *, jclass) +{ + return pJXInputManager->getMaxNumberOfDirectionals(); +} + +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isAxisAvailable + (JNIEnv *, jclass, jint dev, jint idx ) +{ + return apJXInput[ dev ]->isAxisAvailable( idx ); +} + +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getAxisName + (JNIEnv *penv, jclass, jint dev, jint idx ) +{ + return penv->NewStringUTF( apJXInput[ dev ]->getAxisName( idx ) ); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getAxisType + (JNIEnv *, jclass, jint dev, jint idx ) +{ + return apJXInput[ dev ]->getAxisType( idx ); +} + + +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isButtonAvailable + (JNIEnv *, jclass, jint dev, jint idx ) +{ + return apJXInput[ dev ]->isButtonAvailable( idx ); +} + +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getButtonName + (JNIEnv *penv, jclass, jint dev, jint idx ) +{ + return penv->NewStringUTF( apJXInput[ dev ]->getButtonName( idx ) ); +} + +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getButtonType + (JNIEnv *, jclass, jint dev, jint idx ) +{ + return apJXInput[ dev ]->getButtonType( idx ); +} + +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isDirectionalAvailable + (JNIEnv *, jclass, jint dev, jint idx ) +{ + return apJXInput[ dev ]->isDirectionalAvailable( idx ); +} + +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getDirectionalName + (JNIEnv *penv, jclass, jint dev, jint idx ) +{ + return penv->NewStringUTF( apJXInput[ dev ]->getDirectionalName( idx ) ); +} + + + +/** + * The main update method. + * Here, the actual work is done. + */ +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeupdate + (JNIEnv * penv, jclass pClazz ) +{ + + static jdouble axes [ MAX_JXINPUTS ][ JXINPUT_MAX_AXES ]; + static jboolean buttons [ MAX_JXINPUTS ][ JXINPUT_MAX_BUTTONS ]; + static jint directions [ MAX_JXINPUTS ][ JXINPUT_MAX_DIRECTIONALS ]; + + static jobjectArray axisarrayarray; + static jobjectArray buttonarrayarray; + static jobjectArray directionarrayarray; + + static jdoubleArray axisarray; + static jbooleanArray buttonarray; + static jintArray directionarray; + + axisarrayarray = (jobjectArray)penv->GetStaticObjectField( pClazz, sAxesFieldID ); + buttonarrayarray = (jobjectArray)penv->GetStaticObjectField( pClazz, sButtonsFieldID ); + directionarrayarray = (jobjectArray)penv->GetStaticObjectField( pClazz, sDirectionsFieldID ); + + // + // For each device.... + // + for ( int dev = 0; dev < pJXInputManager->getNumberOfJXInputs(); ++dev ) + { + // Do the update of the device. + apJXInput[ dev ]->update(); + + // + // Copy all values into my arrays. + // + for ( int i = 0; i < JXINPUT_MAX_AXES; ++i ) + axes[ dev ][ i ] = apJXInput[ dev ]->getAxisValue( i ); + for ( int i = 0; i < JXINPUT_MAX_BUTTONS; ++i ) + buttons[ dev ][ i ] = apJXInput[ dev ]->isButtonDown( i ); + for ( int i = 0; i < JXINPUT_MAX_DIRECTIONALS; ++i ) + directions[ dev ][ i ] = apJXInput[ dev ]->getDirection( i ); + + + // + // Move my arrays to the Java arrays. + // + axisarray = (jdoubleArray)penv->GetObjectArrayElement( axisarrayarray, dev ); + penv->SetDoubleArrayRegion( axisarray, 0, JXINPUT_MAX_AXES, axes[ dev ] ); + + buttonarray = (jbooleanArray)penv->GetObjectArrayElement( buttonarrayarray, dev ); + penv->SetBooleanArrayRegion( buttonarray, 0, JXINPUT_MAX_BUTTONS, buttons[ dev ] ); + + directionarray = (jintArray)penv->GetObjectArrayElement( directionarrayarray, dev ); + penv->SetIntArrayRegion( directionarray, 0, JXINPUT_MAX_DIRECTIONALS, directions[ dev ] ); + } + +} + diff --git a/vendor/JXInput/0.3.4/c/de_hardcode_jxinput_directinput_DirectInputDriver.h b/vendor/JXInput/0.3.4/c/de_hardcode_jxinput_directinput_DirectInputDriver.h new file mode 100644 index 0000000..bb93548 --- /dev/null +++ b/vendor/JXInput/0.3.4/c/de_hardcode_jxinput_directinput_DirectInputDriver.h @@ -0,0 +1,183 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include + +/* Header for class de_hardcode_jxinput_directinput_DirectInputDriver */ + +#ifndef _Included_de_hardcode_jxinput_directinput_DirectInputDriver +#define _Included_de_hardcode_jxinput_directinput_DirectInputDriver + +#ifdef __cplusplus +extern "C" { +#endif + +/* Inaccessible static: sIsOperational */ +/* Inaccessible static: sAxisValues */ +/* Inaccessible static: sButtonStates */ +/* Inaccessible static: sDirectionalValues */ +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: nativeinit + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeinit + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: nativeexit + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeexit + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: bind + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_bind + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getNumberOfDevices + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfDevices + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getName + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getName + (JNIEnv *, jclass, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getNumberOfAxes + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfAxes + + (JNIEnv *, jclass, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getNumberOfButtons + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfButtons + (JNIEnv *, jclass, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getNumberOfDirectionals + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getNumberOfDirectionals + (JNIEnv *, jclass, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getMaxNumberOfAxes + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfAxes + (JNIEnv *, jclass); + + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getMaxNumberOfButtons + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfButtons + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getMaxNumberOfDirectionals + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getMaxNumberOfDirectionals + (JNIEnv *, jclass); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: isAxisAvailable + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isAxisAvailable + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getAxisName + * Signature: (II)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getAxisName + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getAxisType + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getAxisType + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: isButtonAvailable + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isButtonAvailable + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getButtonName + * Signature: (II)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getButtonName + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getButtonType + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getButtonType + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: isDirectionalAvailable + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_isDirectionalAvailable + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: getDirectionalName + * Signature: (II)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_getDirectionalName + (JNIEnv *, jclass, jint, jint); + +/* + * Class: de_hardcode_jxinput_directinput_DirectInputDriver + * Method: nativeupdate + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_de_hardcode_jxinput_directinput_DirectInputDriver_nativeupdate + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/vendor/JXInput/0.3.4/c/dllmain.cpp b/vendor/JXInput/0.3.4/c/dllmain.cpp new file mode 100644 index 0000000..567e8d4 --- /dev/null +++ b/vendor/JXInput/0.3.4/c/dllmain.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" + +HINSTANCE g_hInst; + + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + g_hInst = (HINSTANCE)hModule; + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + g_hInst = NULL; + break; + } + return TRUE; +} diff --git a/vendor/JXInput/0.3.4/c/jxinput.cpp b/vendor/JXInput/0.3.4/c/jxinput.cpp new file mode 100644 index 0000000..890805b --- /dev/null +++ b/vendor/JXInput/0.3.4/c/jxinput.cpp @@ -0,0 +1,600 @@ +// +// jxinput.cpp +// +#include "stdafx.h" +#include "jxinput.h" + + +// +// Globals +// +extern HINSTANCE g_hInst; + + +/** + * Ctor: Connect with DI + */ +JXInput::JXInput( LPDIRECTINPUTDEVICE8 pJoystick, HWND hWnd ) : + mpJoystick( pJoystick ), + mSliderCount( 0 ), + mPOVCount( 0 ), + mButtonCount( 0 ) +{ + initAxisConfig(); + initButtonsConfig(); + initDirectionalsConfig(); + + if ( FAILED( InitDirectInput( hWnd ) ) ) + { + FreeDirectInput(); + } +} + + + +/** + * Destructor: + * Free DirectInput. + */ +JXInput::~JXInput() +{ + FreeDirectInput(); +} + + +void JXInput::update() +{ + UpdateInputState(); +} + + +TCHAR * const JXInput::getName() const +{ + return (TCHAR*)mdiDevInfo.tszInstanceName; +} + + + +int JXInput::getNumberOfAxes() const +{ + return mdiDevCaps.dwAxes; +} + +int JXInput::getNumberOfButtons() const +{ + return mButtonCount; +} + +int JXInput::getNumberOfDirectionals() const +{ + return mPOVCount; +} + + +double JXInput::getAxisValueHelper( LONG val, int idx ) const +{ + const AxisConfig& cfg = mAxisConfig[ idx ]; + + double span = (double)( cfg.mMaxValue - cfg.mMinValue ); + double ret = (double)(val - cfg.mMinValue) / span; + + if ( TYPE_SLIDER != cfg.mType ) + return ret*2.0 - 1.0; + return ret; +} + +double JXInput::getX() const +{ + return getAxisValueHelper( mJS.lX, ID_X ); +} +double JXInput::getY() const +{ + return getAxisValueHelper( mJS.lY, ID_Y ); +} +double JXInput::getZ() const +{ + return getAxisValueHelper( mJS.lZ, ID_Z ); +} +double JXInput::getRotX() const +{ + return getAxisValueHelper( mJS.lRx, ID_ROTX ); +} +double JXInput::getRotY() const +{ + return getAxisValueHelper( mJS.lRy, ID_ROTY ); +} +double JXInput::getRotZ() const +{ + return getAxisValueHelper( mJS.lRz, ID_ROTZ ); +} +double JXInput::getSlider0() const +{ + return getAxisValueHelper( mJS.rglSlider[ 0 ], ID_SLIDER0 ); +} +double JXInput::getSlider1() const +{ + return getAxisValueHelper( mJS.rglSlider[ 1 ], ID_SLIDER1 ); +} + + + +bool JXInput::isAxisAvailable( int idx ) const +{ + assert( idx < JXINPUT_MAX_AXES ); + return mAxisConfig[ idx ].mIsAvailable; +} + +TCHAR * const JXInput::getAxisName( int idx ) const +{ + assert( idx < JXINPUT_MAX_AXES ); + return (char*const)mAxisConfig[ idx ].mName; +} + +int JXInput::getAxisType( int idx ) const +{ + assert( idx < JXINPUT_MAX_AXES ); + return mAxisConfig[ idx ].mType; +} + +double JXInput::getAxisValue( int idx ) const +{ + assert( idx < JXINPUT_MAX_AXES ); + + // Failsafe if called accidentally + if ( ! mAxisConfig[ idx ].mIsAvailable ) + return 0.0; + + return (this->*mAxisConfig[ idx ].mGetValueMethod)(); +} + + + + + +bool JXInput::isButtonAvailable( int idx ) const +{ + assert( idx < JXINPUT_MAX_BUTTONS ); + return mButtonConfig[ idx ].mIsAvailable; +} + +TCHAR * const JXInput::getButtonName( int idx ) const +{ + assert( idx < JXINPUT_MAX_BUTTONS ); + return (char*const)mButtonConfig[ idx ].mName; +} + +int JXInput::getButtonType( int idx ) const +{ + assert( idx < JXINPUT_MAX_BUTTONS ); + return mButtonConfig[ idx ].mType; +} + +bool JXInput::isButtonDown( int idx ) const +{ + assert( idx < JXINPUT_MAX_BUTTONS ); + return 0 != mJS.rgbButtons[ idx ] ; +} + + +bool JXInput::isDirectionalAvailable( int idx ) const +{ + assert( idx < JXINPUT_MAX_DIRECTIONALS ); + return mDirectionalConfig[ idx ].mIsAvailable; +} + +TCHAR * const JXInput::getDirectionalName( int idx ) const +{ + assert( idx < JXINPUT_MAX_DIRECTIONALS ); + return (char*const)mDirectionalConfig[ idx ].mName; +} + +int JXInput::getDirection( int idx ) const +{ + assert( idx < JXINPUT_MAX_DIRECTIONALS ); + return mJS.rgdwPOV[ idx ] ; +} + + +/** + * Initialize axis configuration array. + */ +void JXInput::initAxisConfig() +{ + mAxisConfig[ ID_X ].mIsAvailable = false; + mAxisConfig[ ID_X ].mType = TYPE_TRANSLATION; + mAxisConfig[ ID_X ].mGetValueMethod = &JXInput::getX; + + mAxisConfig[ ID_Y ].mIsAvailable = false; + mAxisConfig[ ID_Y ].mType = TYPE_TRANSLATION; + mAxisConfig[ ID_Y ].mGetValueMethod = &JXInput::getY; + + mAxisConfig[ ID_Z ].mIsAvailable = false; + mAxisConfig[ ID_Z ].mType = TYPE_TRANSLATION; + mAxisConfig[ ID_Z ].mGetValueMethod = &JXInput::getZ; + + mAxisConfig[ ID_ROTX ].mIsAvailable = false; + mAxisConfig[ ID_ROTX ].mType = TYPE_ROTATION; + mAxisConfig[ ID_ROTX ].mGetValueMethod = &JXInput::getRotX; + + mAxisConfig[ ID_ROTY ].mIsAvailable = false; + mAxisConfig[ ID_ROTY ].mType = TYPE_ROTATION; + mAxisConfig[ ID_ROTY ].mGetValueMethod = &JXInput::getRotY; + + mAxisConfig[ ID_ROTZ ].mIsAvailable = false; + mAxisConfig[ ID_ROTZ ].mType = TYPE_ROTATION; + mAxisConfig[ ID_ROTZ ].mGetValueMethod = &JXInput::getRotZ; + + mAxisConfig[ ID_SLIDER0 ].mIsAvailable = false; + mAxisConfig[ ID_SLIDER0 ].mType = TYPE_SLIDER; + mAxisConfig[ ID_SLIDER0 ].mGetValueMethod = &JXInput::getSlider0; + + mAxisConfig[ ID_SLIDER1 ].mIsAvailable = false; + mAxisConfig[ ID_SLIDER1 ].mType = TYPE_SLIDER; + mAxisConfig[ ID_SLIDER1 ].mGetValueMethod = &JXInput::getSlider1; +} + + +/** + * Initialize buttons configuration array. + */ +void JXInput::initButtonsConfig() +{ + for ( int i = 0; i < JXINPUT_MAX_BUTTONS; ++i ) + { + mButtonConfig[ i ].mIsAvailable = false; + mButtonConfig[ i ].mName[ 0 ] = '\0'; + mButtonConfig[ i ].mType = TYPE_PUSHBUTTON; + } + +} + + +/** + * Initialize directionals configuration array. + */ +void JXInput::initDirectionalsConfig() +{ + for ( int i = 0; i < JXINPUT_MAX_DIRECTIONALS; ++i ) + { + mDirectionalConfig[ i ].mIsAvailable = false; + mDirectionalConfig[ i ].mName[ 0 ] = '\0'; + } + +} + + + +//----------------------------------------------------------------------------- +// Name: EnumAxesCallback() +// Desc: Callback function for enumerating the axes on a joystick +//----------------------------------------------------------------------------- +BOOL CALLBACK JXInput::EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + JXInput* pThis = (JXInput*)pContext; + + AxisConfig* pAxCfg = NULL; + + // Set the UI to reflect what objects the joystick supports + // Code derived from M$ samples, really sucks, eh? + if (pdidoi->guidType == GUID_XAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_X ]; + } + if (pdidoi->guidType == GUID_YAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_Y ]; + } + if (pdidoi->guidType == GUID_ZAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_Z ]; + } + if (pdidoi->guidType == GUID_RxAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_ROTX ]; + } + if (pdidoi->guidType == GUID_RyAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_ROTY ]; + } + if (pdidoi->guidType == GUID_RzAxis) + { + pAxCfg = & pThis->mAxisConfig[ ID_ROTZ ]; + } + if (pdidoi->guidType == GUID_Slider) + { + switch( pThis->mSliderCount++ ) + { + case 0 : + pAxCfg = & pThis->mAxisConfig[ ID_SLIDER0 ]; + break; + + case 1 : + pAxCfg = & pThis->mAxisConfig[ ID_SLIDER1 ]; + break; + } + } + + // fail-safe + if( NULL == pAxCfg ) // e.g. GUID_Unknown + return DIENUM_CONTINUE; + + + // + // Perform config. + // + + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis + + // Get the range for the axis + if( FAILED( pThis->mpJoystick->GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) + return DIENUM_CONTINUE; + + pAxCfg->mMinValue = diprg.lMin; + pAxCfg->mMaxValue = diprg.lMax; + + strcpy( (char*)pAxCfg->mName, (char*)pdidoi->tszName ); + pAxCfg->mIsAvailable = true; + + return DIENUM_CONTINUE; +} + + + +//----------------------------------------------------------------------------- +// Name: EnumButtonsCallback() +// Desc: Callback function for enumerating the axes on a joystick +//----------------------------------------------------------------------------- +BOOL CALLBACK JXInput::EnumButtonsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + JXInput* pThis = (JXInput*)pContext; + + // + // if the maximum number of buttons is already registered, + // issue a warning and stop enumeration. + // + if( JXINPUT_MAX_BUTTONS == pThis->mButtonCount ) + { + OutputDebugString( "Max. number of buttons exceeded!" ); + return DIENUM_STOP; + } + + + ButtonConfig* pBtCfg = NULL; + + if ( pdidoi->guidType == GUID_Button ) + { + assert( JXINPUT_MAX_BUTTONS > pThis->mButtonCount ); + pBtCfg = & pThis->mButtonConfig[ pThis->mButtonCount++ ]; + } + + + // fail-safe + if( NULL == pBtCfg ) // e.g. unknown stuff + return DIENUM_CONTINUE; + assert( NULL != pBtCfg ); + + // + // Perform config. + // + + strcpy( (char*)pBtCfg->mName, (char*)pdidoi->tszName ); + pBtCfg->mIsAvailable = true; + + return DIENUM_CONTINUE; +} + + +//----------------------------------------------------------------------------- +// Name: EnumPOVsCallback() +// Desc: Callback function for enumerating the axes on a joystick +//----------------------------------------------------------------------------- +BOOL CALLBACK JXInput::EnumPOVsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext ) +{ + JXInput* pThis = (JXInput*)pContext; + + // + // if the maximum number of buttons is already registered, + // issue a warning and stop enumeration. + // + if( JXINPUT_MAX_DIRECTIONALS == pThis->mPOVCount ) + { + OutputDebugString( "Max. number of POVs exceeded!" ); + return DIENUM_STOP; + } + + DirectionalConfig* pDirCfg = NULL; + + + if (pdidoi->guidType == GUID_POV) + { + assert( JXINPUT_MAX_DIRECTIONALS > pThis->mPOVCount ); + pDirCfg = & pThis->mDirectionalConfig[ pThis->mPOVCount++ ]; + } + + // fail-safe + if( NULL == pDirCfg ) // e.g. unknown stuff + return DIENUM_CONTINUE; + assert( NULL != pDirCfg ); + + // + // Perform config. + // + + strcpy( (char*)pDirCfg->mName, (char*)pdidoi->tszName ); + pDirCfg->mIsAvailable = true; + + return DIENUM_CONTINUE; +} + + + +//----------------------------------------------------------------------------- +// Name: EnumEffectsCallback() +// Desc: Callback function for enumerating the effects of a joystick +//----------------------------------------------------------------------------- +BOOL CALLBACK JXInput::EnumEffectsCallback( const DIEFFECTINFO* pdidoi, + VOID* pContext ) +{ + JXInput* pThis = (JXInput*)pContext; + + // + // Work on that!! + // + + return DIENUM_CONTINUE; +} + + + +//----------------------------------------------------------------------------- +// Name: InitDirectInput() +// Desc: Initialize the DirectInput variables. +//----------------------------------------------------------------------------- +HRESULT JXInput::InitDirectInput( HWND hWnd ) +{ + HRESULT hr; + + // Make sure we got a joystick + if( NULL == mpJoystick ) + { + return E_FAIL; + } + + + // + // Ask the device for some useful information. + // + mdiDevInfo.dwSize = sizeof( DIDEVICEINSTANCE ); + hr = mpJoystick->GetDeviceInfo( &mdiDevInfo ); + if( FAILED(hr) ) + return hr; + + // Set the data format to "simple joystick" - a predefined data format + // + // A data format specifies which controls on a device we are interested in, + // and how they should be reported. This tells DInput that we will be + // passing a DIJOYSTATE structure to IDirectInputDevice::GetDeviceState(). + hr = mpJoystick->SetDataFormat( &c_dfDIJoystick2 ); + if( FAILED(hr) ) + return hr; + + // Set the cooperative level to let DInput know how this device should + // interact with the system and with other DInput applications. +// hr = g_pJoystick->SetCooperativeLevel( hDlg, DISCL_EXCLUSIVE|DISCL_FOREGROUND ); + DWORD mode = ( NULL == hWnd ? DISCL_NONEXCLUSIVE|DISCL_BACKGROUND : DISCL_EXCLUSIVE|DISCL_BACKGROUND ); + hr = mpJoystick->SetCooperativeLevel( hWnd, mode ); + if( FAILED(hr) ) + return hr; + + // Determine how many axis the joystick has (so we don't error out setting + // properties for unavailable axis) + mdiDevCaps.dwSize = sizeof(DIDEVCAPS); + hr = mpJoystick->GetCapabilities(&mdiDevCaps); + if ( FAILED(hr) ) + return hr; + + + // Enumerate the axes of the joyctick and set the range of each axis. Note: + // we could just use the defaults, but we're just trying to show an example + // of enumerating device objects (axes, buttons, etc.). + mpJoystick->EnumObjects( EnumAxesCallback, (VOID*)this, DIDFT_AXIS ); + mpJoystick->EnumObjects( EnumButtonsCallback, (VOID*)this, DIDFT_BUTTON ); + mpJoystick->EnumObjects( EnumPOVsCallback, (VOID*)this, DIDFT_POV ); + + mpJoystick->EnumEffects( EnumEffectsCallback, (VOID*)this, DIEFT_ALL ); + + // For FF sticks, switch on autocenter as long as we do not use real FF + SwitchAutoCenter( true ); + + return S_OK; +} + + + + + +//----------------------------------------------------------------------------- +// Name: UpdateInputState() +// Desc: Get the input device's state and display it. +//----------------------------------------------------------------------------- +HRESULT JXInput::UpdateInputState() +{ + HRESULT hr; + + if( mpJoystick ) + { + + // Poll the device to read the current state + hr = mpJoystick->Poll(); + if( FAILED(hr) ) + { + // DInput is telling us that the input stream has been + // interrupted. We aren't tracking any state between polls, so + // we don't have any special reset that needs to be done. We + // just re-acquire and try again. + hr = mpJoystick->Acquire(); + while( hr == DIERR_INPUTLOST ) + hr = mpJoystick->Acquire(); + + // hr may be DIERR_OTHERAPPHASPRIO or other errors. This + // may occur when the app is minimized or in the process of + // switching, so just try again later + return S_OK; + } + + // Get the input's device state + if( FAILED( hr = mpJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &mJS ) ) ) + return hr; // The device should have been acquired during the Poll() + + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: FreeDirectInput() +// Desc: Initialize the DirectInput variables. +//----------------------------------------------------------------------------- +HRESULT JXInput::FreeDirectInput() +{ + // Unacquire and release any DirectInputDevice objects. + if( NULL != mpJoystick ) + { + // Unacquire the device one last time just in case + // the app tried to exit while the device is still acquired. + mpJoystick->Unacquire(); + + mpJoystick->Release(); + mpJoystick = NULL; + } + + return S_OK; +} + + + +HRESULT JXInput::SwitchAutoCenter( bool onoff ) +{ + HRESULT hr; + + DIPROPDWORD DIPropAutoCenter; + + DIPropAutoCenter.diph.dwSize = sizeof(DIPropAutoCenter); + DIPropAutoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER); + DIPropAutoCenter.diph.dwObj = 0; + DIPropAutoCenter.diph.dwHow = DIPH_DEVICE; + DIPropAutoCenter.dwData = ( onoff ? DIPROPAUTOCENTER_ON : DIPROPAUTOCENTER_OFF ); + + hr = mpJoystick->SetProperty( DIPROP_AUTOCENTER, &DIPropAutoCenter.diph ); + return hr; +} diff --git a/vendor/JXInput/0.3.4/c/jxinput.dsp b/vendor/JXInput/0.3.4/c/jxinput.dsp new file mode 100644 index 0000000..aac15c1 --- /dev/null +++ b/vendor/JXInput/0.3.4/c/jxinput.dsp @@ -0,0 +1,175 @@ +# Microsoft Developer Studio Project File - Name="jxinput" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=jxinput - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "jxinput.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "jxinput.mak" CFG="jxinput - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "jxinput - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE "jxinput - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "jxinput - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JXINPUT_EXPORTS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "C:\j2sdk1.4.2\include" /I "C:\j2sdk1.4.2\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JXINPUT_EXPORTS" /FR /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 dxguid.lib dinput8.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\build\jxinput.dll" + +!ELSEIF "$(CFG)" == "jxinput - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JXINPUT_EXPORTS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "C:\j2sdk1.4.2\include" /I "C:\j2sdk1.4.2\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JXINPUT_EXPORTS" /FR /Yu"stdafx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 dxguid.lib dinput8.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"..\Classes\jxinput.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "jxinput - Win32 Release" +# Name "jxinput - Win32 Debug" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\de_hardcode_jxinput_directinput_DirectInputDriver.cpp +# End Source File +# Begin Source File + +SOURCE=.\dllmain.cpp +# End Source File +# Begin Source File + +SOURCE=.\jxinput.cpp +# End Source File +# Begin Source File + +SOURCE=.\JXInputManager.cpp +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\de_hardcode_jxinput_directinput_DirectInputDriver.h + +!IF "$(CFG)" == "jxinput - Win32 Release" + +# PROP Ignore_Default_Tool 1 +USERDEP__DE_HA="..\classes\de\hardcode\jxinput\directinput\DirectInputDriver.class" +# Begin Custom Build +InputPath=.\de_hardcode_jxinput_directinput_DirectInputDriver.h + +"de_hardcode_jxinput_directinput_DirectInputDriver.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cd ..\Classes + C:\j2sdk1.4.2\bin\javah -classpath . -d ..\win32 de.hardcode.jxinput.directinput.DirectInputDriver + cd ..\win32 + +# End Custom Build + +!ELSEIF "$(CFG)" == "jxinput - Win32 Debug" + +# PROP Ignore_Default_Tool 1 +USERDEP__DE_HA="..\classes\de\hardcode\jxinput\directinput\DirectInputDriver.class" +# Begin Custom Build +InputPath=.\de_hardcode_jxinput_directinput_DirectInputDriver.h + +"de_hardcode_jxinput_directinput_DirectInputDriver.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cd ..\Classes + C:\j2sdk1.4.2\bin\javah -classpath . -d ..\win32 de.hardcode.jxinput.directinput.DirectInputDriver + cd ..\win32 + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\jxinput.h +# End Source File +# Begin Source File + +SOURCE=.\JXInputManager.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/vendor/JXInput/0.3.4/c/jxinput.dsw b/vendor/JXInput/0.3.4/c/jxinput.dsw new file mode 100644 index 0000000..deb2877 --- /dev/null +++ b/vendor/JXInput/0.3.4/c/jxinput.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "jxinput"=".\jxinput.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/vendor/JXInput/0.3.4/c/jxinput.h b/vendor/JXInput/0.3.4/c/jxinput.h new file mode 100644 index 0000000..6d47a31 --- /dev/null +++ b/vendor/JXInput/0.3.4/c/jxinput.h @@ -0,0 +1,183 @@ + +#define JXINPUT_MAX_AXES 8 +#define JXINPUT_MAX_BUTTONS 256 +#define JXINPUT_MAX_DIRECTIONALS 4 + + +/** + * This class will be exported by jxinput.dll. + */ +class JXINPUT_API JXInput +{ + +public: + + typedef enum AXISTYPE + { + TYPE_TRANSLATION, + TYPE_ROTATION, + TYPE_SLIDER + }; + + typedef enum BUTTONTYPE + { + TYPE_PUSHBUTTON, + TYPE_TOGGLEBUTTON + }; + + typedef enum AXISID + { + ID_X, ID_Y, ID_Z, + ID_ROTX, ID_ROTY, ID_ROTZ, + ID_SLIDER0, ID_SLIDER1 + }; + + + // + // Ctor + // + JXInput( LPDIRECTINPUTDEVICE8 pJoystick, HWND hWnd = NULL ); + + // + // Dtor + // + virtual ~JXInput(); + + // + // Operational methods + // + void update(); + + // Ask for the name + TCHAR * const getName() const; + + // + // Numbering methods + // + int getNumberOfAxes() const; + int getNumberOfButtons() const; + int getNumberOfDirectionals() const; + + + // + // Access axes + // + double getX() const; /** -1.0 .... 1.0 */ + double getY() const; /** -1.0 .... 1.0 */ + double getZ() const; /** -1.0 .... 1.0 */ + double getRotX() const; /** -1.0 .... 1.0 */ + double getRotY() const; /** -1.0 .... 1.0 */ + double getRotZ() const; /** -1.0 .... 1.0 */ + double getSlider0() const; /** 0.0 .... 1.0 */ + double getSlider1() const; /** 0.0 .... 1.0 */ + + + // + // Axis methods + // + bool isAxisAvailable( int idx ) const; + TCHAR* const getAxisName( int idx ) const; + int getAxisType( int idx ) const; + double getAxisValue( int idx ) const; + + // + // Button methods + // + bool isButtonAvailable( int idx ) const; + TCHAR* const getButtonName( int idx ) const; + int getButtonType( int idx ) const; + bool isButtonDown( int idx ) const; + + // + // Directional methods + // + bool isDirectionalAvailable( int idx ) const; + TCHAR* const getDirectionalName( int idx ) const; + int getDirection( int idx ) const; + +private://----------------------------------------------------------------------------------------- + LPDIRECTINPUTDEVICE8 mpJoystick; + + DIDEVICEINSTANCE mdiDevInfo; + DIDEVCAPS mdiDevCaps; + DIJOYSTATE2 mJS; // DInput joystick state + + int mSliderCount; + int mPOVCount; + int mButtonCount; + + double getAxisValueHelper( LONG val, int idx ) const; + + HRESULT SwitchAutoCenter( bool onoff = true ); + + HRESULT InitDirectInput( HWND hWnd = NULL ); + HRESULT FreeDirectInput(); + HRESULT UpdateInputState(); + + + static BOOL CALLBACK EnumAxesCallback + ( + const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext + ); + + static BOOL CALLBACK EnumButtonsCallback + ( + const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext + ); + + static BOOL CALLBACK EnumPOVsCallback + ( + const DIDEVICEOBJECTINSTANCE* pdidoi, + VOID* pContext + ); + + static BOOL CALLBACK EnumEffectsCallback + ( + const DIEFFECTINFO* pdidoi, + VOID* pContext + ); + + + class JXINPUT_API AxisConfig + { + + public: + bool mIsAvailable; + CHAR mName[MAX_PATH]; + AXISTYPE mType; + LONG mMinValue; + LONG mMaxValue; + double (JXInput::*mGetValueMethod)() const; + + } mAxisConfig [ JXINPUT_MAX_AXES ]; + + void initAxisConfig(); + + + class JXINPUT_API ButtonConfig + { + + public: + bool mIsAvailable; + CHAR mName[MAX_PATH]; + BUTTONTYPE mType; + + } mButtonConfig[ JXINPUT_MAX_BUTTONS ]; + + void initButtonsConfig(); + + + class JXINPUT_API DirectionalConfig + { + + public: + bool mIsAvailable; + CHAR mName[MAX_PATH]; + + } mDirectionalConfig[ JXINPUT_MAX_DIRECTIONALS ]; + + void initDirectionalsConfig(); +}; + diff --git a/vendor/JXInput/0.3.4/c/jxinput.sln b/vendor/JXInput/0.3.4/c/jxinput.sln new file mode 100644 index 0000000..714fdc7 --- /dev/null +++ b/vendor/JXInput/0.3.4/c/jxinput.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jxinput", "jxinput.vcproj", "{8AEA84DC-D8F0-4425-BEBF-A84E91115F76}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8AEA84DC-D8F0-4425-BEBF-A84E91115F76}.Debug|Win32.ActiveCfg = Debug|Win32 + {8AEA84DC-D8F0-4425-BEBF-A84E91115F76}.Debug|Win32.Build.0 = Debug|Win32 + {8AEA84DC-D8F0-4425-BEBF-A84E91115F76}.Release|Win32.ActiveCfg = Release|Win32 + {8AEA84DC-D8F0-4425-BEBF-A84E91115F76}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vendor/JXInput/0.3.4/c/jxinput.vcproj b/vendor/JXInput/0.3.4/c/jxinput.vcproj new file mode 100644 index 0000000..c87fc0f --- /dev/null +++ b/vendor/JXInput/0.3.4/c/jxinput.vcproj @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Axis.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Axis.java new file mode 100644 index 0000000..9f1d710 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Axis.java @@ -0,0 +1,72 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 19. Dezember 2001, 21:58 +//********************************************************************************************** +package de.hardcode.jxinput; + +/** + * The Axis interface describes the most common feature of a joystick or other input devices. + * + * @author Herkules + */ +public interface Axis extends Feature +{ + // Enumeration of axes. + final static int ID_X = 0; + final static int ID_Y = 1; + final static int ID_Z = 2; + final static int ID_ROTX = 3; + final static int ID_ROTY = 4; + final static int ID_ROTZ = 5; + final static int ID_SLIDER0 = 6; + final static int ID_SLIDER1 = 7; + final static int NUMBER_OF_ID = 8; + + // Enumeration of axis types + final static int TRANSLATION = 0; + final static int ROTATION = 1; + final static int SLIDER = 2; + + /** + * Retrieve the type of the axis. + * The type is describes the meaning and the range of values of the axis. + *

+ * TRANSLATION typed axes denote a translational deviation from a center + * position. This can be e.g. the common, basic joystick axes. + * The range of getValue() is [-1.0,1.0]. + *

+ * ROTATION typed axes denote a rotational deviation from a center + * position. Something on the stick is turned or twisted. + * The range of getValue() is [-1.0,1.0]. + *

+ * SLIDER typed axes denote a shifting device without a center position. + * A good sample is a throttle control. + * The range of getValue() is [0.0,1.0]. + * + * @return [ TRANSLATION | ROTATION | SLIDER ] + */ + int getType(); + + /** + * Returns the current value of the axis. + * The range of the result depends on the axis type. + * + * @return value [-1.0,1.0] or [0.0,1.0] + */ + double getValue(); + + + /** + * Inform about the resolution of the axis. + * + * @return resolution, e.g. 2^-16 + */ + double getResolution(); + +} + + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Button.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Button.java new file mode 100644 index 0000000..418e2b6 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Button.java @@ -0,0 +1,35 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 19. Dezember 2001, 21:58 +//********************************************************************************************** +package de.hardcode.jxinput; + +/** + * + * @author Herkules + */ +public interface Button extends Feature +{ + // Enumeration of button types + final static int PUSHBUTTON = 0; + final static int TOGGLEBUTTON = 1; + + /** + * Retrieve the type of the button. + * Pushbutton will deliver true==getState() as long as they are pressed down. + * Togglebuttons will change their state once they are pressed and keep that state + * until they are pressed again. + * @return [ PUSHBUTTON | TOGGLEBUTTON ] + */ + int getType(); + + /** + * Tells the state of the button at last update. + */ + boolean getState(); +} + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Directional.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Directional.java new file mode 100644 index 0000000..ccd27c1 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Directional.java @@ -0,0 +1,45 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 27. Dezember 2001, 23:33 +//********************************************************************************************** +package de.hardcode.jxinput; + +/** + * + * @author Herkules + */ +public interface Directional extends Feature +{ + /** + * If the Directional has a center position where it points to no direction, this + * flag is true when this position is reached. + */ + boolean isCentered(); + + /** + * Retrieve the direction pointed to. + * Value is given in 1/100 degree, [0,36000] + */ + int getDirection(); + + /** + * Retrieve the analog value pointing to the angle described by + * getDirection(). + * For coolie hats this will be either 1,0 for any direction or 0.0 + * when isCentered()==true. + */ + double getValue(); + + /** + * Inform about the resolution of the value returned by getValue(). + * + * @return resolution, e.g. 1.0 for coolie hats + */ + double getResolution(); + +} + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Feature.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Feature.java new file mode 100644 index 0000000..20c396f --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/Feature.java @@ -0,0 +1,38 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 27. Dezember 2001, 00:19 +//********************************************************************************************** +package de.hardcode.jxinput; + +/** + * An input device offers a set of features (otherwise it would be pretty useless). + * Features in this sense can be axes, buttons and a feature callede directional here. + * Coolie hats are typical directionals because they control a direction (to look at e.g.). + *

+ * There are no concrete classes directly derived from Feature - it only + * provides a basis for other interfaces. + * + * @see Axis + * @see Button + * @see Directional + * + * @author Herkules + */ +public abstract interface Feature +{ + /** + * Features may have a name provided e.g. by the driver. + */ + String getName(); + + /** + * Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + boolean hasChanged(); +} + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/JXInputDevice.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/JXInputDevice.java new file mode 100644 index 0000000..d8a8bc8 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/JXInputDevice.java @@ -0,0 +1,71 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 19. Dezember 2001, 21:47 +//********************************************************************************************** +package de.hardcode.jxinput; + +/** + * The JXInputDevise is the main entrypoint to the jxinput package. + *

+ * A JXInputDevice represents one physical device like a joystick, a gamepad or + * even some emulation (e.g. using keyboard) that implements the interface. + *

+ * The basis task of a JXInputDevise is to maintain a consistent state of all its features. + *
+ * It is save to distribute the Feature objects into application without worrying + * about someone else performing an update method and thereby destructing the consistent state. + *

+ * An additional task is to provide basic device features information like number of axes, buttons + * and directional features. + * + * @see Feature + * @see JXInputManager + * + * @author Herkules + * @version 0.2beta + */ +public interface JXInputDevice +{ + /** + * @directed + */ + /*#Features lnkFeatures;*/ + + /** + *@link aggregationByValue + */ + /*#Feature lnkFeature;*/ + + /** + * Devices may have a name. + * This name might be provided by a system dependant driver. + */ + String getName(); + + /** Actual number of available axes. */ + int getNumberOfAxes(); + + /** Actual number of available buttons. */ + int getNumberOfButtons(); + + /** Actual number of available directional features. */ + int getNumberOfDirectionals(); + + /** Maximum number of axes as an upper bound for index values. */ + int getMaxNumberOfAxes(); + + /** Maximum number of buttons as an upper bound for index values. */ + int getMaxNumberOfButtons(); + + /** Maximum number of directional features as an upper bound for index values. */ + int getMaxNumberOfDirectionals(); + + Axis getAxis( int idx ); + Button getButton( int idx ); + Directional getDirectional( int idx ); +} + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/JXInputManager.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/JXInputManager.java new file mode 100644 index 0000000..8c3e050 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/JXInputManager.java @@ -0,0 +1,233 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 29. Dezember 2001, 02:17 +//********************************************************************************************** +package de.hardcode.jxinput; + +// +// Import driver stuff +// +import de.hardcode.jxinput.directinput.DirectInputDevice; +import de.hardcode.jxinput.event.JXInputEventManager; +import de.hardcode.jxinput.keyboard.JXKeyboardInputDevice; +import de.hardcode.jxinput.virtual.JXVirtualInputDevice; + + +import java.util.ArrayList; +import java.util.Iterator; +import java.awt.Component; + + +/** + * Manages the available instances of JXInputDevice. + * It holds the one central update method which synchronizes with the physical device. + * @author Herkules + */ +public class JXInputManager +{ + + /** Remember when the last update took place. */ + private static long mTimeOfLastUpdate; + + /** Maintain a list of devices. */ + private final static ArrayList mDevices = new ArrayList(); + + /** Maintain a list of direct input devices. */ + private final static ArrayList mDIDevices = new ArrayList(); + + /** Maintain a list of virtual devices. */ + private final static ArrayList mVirtualDevices = new ArrayList(); + + /** Maintain a list of keyboard devices. */ + private final static ArrayList mKBDevices = new ArrayList(); + + /** + * Statically retrieve all DirectInputDevices available. + */ + static + { + reset(); + } + + + /** + * @directed + */ + /*#JXInputDevice lnkJXInputDevice;*/ + + /** + * Creates a new instance of JXInputManager. + * This is prohibited - it only has static members. + */ + private JXInputManager() + { + } + + + /** + * Retrieve the number of available input devices. + */ + public static int getNumberOfDevices() + { + return mDevices.size(); + } + + /** + * Delivers the JXInputDevice with the desired index. + *

+ * Take care that idx < getNumberOfDevices()! + */ + public static JXInputDevice getJXInputDevice( int idx ) + { + // + // Be well-behaved even if idx is out of range. + // + if ( idx >= mDevices.size() ) + return null; + return (JXInputDevice)mDevices.get( idx ); + } + + + /** + * Master reset for all devices and events. + * After calling reset(), better forget all devices created or retrieved. + * They are no longer valid. + * Event listeners will no longer be called and should be discarded. + */ + synchronized public static void reset() + { + JXInputEventManager.reset(); + + mDevices.clear(); + + mVirtualDevices.clear(); + mDIDevices.clear(); + + DirectInputDevice.reset(); + + for ( int i = 0; i < DirectInputDevice.getNumberOfDevices(); ++i ) + { + DirectInputDevice dev = new DirectInputDevice( i ); + mDevices.add( dev ); + mDIDevices.add( dev ); + } + + // I have to call updateFeatures one time here during initialization + // bc. I experienced difficulties otherwise while running with the + // J3D sensoring stuff! +// updateFeatures(); + DirectInputDevice.update(); + + int n = mKBDevices.size(); + for ( int i = 0; i < n; ++i ) + ((JXKeyboardInputDevice)mKBDevices.get( i )).shutdown(); + mKBDevices.clear(); + } + + + /** + * Update the (shared) state of all features in one step. + * This method asks the actual device for a consistant state. + * After calling this method, all features may have new values. + * updateFeatures() is meant to be called e.g. once per frame in a gaming environment. + */ + public static void updateFeatures() + { + // Get timing + long now = System.currentTimeMillis(); + long deltaT = now - mTimeOfLastUpdate; + + // Update available driver + DirectInputDevice.update(); + + // + // Update the virtual devices. + // + Iterator vdevices = mVirtualDevices.iterator(); + while ( vdevices.hasNext() ) + { + ((JXVirtualInputDevice)vdevices.next()).update( deltaT ); + } + + // Remember time + mTimeOfLastUpdate = now; + + // Fire all events. + JXInputEventManager.trigger(); + } + + + + /** + * Get time when last update occurred. + * @return tickervalue in milliseconds + */ + public static long getLastUpdateTime() + { + return mTimeOfLastUpdate; + } + + + /** + * Create a new pseudo-device. + */ + public static JXKeyboardInputDevice createKeyboardDevice() + { + JXKeyboardInputDevice d = new JXKeyboardInputDevice(); + mDevices.add( d ); + mKBDevices.add( d ); + return d; + } + + + /** + * Create a new pseudo-device listening to a Swing component. + * Make sure that the component also has the keyboard focus!! + */ + public static JXKeyboardInputDevice createKeyboardDevice( Component comp ) + { + JXKeyboardInputDevice d = new JXKeyboardInputDevice( comp ); + mDevices.add( d ); + mKBDevices.add( d ); + return d; + } + + + /** + * Delete a keyboard device again e.g. when the corresponding + * JComponent gets deleted. + */ + public static void deleteKeyboardDevice( JXKeyboardInputDevice dev ) + { + mDevices.remove( dev ); + mKBDevices.remove( dev ); + ((JXKeyboardInputDevice)dev).shutdown(); + } + + + /** + * Create a new pseudo-device. + */ + public static JXVirtualInputDevice createVirtualDevice() + { + JXVirtualInputDevice d = new JXVirtualInputDevice(); + mDevices.add( d ); + mVirtualDevices.add( d ); + return d; + } + + + /** + * Delete a virtual device again. + */ + public static void deleteVirtualDevice( JXVirtualInputDevice dev ) + { + mDevices.remove( dev ); + mVirtualDevices.remove( dev ); + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIAxis.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIAxis.java new file mode 100644 index 0000000..a6d0eac --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIAxis.java @@ -0,0 +1,70 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 27. Dezember 2001, 00:14 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import de.hardcode.jxinput.Axis; + +/** + * + * @author Herkules + */ +class DIAxis implements Axis +{ + private final int mDeviceIdx; + private final int mIdx; + + /** + * Creates a new instance of DIAxis. + */ + DIAxis( int devidx, int idx ) + { + mDeviceIdx = devidx; + mIdx = idx; + } + + public String getName() + { + return DirectInputDriver.getAxisName( mDeviceIdx, mIdx ); + } + + + /** + * Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + + public double getValue() + { + return DirectInputDriver.getAxisValue( mDeviceIdx, mIdx ); + } + + public int getType() + { + return DirectInputDriver.getAxisType( mDeviceIdx, mIdx ); + } + + /** + * Inform about the resolution of the axis. + * + * @return resolution, e.g. 2^-16 + */ + public double getResolution() + { + // extend the driver here!! + // Here I assume typical 16 bit resolution + return ( getType() == Axis.SLIDER ? 1.0/65536.0 : 2.0/65536.0 ) ; + } + +} + + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIButton.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIButton.java new file mode 100644 index 0000000..5419550 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIButton.java @@ -0,0 +1,55 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 27. Dezember 2001, 00:14 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import de.hardcode.jxinput.Button; + + +/** + * + * @author Herkules + */ +class DIButton implements Button +{ + private final int mDeviceIdx; + private final int mIdx; + + /** + * Creates a new instance of DIButton. + */ + DIButton( int devidx, int idx ) + { + mDeviceIdx = devidx; + mIdx = idx; + } + + public String getName() + { + return DirectInputDriver.getButtonName( mDeviceIdx, mIdx ); + } + + /** + * Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + + public int getType() + { + return DirectInputDriver.getButtonType( mDeviceIdx, mIdx ); + } + + public boolean getState() + { + return DirectInputDriver.getButtonState( mDeviceIdx, mIdx ); + } +} \ No newline at end of file diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIDirectional.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIDirectional.java new file mode 100644 index 0000000..9da2d3d --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DIDirectional.java @@ -0,0 +1,78 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 27. Dezember 2001, 23:40 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import de.hardcode.jxinput.Directional; + +/** + * + * @author Herkules + */ +class DIDirectional implements Directional +{ + private final int mDeviceIdx; + private final int mIdx; + + /** + * Creates a new instance of DIDirectional. + */ + DIDirectional( int devidx, int idx ) + { + mDeviceIdx = devidx; + mIdx = idx; + } + + /** Features may have a name provided e.g. by the driver. */ + public String getName() + { + return DirectInputDriver.getDirectionalName( mDeviceIdx, mIdx ); + } + + /** + * Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + + + public boolean isCentered() + { + return ( 0xffff == (DirectInputDriver.getDirection( mDeviceIdx, mIdx ) & 0xffff) ); + } + + public int getDirection() + { + return isCentered() ? 0 : DirectInputDriver.getDirection( mDeviceIdx, mIdx ); + } + + public double getValue() + { + if ( isCentered() ) + return 0.0; + return 1.0; + } + + /** + * Inform about the resolution of the value returned by getValue(). + * + * @return resolution, e.g. 1.0 for coolie hats + */ + public double getResolution() + { + // DI POV always return 0.0 or 1.0, so the resolution is 1.0. + return 1.0; + } + + +} + + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DirectInputDevice.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DirectInputDevice.java new file mode 100644 index 0000000..a20eab3 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DirectInputDevice.java @@ -0,0 +1,170 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 26. Dezember 2001, 00:40 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.Axis; +import de.hardcode.jxinput.Directional; +import de.hardcode.jxinput.Button; + +/** + * + * @author Herkules + */ +public class DirectInputDevice implements JXInputDevice +{ + int mDeviceIdx; + + private DIAxis[] mAxes; + private DIButton[] mButtons; + private DIDirectional[] mDirectionals; + + /** + * The number of DirectInput devices available with the driver. + */ + public static int getNumberOfDevices() + { + if ( DirectInputDriver.isAvailable() ) + return DirectInputDriver.getNumberOfDevices(); + return 0; + } + + + /** + * Update the state of all devices. + */ + public static void update() + { + if ( DirectInputDriver.isAvailable() ) + DirectInputDriver.nativeupdate(); + } + + + + + /** + * Creates a new instance of DirectInputDevice. + */ + public DirectInputDevice( int devidx ) + { + mDeviceIdx = devidx; + + init(); + } + + /** + * Reset the DirectInput connection. + */ + public static void reset() + { + if ( DirectInputDriver.isAvailable() ) + DirectInputDriver.reset(); + } + + + /** + * Initialisation of fields. + */ + private final void init() + { + // + // Allocate arrays for max. number of features + // + mAxes = new DIAxis [ getMaxNumberOfAxes() ]; + mButtons = new DIButton [ getMaxNumberOfButtons() ]; + mDirectionals = new DIDirectional [ getMaxNumberOfDirectionals() ]; + + // + // Fill arrays due to the state of the driver. + // + for ( int i = 0; i < mAxes.length; ++i ) + { + if ( DirectInputDriver.isAxisAvailable( mDeviceIdx, i ) ) + mAxes[ i ] = new DIAxis( mDeviceIdx, i ); + } + + for ( int i = 0; i < mButtons.length; ++i ) + { + if ( DirectInputDriver.isButtonAvailable( mDeviceIdx, i ) ) + mButtons[ i ] = new DIButton( mDeviceIdx, i ); + } + + for ( int i = 0; i < mDirectionals.length; ++i ) + { + if ( DirectInputDriver.isDirectionalAvailable( mDeviceIdx, i ) ) + mDirectionals[ i ] = new DIDirectional( mDeviceIdx, i ); + } + } + + /** Devices may have a name. */ + public String getName() + { + String name = DirectInputDriver.getName( mDeviceIdx ); + if ( null == name ) + return "Win32 DirectInput Joystick"; + return name; + } + + + /** Actual number of available buttons. */ + public int getNumberOfButtons() + { + return DirectInputDriver.getNumberOfButtons( mDeviceIdx ); + } + + /** Actual number of available axes. */ + public int getNumberOfAxes() + { + return DirectInputDriver.getNumberOfAxes( mDeviceIdx ); + } + + /** Actual number of available directional features. */ + public int getNumberOfDirectionals() + { + return DirectInputDriver.getNumberOfDirectionals( mDeviceIdx ); + } + + /** Maximum number of buttons as an upper bound for index values. */ + public int getMaxNumberOfButtons() + { + return DirectInputDriver.getMaxNumberOfButtons(); + } + + /** Maximum number of axes as an upper bound for index values. */ + public int getMaxNumberOfAxes() + { + return DirectInputDriver.getMaxNumberOfAxes(); + } + + /** Maximum number of available directional features. */ + public int getMaxNumberOfDirectionals() + { + return DirectInputDriver.getMaxNumberOfDirectionals(); + } + + + public Axis getAxis(int idx) + { + return mAxes[ idx ]; + } + + public Button getButton(int idx) + { + return mButtons[ idx ]; + } + + public Directional getDirectional(int idx) + { + return mDirectionals[ idx ]; + } + +} + + + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DirectInputDriver.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DirectInputDriver.java new file mode 100644 index 0000000..558f7d8 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/DirectInputDriver.java @@ -0,0 +1,184 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 19. Dezember 2001, 22:44 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import java.lang.reflect.Array; + +/** + * DirectInputDriver: the connection to the Win32 joystick. + * There is only one allowed, so the layout of this class is merely static. + * + * History: + * + * Changes since 0.1beta: + * - support of multiple devices addressed by the dev index + * + * + * @author Herkules + * @version 0.2beta + */ +class DirectInputDriver +{ + private final static String NATIVE_LIB_NAME = "jxinput"; + + /** Remember wether nativeinit() succeeded. */ + static boolean sIsOperational = false; + + // + // Static arrays to hold the values. + // + private static double [][] sAxisValues; + private static boolean [][] sButtonStates; + private static int [][] sDirectionalValues; + + /** + * Perform the static initialization. + */ + static + { + try + { + // Load the native lib. + System.loadLibrary( NATIVE_LIB_NAME ); + + init(); + } + catch( SecurityException e ) + { + Log.logger.warning("Native library jxinput not loaded due to a SecurityException."); + } + catch( UnsatisfiedLinkError e ) + { + Log.logger.info("Native library jxinput not loaded due to an UnsatisfiedLinkError."); + } + } + + + private final static void init() + { + sIsOperational = false; + // + // Initialize it. + // + if ( nativeinit() ) + { + int devs = getNumberOfDevices(); + sAxisValues = new double [ devs ][ DirectInputDriver.getMaxNumberOfAxes() ]; + sButtonStates = new boolean [ devs ][ DirectInputDriver.getMaxNumberOfButtons() ]; + sDirectionalValues = new int [ devs ][ DirectInputDriver.getMaxNumberOfDirectionals() ]; + + // Bind the native lib to my variables. + bind(); + + // Remember I am fine. + sIsOperational = true; + } + + } + + + /** + * Static ctor of DirectInputDriver. + * No object will be created due to the static layout. + */ + private DirectInputDriver() + { + } + + // Administration + private static native boolean nativeinit(); + private static native void nativeexit(); + private static native void bind(); + + static native int getNumberOfDevices(); + + // Configuration + static native String getName( int dev ); + static native int getNumberOfAxes( int dev ); + static native int getNumberOfButtons( int dev ); + static native int getNumberOfDirectionals( int dev ); + static native int getMaxNumberOfAxes(); + static native int getMaxNumberOfButtons(); + static native int getMaxNumberOfDirectionals(); + + static native boolean isAxisAvailable( int dev, int idx ); + static native String getAxisName( int dev, int idx ); + static native int getAxisType( int dev, int idx ); + + static native boolean isButtonAvailable( int dev, int idx ); + static native String getButtonName( int dev, int idx ); + static native int getButtonType( int dev, int idx ); + + static native boolean isDirectionalAvailable( int dev, int idx ); + static native String getDirectionalName( int dev, int idx ); + + // Operation + static native void nativeupdate(); + + + public static boolean isAvailable() + { + return sIsOperational; + } + + + /** + * Shutdown the device and free all Win32 resources. + * It is not a good idea to access any joystick features after + * shutdown(). + */ + static void shutdown() + { + nativeexit(); + sAxisValues = null; + sButtonStates = null; + sDirectionalValues = null; + } + + + /** + * Reset the device and free all Win32 resources. + */ + static void reset() + { + shutdown(); + init(); + } + + static double getAxisValue( int dev, int idx ) + { + return sAxisValues[ dev ][ idx ]; + } + + static boolean getButtonState( int dev, int idx ) + { + return sButtonStates[ dev ][ idx ]; + } + + static int getDirection( int dev, int idx ) + { + return sDirectionalValues[ dev ][ idx ]; + } + + /** + * @param args the command line arguments + */ + public static void main (String args[]) + { + + if ( ! sIsOperational ) + return; + + for( int i = 0; i < 5000; ++i ) + nativeupdate(); + + shutdown(); + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/Log.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/Log.java new file mode 100644 index 0000000..95e586c --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/directinput/Log.java @@ -0,0 +1,34 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 29. Oktober 2002, 22:57 +//********************************************************************************************** +package de.hardcode.jxinput.directinput; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Herkules + */ +public class Log +{ + public final static Logger logger = Logger.getLogger( Log.class.getPackage().getName() ); + +// static +// { +// logger.setLevel( Level.ALL ); +// } + + /** + * Creates a new instance of Log. + */ + private Log() + { + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputAxisEvent.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputAxisEvent.java new file mode 100644 index 0000000..c353b5e --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputAxisEvent.java @@ -0,0 +1,48 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:33 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.Axis; + +/** + * Represents an event coming from an axis. + * @author Joerg Plewe + */ +public class JXInputAxisEvent +{ + private final Axis mAxis; + double mDelta; + + /** + * Creates a new instance of JXInputEvent. + */ + JXInputAxisEvent( Axis axis ) + { + mAxis = axis; + } + + /** + * The feature that caused the event. + */ + public final Axis getAxis() + { + return mAxis; + } + + + /** + * Return the change in value that caused the event. + */ + public double getDelta() + { + return mDelta; + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputAxisEventListener.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputAxisEventListener.java new file mode 100644 index 0000000..d8adf46 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputAxisEventListener.java @@ -0,0 +1,19 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:54 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +/** + * + * @author Herkules + */ +public interface JXInputAxisEventListener +{ + void changed( JXInputAxisEvent ev ); +} + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputButtonEvent.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputButtonEvent.java new file mode 100644 index 0000000..d82d0b9 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputButtonEvent.java @@ -0,0 +1,38 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:33 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.Button; + +/** + * Represents event coming from a button. + * @author Joerg Plewe + */ +public class JXInputButtonEvent +{ + final Button mButton; + + /** + * Creates a new instance of JXInputEvent. + */ + JXInputButtonEvent( Button button ) + { + mButton = button; + } + + /** + * The feature that caused the event. + */ + public final Button getButton() + { + return mButton; + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputButtonEventListener.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputButtonEventListener.java new file mode 100644 index 0000000..afdc323 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputButtonEventListener.java @@ -0,0 +1,19 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:54 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +/** + * + * @author Herkules + */ +public interface JXInputButtonEventListener +{ + void changed( JXInputButtonEvent ev ); +} + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputDirectionalEvent.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputDirectionalEvent.java new file mode 100644 index 0000000..70e6bcd --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputDirectionalEvent.java @@ -0,0 +1,56 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:33 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.Directional; + +/** + * Represents an event coming from an axis. + * @author Joerg Plewe + */ +public class JXInputDirectionalEvent +{ + private final Directional mDirectional; + double mValueDelta; + int mDirectionDelta; + + /** + * Creates a new instance of JXInputEvent. + */ + JXInputDirectionalEvent( Directional directional ) + { + mDirectional = directional; + } + + /** + * The feature that caused the event. + */ + public final Directional getDirectional() + { + return mDirectional; + } + + /** + * Return the change in value that caused the event. + */ + public double getValueDelta() + { + return mValueDelta; + } + + /** + * Return the change in direction that caused the event. + */ + public int getDirectionDelta() + { + return mDirectionDelta; + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputDirectionalEventListener.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputDirectionalEventListener.java new file mode 100644 index 0000000..65c7efa --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputDirectionalEventListener.java @@ -0,0 +1,19 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:54 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +/** + * + * @author Herkules + */ +public interface JXInputDirectionalEventListener +{ + void changed( JXInputDirectionalEvent ev ); +} + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputEventManager.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputEventManager.java new file mode 100644 index 0000000..aa196d7 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/event/JXInputEventManager.java @@ -0,0 +1,284 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 31. Januar 2002, 23:42 +//********************************************************************************************** +package de.hardcode.jxinput.event; + +import de.hardcode.jxinput.JXInputManager; +import de.hardcode.jxinput.JXInputDevice; + +import java.util.ArrayList; +import de.hardcode.jxinput.Axis; +import java.util.Iterator; +import de.hardcode.jxinput.Button; +import de.hardcode.jxinput.Directional; + +/** + * Handles all events and listeners. + * JXInputEventManager is layed out a static singleton. + * @author Herkules + */ +public class JXInputEventManager +{ + + private final static ArrayList mAxisEventListeners = new ArrayList(); + private final static ArrayList mButtonEventListeners = new ArrayList(); + private final static ArrayList mDirectionalEventListeners = new ArrayList(); + + private static autotrigger mAutoTrigger = null; + + /** + * Inner class combining a listener with its scheduling parameters. + */ + private static class axislistener + { + final JXInputAxisEventListener mListener; + final double mTreshold; + final JXInputAxisEvent mEvent; + double mLastValueFired = 0.0; + + axislistener( JXInputAxisEventListener l, Axis axis, double treshold ) + { + mListener = l; + mTreshold = treshold; + mEvent = new JXInputAxisEvent( axis ); + } + + final void checkTrigger() + { + double curval = mEvent.getAxis().getValue(); + double delta = curval - mLastValueFired; + + if ( Math.abs( delta ) >= mTreshold ) + { + mLastValueFired = curval; + mEvent.mDelta = delta; + mListener.changed( mEvent ); + } + } + } + + /** + * Inner class combining a listener with its scheduling parameters. + */ + private static class buttonlistener + { + final JXInputButtonEventListener mListener; + final JXInputButtonEvent mEvent; + boolean mLastValueFired = false; + + buttonlistener( JXInputButtonEventListener l, Button button ) + { + mListener = l; + mEvent = new JXInputButtonEvent( button ); + } + + final void checkTrigger() + { + boolean curstate = mEvent.getButton().getState(); + if ( curstate != mLastValueFired ) + { + mLastValueFired = curstate; + mListener.changed( mEvent ); + } + } + } + + + private static class directionallistener + { + final JXInputDirectionalEventListener mListener; + final double mValueTreshold; + final JXInputDirectionalEvent mEvent; + double mLastValueFired = 0.0; + boolean mLastCenteredFired = true; + int mLastDirectionFired = 0; + + directionallistener( JXInputDirectionalEventListener l, Directional directional, double valuetreshold ) + { + mListener = l; + mValueTreshold = valuetreshold; + mEvent = new JXInputDirectionalEvent( directional ); + } + + final void checkTrigger() + { + double curval = mEvent.getDirectional().getValue(); + int curdir = mEvent.getDirectional().getDirection(); + boolean curctr = mEvent.getDirectional().isCentered(); + + double delta = curval - mLastValueFired; + int dirdelta = curdir - mLastDirectionFired; + boolean centeredchanged = mLastCenteredFired != curctr; + + if ( Math.abs( delta ) >= mValueTreshold + || Math.abs( dirdelta ) > 0 + || centeredchanged ) + { + mLastValueFired = curval; + mLastDirectionFired = curdir; + mLastCenteredFired = curctr; + + mEvent.mValueDelta = delta; + mEvent.mDirectionDelta = dirdelta; + mListener.changed( mEvent ); + } + } + } + + /** + * Creates a new instance of JXInputEventManager. + */ + private JXInputEventManager() + { + } + + + /** + * Remove all listeners at once. + */ + public static void reset() + { + mAxisEventListeners.clear(); + mButtonEventListeners.clear(); + mDirectionalEventListeners.clear(); + } + + + /** + * Query devices and fire all occuring events. + * trigger() is thought to be called by JXInputManager#updateFeatures(). + */ + public static void trigger() + { + int n = mAxisEventListeners.size(); + for ( int i = 0; i < n; i++ ) + { + axislistener l = (axislistener)mAxisEventListeners.get( i ); + l.checkTrigger(); + } + + n = mButtonEventListeners.size(); + for ( int i = 0; i < n; i++ ) + { + buttonlistener l = (buttonlistener)mButtonEventListeners.get( i ); + l.checkTrigger(); + } + + n = mDirectionalEventListeners.size(); + for ( int i = 0; i < n; i++ ) + { + directionallistener l = (directionallistener)mDirectionalEventListeners.get( i ); + l.checkTrigger(); + } + } + + + private final static class autotrigger extends Thread + { + boolean mFinish = false; + final int mDelay; + + autotrigger( int delay ) + { + mDelay = delay; + } + + public void run() + { + while ( ! mFinish ) + { + try + { + Thread.sleep( mDelay ); + JXInputManager.updateFeatures(); + } + catch ( InterruptedException ex ) + { + } + } + } + } + + + /** + * Set the intervall in ms that is used to check for new values of the features. + * Set it to <= 0 to prohibit automatic triggering. Events will then only be fired + * when somebody invokes JXInputManager#updateFeatures(). + */ + public static void setTriggerIntervall( int ms ) + { + // + // Kill current thread, if any + // + if ( null != mAutoTrigger ) + { + mAutoTrigger.mFinish = true; + try + { + mAutoTrigger.join(); + } + catch ( InterruptedException ex ) + { + } + } + + mAutoTrigger = null; + + if ( ms > 0 ) + { + mAutoTrigger = new autotrigger( ms ); + mAutoTrigger.start(); + } + + } + + + + + public static void addListener( JXInputAxisEventListener l, Axis axis, double treshold ) + { + mAxisEventListeners.add( new JXInputEventManager.axislistener( l, axis, treshold ) ); + } + + public static void addListener( JXInputAxisEventListener l, Axis axis ) + { + mAxisEventListeners.add( new JXInputEventManager.axislistener( l, axis, axis.getResolution() ) ); + } + + public static void removeListener( JXInputAxisEventListener l ) + { + mAxisEventListeners.remove( l ); + } + + + public static void addListener( JXInputButtonEventListener l, Button button ) + { + mButtonEventListeners.add( new JXInputEventManager.buttonlistener( l, button ) ); + } + + public static void removeListener( JXInputButtonEventListener l ) + { + mButtonEventListeners.remove( l ); + } + + public static void addListener( JXInputDirectionalEventListener l, Directional directional, double valuetreshold ) + { + mDirectionalEventListeners.add( new JXInputEventManager.directionallistener( l, directional, valuetreshold ) ); + } + + public static void addListener( JXInputDirectionalEventListener l, Directional directional ) + { + mDirectionalEventListeners.add( new JXInputEventManager.directionallistener( l, directional, directional.getResolution() ) ); + } + + public static void removeListener( JXInputDirectionalEventListener l ) + { + mDirectionalEventListeners.remove( l ); + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/DeviceConfiguration.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/DeviceConfiguration.java new file mode 100644 index 0000000..8c1288a --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/DeviceConfiguration.java @@ -0,0 +1,95 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 23. Februar 2002, 14:05 +//********************************************************************************************** +package de.hardcode.jxinput.j3d; + +import de.hardcode.jxinput.Axis; + + +/** + * Connects JXInput with J3DInputDevice. + * + * @author Herkules + */ +public class DeviceConfiguration +{ + public final static int AXIS_X = 0; + public final static int AXIS_Y = 1; + public final static int AXIS_Z = 2; + + private final static class axisvalue + { + private final Axis mAxis; + private final IsActiveCondition mIsActive; + private final IsActiveCondition mIsIncremental; + private final double mScale; + private final double mOffset; + private double mValue; + + axisvalue( Axis axis, IsActiveCondition active, IsActiveCondition incremental, double offset, double scale ) + { + mAxis = axis; + mIsActive = active; + mIsIncremental = incremental; + mValue = mOffset = offset; + mScale = scale; + } + + double value() + { + if ( mIsActive.isActive() ) + { + double newval = mAxis.getValue() * mScale; + + if ( mIsIncremental.isActive() ) + mValue += newval; + else + mValue = newval + mOffset; + } + return mValue; + } + } + + DeviceConfiguration.axisvalue [] mAxisTrans = new DeviceConfiguration.axisvalue[ 3 ]; + DeviceConfiguration.axisvalue [] mAxisRot = new DeviceConfiguration.axisvalue[ 3 ]; + + /** + * Creates a new instance of DeviceConfiguration. + */ + public DeviceConfiguration() + { + } + + + double getTranslational( int axisid ) + { + DeviceConfiguration.axisvalue val = mAxisTrans[ axisid ]; + return null == val ? 0.0 : val.value(); + } + + double getRotational( int axisid ) + { + DeviceConfiguration.axisvalue val = mAxisRot[ axisid ]; + return null == val ? 0.0 : val.value(); + } + + public void setTranslational( int axisid, Axis axis, IsActiveCondition active, IsActiveCondition incremental, double offset, double scale ) + { + if ( axisid < 0 || axisid > AXIS_Z ) + throw new IllegalArgumentException(); + mAxisTrans[ axisid ] = new DeviceConfiguration.axisvalue( axis, active, incremental, offset, scale ); + } + + public void setRotational( int axisid, Axis axis, IsActiveCondition active, IsActiveCondition incremental, double offset, double scale ) + { + if ( axisid < 0 || axisid > AXIS_Z ) + throw new IllegalArgumentException(); + mAxisRot[ axisid ] = new DeviceConfiguration.axisvalue( axis, active, incremental, offset, scale ); + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsActiveCondition.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsActiveCondition.java new file mode 100644 index 0000000..af6ca08 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsActiveCondition.java @@ -0,0 +1,25 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 25. Februar 2002, 22:41 +//********************************************************************************************** +package de.hardcode.jxinput.j3d; + +/** + * + * @author Herkules + */ +public interface IsActiveCondition +{ + public final static IsActiveCondition ALWAYS = IsAlwaysActiveCondition.ALWAYS; + public final static IsActiveCondition NEVER = IsAlwaysActiveCondition.NEVER; + + /** + * Tell wether a certain thing is active. + */ + boolean isActive(); +} + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsActiveOnButtonCondition.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsActiveOnButtonCondition.java new file mode 100644 index 0000000..98da7bb --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsActiveOnButtonCondition.java @@ -0,0 +1,39 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 25. Februar 2002, 22:43 +//********************************************************************************************** +package de.hardcode.jxinput.j3d; + +import de.hardcode.jxinput.Button; + +/** + * + * @author Herkules + */ +public class IsActiveOnButtonCondition implements IsActiveCondition +{ + private final boolean mActiveState; + private final Button mButton; + + /** + * Creates a new instance of IsAlwayActiveCondition. + */ + public IsActiveOnButtonCondition( Button button, boolean activestate ) + { + mActiveState = activestate; + mButton = button; + } + + /** + * Tell wether a certain thing is active. + */ + public boolean isActive() + { + return mButton.getState() == mActiveState; + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsAlwaysActiveCondition.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsAlwaysActiveCondition.java new file mode 100644 index 0000000..cd8b1fe --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/IsAlwaysActiveCondition.java @@ -0,0 +1,38 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 25. Februar 2002, 22:43 +//********************************************************************************************** +package de.hardcode.jxinput.j3d; + +/** + * + * @author Herkules + */ +final class IsAlwaysActiveCondition implements IsActiveCondition +{ + private final boolean mIsActive; + + public final static IsActiveCondition ALWAYS = new IsAlwaysActiveCondition( true ); + public final static IsActiveCondition NEVER = new IsAlwaysActiveCondition( false ); + + /** + * Creates a new instance of IsAlwayActiveCondition. + */ + private IsAlwaysActiveCondition(boolean isactive) + { + mIsActive = isactive; + } + + /** + * Tell wether a certain thing is active. + */ + public boolean isActive() + { + return mIsActive; + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/J3DInputDevice.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/J3DInputDevice.java new file mode 100644 index 0000000..f5b08f2 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/J3DInputDevice.java @@ -0,0 +1,171 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 22. Februar 2002, 13:21 +//********************************************************************************************** +package de.hardcode.jxinput.j3d; + +import javax.media.j3d.InputDevice; +import javax.media.j3d.Sensor; +import javax.media.j3d.SensorRead; +import javax.vecmath.Vector3d; +import javax.media.j3d.Transform3D; +import de.hardcode.jxinput.JXInputManager; + + +/** + * Implementation of Java3D's InputDevice + * + * @author Herkules + */ +public class J3DInputDevice + implements InputDevice +{ + private Vector3d mPosition = new Vector3d(); + private Transform3D mNewTransform = new Transform3D(); + + private Transform3D mRotTransX = new Transform3D(); + private Transform3D mRotTransY = new Transform3D(); + private Transform3D mRotTransZ = new Transform3D(); + + private Vector3d mInitPos = new Vector3d( 0.0, 0.0, 0.0 ); + + private Sensor mSensor = new Sensor( this ); + private SensorRead mSensorRead = new SensorRead(); + + private DeviceConfiguration mConfig; + + /** + * Creates a new instance of J3DInputDevice. + */ + public J3DInputDevice( DeviceConfiguration config ) + { + mConfig = config; + setNominalPositionAndOrientation(); + } + + + public void close() + { + // Intentionally empty + } + + + /** + * Retrieve processing mode. + * For this device, it always is NON_BLOCKING. + */ + public int getProcessingMode() + { + return InputDevice.NON_BLOCKING; + } + + + /** + * Don't care for the index, I only support one sensor. + * And I deliver that. + */ + public Sensor getSensor( int param ) + { + return mSensor; + } + + + /** + * Tell the world about the only one sensor I support. + */ + public int getSensorCount() + { + return 1; + } + + + /** + * Well - initialize! + * Nothing to do here. + */ + public boolean initialize() + { + return true; + } + + + /** + * The main update method. + */ + public void pollAndProcessInput() + { + JXInputManager.updateFeatures(); + + mSensorRead.setTime( JXInputManager.getLastUpdateTime() ); + + mRotTransX.rotX( mConfig.getRotational( DeviceConfiguration.AXIS_X ) ); + mRotTransY.rotY( mConfig.getRotational( DeviceConfiguration.AXIS_Y ) ); + mRotTransZ.rotZ( mConfig.getRotational( DeviceConfiguration.AXIS_Z ) ); + + mPosition.set( + mConfig.getTranslational( DeviceConfiguration.AXIS_X ), + mConfig.getTranslational( DeviceConfiguration.AXIS_Y ), + mConfig.getTranslational( DeviceConfiguration.AXIS_Z ) + ); + + mNewTransform.set( mPosition ); + + mNewTransform.mul( mRotTransX ); + mNewTransform.mul( mRotTransY ); + mNewTransform.mul( mRotTransZ ); + + mSensorRead.set( mNewTransform ); + mSensor.setNextSensorRead( mSensorRead ); + } + + + /** + * Not called by current j3d implementation. + */ + public void processStreamInput() + { + // Intentionally empty + } + + + /** + * Reset state. + */ + public void setNominalPositionAndOrientation() + { + mSensorRead.setTime( JXInputManager.getLastUpdateTime() ); + + mRotTransX.rotX( 0.0 ); + mRotTransY.rotY( 0.0 ); + mRotTransZ.rotZ( 0.0 ); + + mPosition.set( mInitPos ); + + mNewTransform.set( mPosition ); + + mNewTransform.mul( mRotTransX ); + mNewTransform.mul( mRotTransY ); + mNewTransform.mul( mRotTransZ ); + + mSensorRead.set( mNewTransform ); + mSensor.setNextSensorRead( mSensorRead ); + + } + + + /** + * Set the processing mode. + * Only NON_BLOCKING is allowed! + */ + public void setProcessingMode(int param) + { + if ( param != InputDevice.NON_BLOCKING ) + throw new IllegalArgumentException("Processing mode must be NON_BLOCKING"); + + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/package.html b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/package.html new file mode 100644 index 0000000..9b92964 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/package.html @@ -0,0 +1,11 @@ + + + + + + + +Connecting JXInput to Java3D by implementing the interface +javax.media.j3d.InputDevice. + + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/test/HelloUniverse.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/test/HelloUniverse.java new file mode 100644 index 0000000..fde34bc --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/test/HelloUniverse.java @@ -0,0 +1,205 @@ + +/* + * @(#)HelloUniverse.java 1.15 02/02/07 14:48:36 + * + * Copyright (c) 1996-2002 Sun Microsystems, Inc. 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. + * + * - Redistribution 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 Sun Microsystems, Inc. or 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 "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES + * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN + * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR + * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed,licensed or intended + * for use in the design, construction, operation or maintenance of + * any nuclear facility. + */ + +package de.hardcode.jxinput.j3d.test; + + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; +import com.sun.j3d.utils.applet.MainFrame; +import com.sun.j3d.utils.geometry.ColorCube; +import com.sun.j3d.utils.universe.*; +import javax.media.j3d.*; +import javax.vecmath.*; +import de.hardcode.jxinput.j3d.DeviceConfiguration; +import de.hardcode.jxinput.Axis; +import de.hardcode.jxinput.JXInputManager; +import de.hardcode.jxinput.j3d.IsActiveCondition; +import de.hardcode.jxinput.j3d.J3DInputDevice; +import de.hardcode.jxinput.j3d.IsActiveOnButtonCondition; + + +public class HelloUniverse extends Applet +{ + + private SimpleUniverse u = null; + TransformGroup objTrans; + + public BranchGroup createSceneGraph() + { + BranchGroup objRoot = new BranchGroup(); + objTrans = new TransformGroup(); + objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); + objRoot.addChild(objTrans); + objTrans.addChild(new ColorCube(0.4)); + +// Transform3D yAxis = new Transform3D(); +// Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, +// 0, 0, +// 4000, 0, 0, +// 0, 0, 0); +// RotationInterpolator rotator = new RotationInterpolator(rotationAlpha, objTrans, yAxis, +// 0.0f, (float) Math.PI*2.0f); +// BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); +// rotator.setSchedulingBounds(bounds); +// objTrans.addChild(rotator); + return objRoot; + } + + + public HelloUniverse() + { + + } + + public void init() + { + // These are the string arguments given to the VirtualInputDevice + // constructor. These are settable parameters. Look in the + // VirtualInputDevice constructor for a complete list. + String[] args = new String[10]; + args[0] = "printvalues"; + args[1] = "true"; + args[2] = "yscreeninitloc"; + args[3] = "50"; + args[4] = null; + + + // now create the HelloUniverse Canvas + setLayout(new BorderLayout()); + GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); + + Canvas3D c = new Canvas3D(config); + add("Center", c); + + // Create a simple scene and attach it to the virtual universe + BranchGroup scene = createSceneGraph(); + u = new SimpleUniverse(c); + + // + // Use the inputdevice + // + InputDevice device = createInputDevice(); + + // Register the VirtualInputDevice with Java 3D + u.getViewer().getPhysicalEnvironment().addInputDevice( device ); + +// TransformGroup viewTrans = u.getViewingPlatform().getViewPlatformTransform(); + + // Put the behavoir to teh object + SensorBehavior s = new SensorBehavior( objTrans, device.getSensor(0) ); + s.setSchedulingBounds( new BoundingSphere( new Point3d(0.0,0.0,0.0), Float.MAX_VALUE ) ); + objTrans.addChild( s ); + + u.getViewingPlatform().setNominalViewingTransform(); + u.addBranchGraph(scene); + } + + public void destroy() + { + u.removeAllLocales(); + } + + + /** + * Setup an input device. + */ + private InputDevice createInputDevice() + { + IsActiveCondition button1down = new IsActiveOnButtonCondition(JXInputManager.getJXInputDevice( 0 ).getButton( 0 ), true ); + IsActiveCondition button1up = new IsActiveOnButtonCondition(JXInputManager.getJXInputDevice( 0 ).getButton( 0 ), false ); + + Axis xaxis = JXInputManager.getJXInputDevice( 0 ).getAxis( Axis.ID_X ); + Axis yaxis = JXInputManager.getJXInputDevice( 0 ).getAxis( Axis.ID_Y ); + + DeviceConfiguration cnf = new DeviceConfiguration(); + + // + // Setup the configuration to use joysticks x/y for rotation is not button is pressed + // and for translation if button1 is pressed. + // + cnf.setRotational( + DeviceConfiguration.AXIS_Y, + xaxis, + button1up, + IsActiveCondition.NEVER, + 0.0, Math.PI + ); + + cnf.setRotational( + DeviceConfiguration.AXIS_X, + yaxis, + button1up, + IsActiveCondition.NEVER, + 0.0, Math.PI + ); + + cnf.setTranslational( + DeviceConfiguration.AXIS_Z, + yaxis, + button1down, + IsActiveCondition.NEVER, + -5.0, 4.0 + ); + cnf.setTranslational( + DeviceConfiguration.AXIS_X, + xaxis, + button1down, + IsActiveCondition.NEVER, + 0.0, 4.0 + ); + + // We have the config, create the device... + J3DInputDevice d = new J3DInputDevice( cnf ); + + // The InputDevice must be initialized before registering it + // with the PhysicalEnvironment object. + d.initialize(); + + return d; + } + + + public static void main(String[] args) + { + new MainFrame(new HelloUniverse(), 350, 350); + } +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/test/SensorBehavior.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/test/SensorBehavior.java new file mode 100644 index 0000000..6836ebb --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/j3d/test/SensorBehavior.java @@ -0,0 +1,70 @@ +package de.hardcode.jxinput.j3d.test; + +/* + * @(#)SensorBehavior.java 1.8 02/02/07 14:48:34 + * + * Copyright (c) 1996-2002 Sun Microsystems, Inc. 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. + * + * - Redistribution 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 Sun Microsystems, Inc. or 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 "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES + * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN + * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR + * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed,licensed or intended + * for use in the design, construction, operation or maintenance of + * any nuclear facility. + */ + +import javax.media.j3d.*; +import java.util.*; + +public class SensorBehavior extends Behavior +{ + private WakeupOnElapsedFrames conditions = new WakeupOnElapsedFrames(0); + private TransformGroup transformGroup; + private Sensor sensor; + private Transform3D transform = new Transform3D(); + + public SensorBehavior( TransformGroup tg, Sensor sensor ) + { + transformGroup = tg; + this.sensor = sensor; + } + + public void initialize() + { + wakeupOn( conditions ); + } + + public void processStimulus( Enumeration criteria ) + { + sensor.getRead( transform ); + transformGroup.setTransform( transform ); + wakeupOn( conditions ); + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/InvalidKeyCodeException.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/InvalidKeyCodeException.java new file mode 100644 index 0000000..f44ee6b --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/InvalidKeyCodeException.java @@ -0,0 +1,35 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 16. April 2002, 23:31 +//********************************************************************************************** +package de.hardcode.jxinput.keyboard; + +/** + * Exeception to be thrown if keycode is not in then range [0,255]. + * + * @author Herkules + */ +public class InvalidKeyCodeException + extends IllegalArgumentException +{ + + /** + * Creates a new instance of InvalidKeyCodeException. + */ + public InvalidKeyCodeException() + { + } + + + /** + * Creates a new instance of InvalidKeyCodeException. + */ + public InvalidKeyCodeException( String s ) + { + super( s ); + } +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/JXKeyboardInputDevice.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/JXKeyboardInputDevice.java new file mode 100644 index 0000000..858bdb7 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/JXKeyboardInputDevice.java @@ -0,0 +1,175 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 9. April 2002, 22:40 +//********************************************************************************************** +package de.hardcode.jxinput.keyboard; + + +import de.hardcode.jxinput.*; +import java.awt.Component; + + +/** + * Virtual input device treating a AWT keyboard as a source for Buttons. + * + * @author Herkules + */ +public class JXKeyboardInputDevice + implements JXInputDevice +{ + private static final String DEVICENAME = "Swing Keyboard"; + + /** The driver doing all the real work. */ + private final KeyboardDriver mDriver = new KeyboardDriver(); + + /** The Component I am listening to. */ + private Component mComponent = null; + + /** Hold the biggest keycode for which a button has been created. */ + private int mMaxIdxCreated = 0; + + + /** + * Creates a new instance of JXKeyboardInputDevice. + */ + public JXKeyboardInputDevice() + { + } + + + /** + * Creates a new instance of JXKeyboardInputDevice + * immediately listening to a JComponent. + */ + public JXKeyboardInputDevice( Component comp ) + { + listenTo( comp ); + } + + /** + * Makes this device listen to a certain JComponent. + */ + public final void listenTo( Component comp ) + { + shutdown(); + mComponent = comp; + mComponent.addKeyListener( mDriver ); + } + + /** + * Shut down. No longer listen to my JComponent. + */ + public final void shutdown() + { + if ( null != mComponent ) + mComponent.removeKeyListener( mDriver ); + } + + + /** + * Create a button object for a certain keycode. + */ + public Button createButton( int keycode ) + { + if ( 0 > keycode || 0x100 < keycode ) + throw new InvalidKeyCodeException(); + + KeyButton b; + if ( null == (b = mDriver.getButton( keycode ) ) ) + { + b = new KeyButton( keycode ); + mDriver.registerKeyButton( b ); + if ( keycode > mMaxIdxCreated ) + mMaxIdxCreated = keycode; + } + return b; + } + + + public void removeButton( Button b ) + { + mDriver.unregisterKeyButton( (KeyButton) b ); + } + + + + //********************************************************************************************* + // + // Implement JXInputDevice + // + //********************************************************************************************* + + public Axis getAxis(int idx) + { + // No axes on keyboard. + return null; + } + + + public Button getButton(int idx) + { + // idx is interpreted as the keycode + return mDriver.getButton( idx ); + } + + public Directional getDirectional(int idx) + { + // No directionals on keyboard. + return null; + } + + /** Maximum number of axes as an upper bound for index values. */ + public int getMaxNumberOfAxes() + { + // No axes on keyboard. + return 0; + } + + /** Maximum number of buttons as an upper bound for index values. */ + public int getMaxNumberOfButtons() + { + // Return biggest keycode (inclusive). + return mMaxIdxCreated + 1; + } + + /** Maximum number of directional features as an upper bound for index values. */ + public int getMaxNumberOfDirectionals() + { + // No directionals on keyboard. + return 0; + } + + /** + * Devices may have a name. + * This name might be provided by a system dependant driver. + */ + public String getName() + { + return DEVICENAME; + } + + /** Actual number of available axes. */ + public int getNumberOfAxes() + { + // No axes on keyboard. + return 0; + } + + /** Actual number of available buttons. */ + public int getNumberOfButtons() + { + return mDriver.getNumberOfButtons(); + } + + /** Actual number of available directional features. */ + public int getNumberOfDirectionals() + { + // No directionals on keyboard. + return 0; + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/KeyButton.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/KeyButton.java new file mode 100644 index 0000000..3fd7130 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/KeyButton.java @@ -0,0 +1,94 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 9. April 2002, 22:51 +//********************************************************************************************** +package de.hardcode.jxinput.keyboard; + +import de.hardcode.jxinput.Button; +import java.awt.event.KeyEvent; + + +/** + * Associates a keycode with a Button and handles the current state of that button. + * + * @author Herkules + */ +class KeyButton + implements Button +{ + private final int mKeyCode; + private boolean mIsPressed; + private boolean mHasChanged; + + /** + * Creates a new instance of KeyButton. + */ + public KeyButton( int keycode ) + { + mKeyCode = keycode; + } + + + /** + * Return the keycode assigned with this button. + */ + public final int getKeyCode() + { + return mKeyCode; + } + + final void setIsPressed( boolean flag ) + { + mIsPressed = flag; + } + + //********************************************************************************************* + // + // Implement Button + // + //********************************************************************************************* + + + /** + * Features may have a name provided e.g. by the driver. + */ + public String getName() + { + return KeyEvent.getKeyText( mKeyCode ); + } + + /** + * Tells the state of the button at last update. + */ + public boolean getState() + { + return mIsPressed; + } + + /** + * Retrieve the type of the button. + * Pushbutton will deliver true==getState() as long as they are pressed down. + * Togglebuttons will change their state once they are pressed and keep that state + * until they are pressed again. + * @return [ PUSHBUTTON | TOGGLEBUTTON ] + */ + public int getType() + { + return Button.PUSHBUTTON; + } + + + /** + * Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/KeyboardDriver.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/KeyboardDriver.java new file mode 100644 index 0000000..7eb6232 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/KeyboardDriver.java @@ -0,0 +1,141 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 9. April 2002, 22:43 +//********************************************************************************************** +package de.hardcode.jxinput.keyboard; + +import java.awt.event.KeyListener; +import java.awt.event.KeyEvent; +import java.util.HashMap; +import java.security.InvalidParameterException; + + + +/** + * Listen to a JComponent handle handle all associated button objects. + * This is the main worker class for JXKeyboardInputDevice. + * + * @author Herkules + */ +class KeyboardDriver implements KeyListener +{ +// HashMap mKeysToObserveMap = new HashMap(); + + int mNumberOfKeysObserved = 0; + KeyButton [] mKeysObserved = new KeyButton [ 0x100 ]; + + + /** + * Creates a new instance of KeyboardDriver. + */ + public KeyboardDriver() + { + } + + + /** + * How many buttons are registered? + */ + final int getNumberOfButtons() + { + return mNumberOfKeysObserved; +// return mKeysToObserveMap.size(); + } + + + /** + * Place a new button under my observation. + */ + final boolean registerKeyButton( KeyButton b ) + { + final int keycode = b.getKeyCode(); + + if ( 0 > keycode || 0x100 < keycode ) + throw new InvalidKeyCodeException(); + + if ( null == mKeysObserved[ keycode ] ) + { + mKeysObserved[ keycode ] = b; + mNumberOfKeysObserved++; + return true; + } + else + { + return false; + } + +// Integer code = new Integer( b.getKeyCode() ); +// if ( ! mKeysToObserveMap.containsKey( code ) ) +// { +// mKeysToObserveMap.put( code, b ); +// return true; +// } +// else +// { +// return false; +// } + } + + final void unregisterKeyButton( KeyButton b ) + { + final int keycode = b.getKeyCode(); + + if ( 0 > keycode || 0x100 < keycode ) + throw new InvalidKeyCodeException(); + + if ( null != mKeysObserved[ b.getKeyCode() ] ) + { + mKeysObserved[ keycode ] = null; + mNumberOfKeysObserved--; + } + +// Integer code = new Integer( b.getKeyCode() ); +// mKeysToObserveMap.remove( code ); + } + + + /** + * Retrieve the button from its keycode. + */ + final KeyButton getButton( int keycode ) + { + if ( 0 > keycode || 0x100 < keycode ) + throw new InvalidKeyCodeException(); + + return mKeysObserved[ keycode ]; + +// Integer code = new Integer( keycode ); +// return (KeyButton)mKeysToObserveMap.get( code ); + } + + + //********************************************************************************************* + // + // Implement KeyListener + // + //********************************************************************************************* + + public void keyPressed( KeyEvent keyEvent ) + { + KeyButton b = getButton( keyEvent.getKeyCode() ); + if ( null != b ) + b.setIsPressed( true ); + } + + public void keyReleased( KeyEvent keyEvent ) + { + KeyButton b = getButton( keyEvent.getKeyCode() ); + if ( null != b ) + b.setIsPressed( false ); + } + + public void keyTyped( KeyEvent keyEvent ) + { + // Intentionally empty. + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/package.html b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/package.html new file mode 100644 index 0000000..e1021d1 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/keyboard/package.html @@ -0,0 +1,10 @@ + + + + + de.hardcode.jxinput.keyboard + + +Connects Swing keyboard handling to the JXInput infrastructure. + + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/AxisListener.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/AxisListener.java new file mode 100644 index 0000000..7d2b138 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/AxisListener.java @@ -0,0 +1,39 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 20. Februar 2002, 22:19 +//********************************************************************************************** +package de.hardcode.jxinput.test; + +import de.hardcode.jxinput.event.JXInputEventManager; +import de.hardcode.jxinput.event.JXInputAxisEventListener; +import de.hardcode.jxinput.event.JXInputAxisEvent; +import de.hardcode.jxinput.Axis; + +/** + * Example listener to an axis. + * + * @author Herkules + */ +public class AxisListener + implements JXInputAxisEventListener +{ + + /** + * Creates a new instance of AxisListener. + */ + public AxisListener( Axis axis ) + { + JXInputEventManager.addListener( this, axis, 0.1 ); + } + + + public void changed( JXInputAxisEvent ev ) + { + System.out.println( "Axis " + ev.getAxis().getName() + " changed : value=" + ev.getAxis().getValue() + ", event causing delta=" + ev.getDelta() ); + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/ButtonListener.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/ButtonListener.java new file mode 100644 index 0000000..604002d --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/ButtonListener.java @@ -0,0 +1,38 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 20. Februar 2002, 22:19 +//********************************************************************************************** +package de.hardcode.jxinput.test; + +import de.hardcode.jxinput.event.JXInputEventManager; +import de.hardcode.jxinput.event.JXInputButtonEventListener; +import de.hardcode.jxinput.event.JXInputButtonEvent; +import de.hardcode.jxinput.Button; + +/** + * Sample button listener. + * + * @author Herkules + */ +public class ButtonListener implements JXInputButtonEventListener +{ + + /** + * Creates a new instance of AxisListener. + */ + public ButtonListener( Button button ) + { + JXInputEventManager.addListener( this, button ); + } + + + public void changed( JXInputButtonEvent ev ) + { + System.out.println( "Button " + ev.getButton().getName() + " changed : state=" + ev.getButton().getState() ); + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/DirectionalListener.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/DirectionalListener.java new file mode 100644 index 0000000..9f79796 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/DirectionalListener.java @@ -0,0 +1,37 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 20. Februar 2002, 22:19 +//********************************************************************************************** +package de.hardcode.jxinput.test; + +import de.hardcode.jxinput.event.JXInputEventManager; +import de.hardcode.jxinput.event.JXInputDirectionalEventListener; +import de.hardcode.jxinput.event.JXInputDirectionalEvent; +import de.hardcode.jxinput.Directional; + +/** + * Sample directional listener. + * + * @author Herkules + */ +public class DirectionalListener implements JXInputDirectionalEventListener +{ + /** + * Creates a new instance of AxisListener. + */ + public DirectionalListener( Directional directional ) + { + JXInputEventManager.addListener( this, directional, 1.0 ); + } + + + public void changed( JXInputDirectionalEvent ev ) + { + System.out.println( "Directional " + ev.getDirectional().getName() + " changed : direction=" + ev.getDirectional().getDirection() + ", value=" + ev.getDirectional().getValue() + ", event causing delta=" + ev.getDirectionDelta() ); + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputDevicePanel.form b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputDevicePanel.form new file mode 100644 index 0000000..fe9f69e --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputDevicePanel.form @@ -0,0 +1,97 @@ + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputDevicePanel.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputDevicePanel.java new file mode 100644 index 0000000..81fbef3 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputDevicePanel.java @@ -0,0 +1,296 @@ +/* + * JXInputDevicePanel.java + * + * Created on 23. Januar 2002, 22:19 + */ +package de.hardcode.jxinput.test; + +import de.hardcode.jxinput.JXInputManager; +import de.hardcode.jxinput.JXInputDevice; +import de.hardcode.jxinput.Axis; +import de.hardcode.jxinput.Directional; +import de.hardcode.jxinput.Button; + +import javax.swing.*; +import java.awt.GridLayout; +import java.util.ArrayList; +import java.util.Iterator; +import java.awt.BorderLayout; +import java.awt.Font; +import java.util.Dictionary; +import java.util.Enumeration; + +/** + * + * @author Herkules + */ +public class JXInputDevicePanel extends javax.swing.JPanel +{ + private static final Font AXIS_SLIDER_FONT = new Font( "Verdana", Font.PLAIN, 9 ); + + private final JXInputDevice mDev; + private final ArrayList mAxisSliders = new ArrayList(); + private final ArrayList mButtonCheckboxes = new ArrayList(); + private final ArrayList mDirectionalLabels = new ArrayList(); + + + /** Creates new form JXInputDevicePanel */ + public JXInputDevicePanel( JXInputDevice dev ) + { + mDev = dev; + initComponents(); + initFromDevice(); + } + + /** + * Helper class connecting a JSlider with an Axis. + */ + private class AxisSlider extends JSlider + { + Axis mAxis; + AxisSlider( Axis axis ) + { + super( ( Axis.SLIDER == axis.getType() ? 0 : -100 ), 100 ); + this.setMajorTickSpacing( Axis.SLIDER == axis.getType() ? 25 : 50 ); + this.setMinorTickSpacing( 5 ); + this.setPaintTicks( true ); + this.setPaintLabels( true ); + this.setEnabled( false ); + + Dictionary labeldict = this.getLabelTable(); + Enumeration labels = labeldict.elements(); + while ( labels.hasMoreElements() ) + { + JLabel label = (JLabel)labels.nextElement(); + label.setFont( AXIS_SLIDER_FONT ); + label.setSize( 32, 12 ); + label.setHorizontalAlignment( SwingConstants.LEFT ); + } + + mAxis = axis; + } + + void update() + { + int ax = (int)(mAxis.getValue() * 100.0); + + // + // Only if value really changes + // + if ( ax != this.getValue() ) + { + this.setValue( ax ); + this.setToolTipText( mAxis.getName() + ": " + Double.toString( mAxis.getValue() ) ); + } + } + + } + + + private class ButtonCheckbox extends JCheckBox + { + Button mButton; + ButtonCheckbox( Button button ) + { + super( button.getName() ); + this.setEnabled( false ); + mButton = button; + } + + void update() + { + boolean state = mButton.getState(); + + // + // Only if value really changes + // + if ( state != this.isSelected() ) + { + this.setSelected( state ); + } + } + } + + + private class DirectionalLabel extends JLabel + { + Directional mDirectional; + int mCurrent = 0; + + DirectionalLabel( Directional directional ) + { + super( directional.getName() ); + mDirectional = directional; + } + + void update() + { + int dir = mDirectional.getDirection(); + + // + // Only if value really changes + // + if ( dir != mCurrent ) + { + this.setText( mDirectional.getName() + ": " + ( mDirectional.isCentered() ? "-" : Integer.toString( dir ) ) ); + mCurrent = dir; + } + } + } + + + /** + * Setup the dialogs content from the JXInputDevice. + */ + void initFromDevice() + { + if ( null != mDev ) + { + ((GridLayout)mAxesPanel.getLayout()).setRows( mDev.getNumberOfAxes() ); + + for ( int i = 0; i < mDev.getMaxNumberOfAxes(); ++i ) + { + if ( null != mDev.getAxis( i ) ) + { + AxisSlider slider = new AxisSlider( mDev.getAxis( i ) ); + + JLabel name = new JLabel( mDev.getAxis( i ).getName() ); + name.setVerticalAlignment( SwingConstants.TOP ); + name.setHorizontalAlignment( SwingConstants.CENTER ); + name.setPreferredSize( new java.awt.Dimension( 90, 0 ) ); + + JPanel p = new JPanel(); + p.setLayout( new BorderLayout() ); + + p.add( name, BorderLayout.WEST ); + p.add( slider, BorderLayout.CENTER ); + + mAxesPanel.add( p ); + + // Add to list of all AxisSlider controls + mAxisSliders.add( slider ); + + // Add an event listener: + new AxisListener( mDev.getAxis( i ) ); + } + } + + + ((GridLayout)mButtonsPanel.getLayout()).setRows( mDev.getNumberOfButtons() ); + for ( int i = 0; i < mDev.getMaxNumberOfButtons(); ++i ) + { + if ( null != mDev.getButton( i ) ) + { + ButtonCheckbox chk = new ButtonCheckbox( mDev.getButton( i ) ); + mButtonCheckboxes.add( chk ); + mButtonsPanel.add( chk ); + + // Add an event listener: + new ButtonListener( mDev.getButton( i ) ); + } + } + + ((GridLayout)mDirectionalPanel.getLayout()).setRows( mDev.getNumberOfDirectionals() / 2 ); + for ( int i = 0; i < mDev.getMaxNumberOfDirectionals(); ++i ) + { + if ( null != mDev.getDirectional( i ) ) + { + DirectionalLabel lbl = new DirectionalLabel( mDev.getDirectional( i ) ); + mDirectionalLabels.add( lbl ); + mDirectionalPanel.add( lbl ); + + // Add an event listener: + new DirectionalListener( mDev.getDirectional( i ) ); + } + } + } + } + + + public void update() + { + Iterator it = mAxisSliders.iterator(); + while ( it.hasNext() ) + { + ((AxisSlider)it.next()).update(); + } + + it = mButtonCheckboxes.iterator(); + while ( it.hasNext() ) + { + ((ButtonCheckbox)it.next()).update(); + } + + it = mDirectionalLabels.iterator(); + while ( it.hasNext() ) + { + ((DirectionalLabel)it.next()).update(); + } + } + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() + { + mAxesPanelContainer = new javax.swing.JPanel(); + mAxesPanel = new javax.swing.JPanel(); + mDirectionalPanel = new javax.swing.JPanel(); + mButtonScrollPane = new javax.swing.JScrollPane(); + mButtonsPanel = new javax.swing.JPanel(); + + setLayout(new java.awt.BorderLayout(2, 2)); + + addComponentListener(new java.awt.event.ComponentAdapter() + { + public void componentShown(java.awt.event.ComponentEvent evt) + { + OnShow(evt); + } + }); + + mAxesPanelContainer.setLayout(new java.awt.BorderLayout()); + + mAxesPanelContainer.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + mAxesPanel.setLayout(new java.awt.GridLayout(1, 1, 0, 20)); + + mAxesPanelContainer.add(mAxesPanel, java.awt.BorderLayout.NORTH); + + add(mAxesPanelContainer, java.awt.BorderLayout.CENTER); + + mDirectionalPanel.setLayout(new java.awt.GridLayout(1, 1)); + + mDirectionalPanel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + add(mDirectionalPanel, java.awt.BorderLayout.SOUTH); + + mButtonsPanel.setLayout(new java.awt.GridLayout(1, 1)); + + mButtonsPanel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + mButtonScrollPane.setViewportView(mButtonsPanel); + + add(mButtonScrollPane, java.awt.BorderLayout.EAST); + + }// //GEN-END:initComponents + + private void OnShow(java.awt.event.ComponentEvent evt)//GEN-FIRST:event_OnShow + {//GEN-HEADEREND:event_OnShow + // Commented: the focus is held by a parent component +// System.out.println("OnShow"); +// this.requestFocus(); + }//GEN-LAST:event_OnShow + + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel mAxesPanel; + private javax.swing.JPanel mAxesPanelContainer; + private javax.swing.JScrollPane mButtonScrollPane; + private javax.swing.JPanel mButtonsPanel; + private javax.swing.JPanel mDirectionalPanel; + // End of variables declaration//GEN-END:variables + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputTestDialog.form b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputTestDialog.form new file mode 100644 index 0000000..1abc589 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputTestDialog.form @@ -0,0 +1,79 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputTestDialog.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputTestDialog.java new file mode 100644 index 0000000..3829aa2 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/test/JXInputTestDialog.java @@ -0,0 +1,286 @@ +//********************************************************************************************** +// Dipl. Phys. Joerg Plewe, HARDCODE Development +// Created on 27. Dezember 2001, 01:15 +//********************************************************************************************** + +package de.hardcode.jxinput.test; + +import de.hardcode.jxinput.*; +import de.hardcode.jxinput.event.*; +import de.hardcode.jxinput.keyboard.JXKeyboardInputDevice; +import de.hardcode.jxinput.virtual.JXVirtualInputDevice; +import de.hardcode.jxinput.virtual.VirtualAxis; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + + +/** + * Test dialog showing some features of JXInput. + * @author Herkules + */ +public class JXInputTestDialog extends javax.swing.JDialog + implements ActionListener +{ + + private JXKeyboardInputDevice mKeyboardDevice = null; + private JXVirtualInputDevice mVirtualDevice = null; + + Button mButtonUp; + Button mButtonDown; + Button mButtonLeft; + Button mButtonRight; + Button mButtonFire; + Button mButtonSpace; + + /** Creates new form JXInputTestDialog */ + public JXInputTestDialog(java.awt.Frame parent, boolean modal) + { + super(parent, modal); + initComponents(); + configureKeyboardInputDevice(); + configureVirtualInputDevice(); + initDevicePanels(); + pack(); + + // Request the focus so that the keyboarddevice can work + mMainPanel.requestFocus(); + + new Timer( 50, this ).start(); + + // Uncomment this line as an alternative to the Timer above. + // Don't use both!! + //JXInputEventManager.setTriggerIntervall( 50 ); + } + + + /** + * Implement ActionListener#actionPerformed(). + * This is called by the Timer. + */ + public void actionPerformed( ActionEvent e ) + { + JXInputManager.updateFeatures(); + SwingUtilities.invokeLater( + new Runnable() + { + public void run() + { + for ( int i = 0; i < mDevicesTabbedPane.getComponentCount(); ++i ) + { + ((JXInputDevicePanel)mDevicesTabbedPane.getComponent( i )).update(); + } + } + } + ); + } + + + /** + * Configure a test JXKeyboardInputdevice. + */ + void configureKeyboardInputDevice() + { + mKeyboardDevice = JXInputManager.createKeyboardDevice(); + + mKeyboardDevice.createButton( KeyEvent.VK_ESCAPE ); + + mKeyboardDevice.createButton( KeyEvent.VK_F1 ); + mKeyboardDevice.createButton( KeyEvent.VK_F2 ); + mKeyboardDevice.createButton( KeyEvent.VK_F3 ); + mKeyboardDevice.createButton( KeyEvent.VK_F4 ); + + mKeyboardDevice.createButton( KeyEvent.VK_LEFT ); + mKeyboardDevice.createButton( KeyEvent.VK_RIGHT ); + mKeyboardDevice.createButton( KeyEvent.VK_UP ); + mKeyboardDevice.createButton( KeyEvent.VK_DOWN ); + + mKeyboardDevice.createButton( KeyEvent.VK_PAGE_UP ); + mKeyboardDevice.createButton( KeyEvent.VK_PAGE_DOWN ); + + mButtonSpace = mKeyboardDevice.createButton( KeyEvent.VK_SPACE ); + mButtonLeft = mKeyboardDevice.createButton( KeyEvent.VK_A ); + mButtonRight = mKeyboardDevice.createButton( KeyEvent.VK_D ); + mButtonDown = mKeyboardDevice.createButton( KeyEvent.VK_S ); + mButtonUp = mKeyboardDevice.createButton( KeyEvent.VK_W ); + + // Configure it to make it listen to the main panel. + // I try to keep the kbd focus on it. + mKeyboardDevice.listenTo( mMainPanel ); + } + + + /** + * Configure a test JXVirtualInputdevice. + */ + void configureVirtualInputDevice() + { + mVirtualDevice = JXInputManager.createVirtualDevice(); + + Button firebutton; + // + // Remember 'fire' button of first device for use + // in the virtual device. + // For we ran configureKeyboardInputDevice() before, + // getJXInputDevice( 0 ) should not return null + // + firebutton = JXInputManager.getJXInputDevice( 0 ).getButton( 0 ); + + VirtualAxis x = mVirtualDevice.createAxis( Axis.ID_X ); + x.setButtons( mButtonRight, mButtonLeft ); + x.setName( "x: A-D" ); + + VirtualAxis y = mVirtualDevice.createAxis( Axis.ID_Y ); + y.setButtons( mButtonUp, mButtonDown ); + y.setSpringSpeed( 0.0 ); + y.setName( "y: S|W" ); + + VirtualAxis slider = mVirtualDevice.createAxis( Axis.ID_SLIDER0 ); + slider.setIncreaseButton( mButtonSpace ); + slider.setTimeFor0To1( 2000 ); + slider.setName( "" ); + slider.setType( Axis.SLIDER ); + + if ( null != firebutton ) + { + slider = mVirtualDevice.createAxis( Axis.ID_SLIDER1 ); + slider.setIncreaseButton( firebutton ); + slider.setTimeFor0To1( 2000 ); + slider.setName( "JoyButton 0" ); + } + + + } + + + /** + * Initialize one panel for each device available. + */ + void initDevicePanels() + { + int cnt = JXInputManager.getNumberOfDevices(); + + mLabelNoDevice.setVisible( cnt == 0 ); + mDevicesTabbedPane.setVisible( cnt != 0 ); + + for ( int i = 0; i < cnt; ++i ) + { + JXInputDevice dev = JXInputManager.getJXInputDevice( i ); + if ( null != dev ) + { + // + // Setup an own panel for each device. + // + JPanel panel = new JXInputDevicePanel( dev ); + mDevicesTabbedPane.addTab( dev.getName(), panel ); + } + } + } + + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() + { + mMainPanel = new javax.swing.JPanel(); + mLabelNoDevice = new javax.swing.JLabel(); + mDevicesTabbedPane = new javax.swing.JTabbedPane(); + mButtonReset = new javax.swing.JButton(); + + setTitle("JXInput (C) 2001-2006 HARDCODE Dev."); + addWindowListener(new java.awt.event.WindowAdapter() + { + public void windowClosing(java.awt.event.WindowEvent evt) + { + closeDialog(evt); + } + }); + + mMainPanel.setLayout(new java.awt.BorderLayout(10, 0)); + + mLabelNoDevice.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + mLabelNoDevice.setText("No JXInputDevice available!"); + mLabelNoDevice.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED)); + mMainPanel.add(mLabelNoDevice, java.awt.BorderLayout.NORTH); + + mDevicesTabbedPane.addFocusListener(new java.awt.event.FocusAdapter() + { + public void focusGained(java.awt.event.FocusEvent evt) + { + mDevicesTabbedPaneFocusGained(evt); + } + }); + + mMainPanel.add(mDevicesTabbedPane, java.awt.BorderLayout.CENTER); + + mButtonReset.setText("Reset "); + mButtonReset.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent evt) + { + mButtonResetActionPerformed(evt); + } + }); + + mMainPanel.add(mButtonReset, java.awt.BorderLayout.SOUTH); + + getContentPane().add(mMainPanel, java.awt.BorderLayout.CENTER); + + pack(); + }// //GEN-END:initComponents + + private void mButtonResetActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_mButtonResetActionPerformed + {//GEN-HEADEREND:event_mButtonResetActionPerformed + + while ( this.mDevicesTabbedPane.getTabCount() > 0 ) + this.mDevicesTabbedPane.removeTabAt( 0 ); + + JXInputManager.reset(); + configureKeyboardInputDevice(); + configureVirtualInputDevice(); + initDevicePanels(); + pack(); + + // Request the focus so that the keyboarddevice can work + mMainPanel.requestFocus(); + + }//GEN-LAST:event_mButtonResetActionPerformed + + private void mDevicesTabbedPaneFocusGained(java.awt.event.FocusEvent evt)//GEN-FIRST:event_mDevicesTabbedPaneFocusGained + {//GEN-HEADEREND:event_mDevicesTabbedPaneFocusGained + // Switch focus back to main panel! + this.mMainPanel.requestFocus(); + }//GEN-LAST:event_mDevicesTabbedPaneFocusGained + + /** Closes the dialog */ + private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog + setVisible(false); + dispose(); + System.exit( 0 ); + }//GEN-LAST:event_closeDialog + + /** + * Allow the dialog to run standalone. + * @param args the command line arguments + */ + public static void main(String args[]) + { + new JXInputTestDialog(new javax.swing.JFrame(), true).setVisible(true); + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton mButtonReset; + private javax.swing.JTabbedPane mDevicesTabbedPane; + private javax.swing.JLabel mLabelNoDevice; + private javax.swing.JPanel mMainPanel; + // End of variables declaration//GEN-END:variables + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/util/LatestChangedValueAxis.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/util/LatestChangedValueAxis.java new file mode 100644 index 0000000..f4f2c35 --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/util/LatestChangedValueAxis.java @@ -0,0 +1,98 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 17. April 2002, 23:24 +//********************************************************************************************** +package de.hardcode.jxinput.util; + +import de.hardcode.jxinput.Axis; + +/** + * + * @author Herkules + */ +public class LatestChangedValueAxis implements Axis +{ + private final Axis mAxis1; + private final Axis mAxis2; + private Axis mAxisInUse; + + private double mSaved1; + private double mSaved2; + + /** + * Creates a new instance of MeanValueAxis. + */ + public LatestChangedValueAxis(Axis a1, Axis a2) + { + mAxis1 = a1; + mAxis2 = a2; + mAxisInUse = a1; + + mSaved1 = a1.getValue(); + mSaved2 = a2.getValue(); + } + + /** + * Features may have a name provided e.g. by the driver. + */ + public String getName() + { + return mAxis1.getName(); + } + + /** Inform about the resolution of the axis. + * + * @return resolution, e.g. 2^-16 + */ + public double getResolution() + { + return mAxis1.getResolution(); + } + + /** + * Retrieve the type of the axis. + * + * @return [ TRANSLATION | ROTATION | SLIDER ] + */ + public int getType() + { + return mAxis1.getType(); + } + + /** Returns the current value of the axis. + * The range of the result depends on the axis type. + *s + * @return value [-1.0,1.0] or [0.0,1.0] + */ + public double getValue() + { + double v1 = mAxis1.getValue(); + double v2 = mAxis2.getValue(); + + if ( Math.abs( v2 - mSaved2 ) > 0.2 ) + { + mAxisInUse = mAxis2; + mSaved2 = v2; + } + if ( Math.abs( v1 - mSaved1 ) > 0.2 ) + { + mAxisInUse = mAxis1; + mSaved1 = v1; + } + + return mAxisInUse.getValue(); + } + + /** Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/util/OrButton.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/util/OrButton.java new file mode 100644 index 0000000..338538c --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/util/OrButton.java @@ -0,0 +1,52 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 23. Dezember 2002, 19:21 +//********************************************************************************************** +package de.hardcode.jxinput.util; + +import de.hardcode.jxinput.Button; + +/** + * + * @author Herkules + */ +public class OrButton implements Button +{ + private final Button mButton1; + private final Button mButton2; + + + /** + * Creates a new instance of OrButton. + */ + public OrButton( Button b1, Button b2 ) + { + mButton1 = b1; + mButton2 = b2; + } + + public String getName() + { + return mButton1.getName(); + } + + public boolean getState() + { + return mButton1.getState() || mButton2.getState(); + } + + public int getType() + { + return mButton1.getType(); + } + + public boolean hasChanged() + { + return mButton1.hasChanged() || mButton2.hasChanged(); + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/JXVirtualInputDevice.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/JXVirtualInputDevice.java new file mode 100644 index 0000000..aa125af --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/JXVirtualInputDevice.java @@ -0,0 +1,140 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 9. April 2002, 22:40 +//********************************************************************************************** +package de.hardcode.jxinput.virtual; + + +import de.hardcode.jxinput.*; + + +/** + * Virtual input device. + * + * @author Herkules + */ +public class JXVirtualInputDevice implements JXInputDevice +{ + private static final String DEVICENAME = "Virtual Device"; + + /** The driver doing all the real work. */ + private final VirtualDriver mDriver = new VirtualDriver(); + + + /** + * Creates a new instance of JXKeyboardInputDevice. + */ + public JXVirtualInputDevice() + { + } + + + /** + * The virtual input device needs to be updated regularly. + */ + public final void update( long deltaT ) + { + // + // Delegate the update call to the driver. + // + mDriver.update( deltaT ); + } + + /** + * Create a virtual axis object with a certain ID, e.g. Axis.ID_X. + */ + public VirtualAxis createAxis( int id ) + { + VirtualAxis a; + a = new VirtualAxis( id ); + mDriver.registerVirtualAxis( id, a ); + return a; + } + + + public void removeAxis( VirtualAxis a ) + { + mDriver.unregisterVirtualAxis( a ); + } + + + + //********************************************************************************************* + // + // Implement JXInputDevice + // + //********************************************************************************************* + + public Axis getAxis(int idx) + { + return mDriver.getAxis( idx ); + } + + + public Button getButton(int idx) + { + // No virtual buttons. + return null; + } + + + public Directional getDirectional(int idx) + { + // No virtual directionals. + return null; + } + + /** Maximum number of axes as an upper bound for index values. */ + public int getMaxNumberOfAxes() + { + return Axis.NUMBER_OF_ID; + } + + /** Maximum number of buttons as an upper bound for index values. */ + public int getMaxNumberOfButtons() + { + // No virtual buttons. + return 0; + } + + /** Maximum number of directional features as an upper bound for index values. */ + public int getMaxNumberOfDirectionals() + { + // No virtual directionals. + return 0; + } + + /** + * Devices may have a name. + * This name might be provided by a system dependant driver. + */ + public String getName() + { + return DEVICENAME; + } + + /** Actual number of available axes. */ + public int getNumberOfAxes() + { + // No axes on keyboard. + return mDriver.getNumberOfAxes(); + } + + /** Actual number of available buttons. */ + public int getNumberOfButtons() + { + return 0; + } + + /** Actual number of available directional features. */ + public int getNumberOfDirectionals() + { + // No directionals on keyboard. + return 0; + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/VirtualAxis.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/VirtualAxis.java new file mode 100644 index 0000000..b272c6e --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/VirtualAxis.java @@ -0,0 +1,207 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 11. April 2002, 23:40 +//********************************************************************************************** +package de.hardcode.jxinput.virtual; + +import de.hardcode.jxinput.Axis; +import de.hardcode.jxinput.Button; +import java.security.InvalidParameterException; + +/** + * + * @author Jörg Plewe + */ +public class VirtualAxis + implements Axis +{ + + private int mType = Axis.TRANSLATION; + private final int mID; + private String mName = "VirtualAxis"; + private double mCurrentValue = 0; + + private Button mButtonIncrease = null; + private Button mButtonDecrease = null; + private double mSpeed = 1.0 / 500.0; + private double mSpringSpeed = 1.0 / 500.0; + + /** + * Creates a new instance of VirtualAxis. + */ + public VirtualAxis( int id ) + { + mID = id; + } + + + /** + * Set the type of this axis to be either Axis.ROTATION, + * Axis.TRANSLATION or Axis.SLIDER. + */ + public void setType( int type ) + { + if ( Axis.ROTATION != type + && Axis.TRANSLATION != type + && Axis.SLIDER != type + ) + throw new InvalidParameterException( "Invalid type for axis!" ); + + mType = type; + } + + /** + * Update features under my control. + */ + final void update( long deltaT ) + { + double change = mSpeed * deltaT; + double springchange = mSpringSpeed * deltaT; + boolean doincrease = ( null != mButtonIncrease && mButtonIncrease.getState() ); + boolean dodecrease = ( null != mButtonDecrease && mButtonDecrease.getState() ); + boolean iscontrolled = doincrease || dodecrease; + + double controlledchange = 0.0; + if ( doincrease ) + controlledchange += change; + if ( dodecrease ) + controlledchange -= change; + + mCurrentValue += controlledchange; + + if ( mCurrentValue > 0.0 && ! doincrease ) + { + springchange = Math.min( mCurrentValue, springchange ); + mCurrentValue -= springchange; + } + if ( mCurrentValue < 0.0 && ! dodecrease ) + { + springchange = Math.min( -mCurrentValue, springchange ); + mCurrentValue += springchange; + } + + // + // Hold value within range + // + if ( mCurrentValue > 1.0 ) + mCurrentValue = 1.0; + double lowerlimit = Axis.SLIDER == mType ? 0.0 : -1.0; + if ( mCurrentValue < lowerlimit ) + mCurrentValue = lowerlimit; + } + + + /** + * Set the button to increase the axis for a single button axis. + */ + public final void setIncreaseButton( Button b ) + { + if ( null == b ) + throw new InvalidParameterException( "Button may not be null!" ); + + mButtonIncrease = b; + } + + + /** + * Set the buttons to increase and descrease the axis. + */ + public final void setButtons( Button increase, Button decrease ) + { + if ( null == increase || null == decrease ) + throw new InvalidParameterException( "Buttons may not be null!" ); + + mButtonIncrease = increase; + mButtonDecrease = decrease; + } + + + public final void setSpeed( double speed ) + { + mSpeed = speed; + } + + public final void setSpringSpeed( double springspeed ) + { + mSpringSpeed = springspeed; + } + + + public final void setTimeFor0To1( int ms ) + { + if ( 0 >= ms ) + mSpeed = 0.0; + else + mSpeed = 1.0/ ms; + } + public final void setTimeFor1To0( int ms ) + { + if ( 0 >= ms ) + mSpringSpeed = 0.0; + else + mSpringSpeed = 1.0/ ms; + } + + + public final void setName( String name ) + { + mName = name; + } + + //********************************************************************************************* + // + // Implement Axis + // + //********************************************************************************************* + + /** + * Features may have a name provided e.g. by the driver. + */ + public String getName() + { + return mName; + } + + /** + * Inform about the resolution of the axis. + * + * @return resolution, e.g. 2^-16 + */ + public double getResolution() + { + return 1.0/65536.0; + } + + + /** + * Retrieve the type of the axis. + * @return [ TRANSLATION | ROTATION | SLIDER ] + */ + public int getType() + { + return mType; + } + + /** Returns the current value of the axis. + * The range of the result depends on the axis type. + * + * @return value [-1.0,1.0] or [0.0,1.0] + */ + public double getValue() + { + return mCurrentValue; + } + + /** Denote wether this feature has changed beyond it's resolution since it got last + * updated. + */ + public boolean hasChanged() + { + return true; + } + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/VirtualDriver.java b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/VirtualDriver.java new file mode 100644 index 0000000..5952eff --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/VirtualDriver.java @@ -0,0 +1,95 @@ +//********************************************************************************************** +// (C) Copyright 2002 by Dipl. Phys. Joerg Plewe, HARDCODE Development +// All rights reserved. Copying, modification, +// distribution or publication without the prior written +// consent of the author is prohibited. +// +// Created on 9. April 2002, 22:43 +//********************************************************************************************** +package de.hardcode.jxinput.virtual; + +import java.util.ArrayList; +import de.hardcode.jxinput.Axis; + + + +/** + * This is the main worker class for JXVirtualInputDevice. + * + * @author Herkules + */ +class VirtualDriver +{ + + private final VirtualAxis[] mVAxes = new VirtualAxis[ Axis.NUMBER_OF_ID ]; + + /** + * Creates a new instance of KeyboardDriver. + */ + VirtualDriver() + { + } + + + /** + * Update features under my control. + */ + final void update( long deltaT ) + { + // + // Delegate the update call to the axes in use. + // + for ( int i = 0; i < mVAxes.length; i++ ) + { + if ( null != mVAxes[ i ] ) + mVAxes[ i ].update( deltaT ); + } + } + + + /** + * How many axes are registered? + */ + final int getNumberOfAxes() + { + int ctr = 0; + for ( int i = 0; i < mVAxes.length; i++ ) + { + if ( null != mVAxes[ i ] ) + ctr++; + } + return ctr; + } + + Axis getAxis(int idx) + { + return mVAxes[ idx ]; + } + + + /** + * Place a new axis under my observation. + */ + final void registerVirtualAxis( int id, VirtualAxis a ) + { + mVAxes[ id ] = a; + } + + + /** + * Remove an axis from my control. + */ + final void unregisterVirtualAxis( VirtualAxis a ) + { + for ( int i = 0; i < mVAxes.length; ++i ) + { + if ( mVAxes[ i ] == a ) + { + mVAxes[ i ] = null; + break; + } + } + } + + +} diff --git a/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/package.html b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/package.html new file mode 100644 index 0000000..d8e1d6a --- /dev/null +++ b/vendor/JXInput/0.3.4/java/de/hardcode/jxinput/virtual/package.html @@ -0,0 +1,11 @@ + + + + + de.hardcode.jxinput.virtual + + +Allows to define virtual axes that are not derived from any device +but from other JXInput feature objects. + + diff --git a/vendor/JXInput/0.3.4/jxinput.dll b/vendor/JXInput/0.3.4/jxinput.dll new file mode 100644 index 0000000000000000000000000000000000000000..720b9bba7fad06f7369a20c898c67bcf5e717069 GIT binary patch literal 94208 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¬>YJ!si#5@ zP6kK62y3j=mSJg~xL}!jinf}BMR*+)qo(88kj(wHXe=z}C}(|Hg! zb785))(lLq6?8AmN=Rg=1p4G4hKV{Ql1y(<1hVfiikVYAthk}B(H#uYx!TBC^@6cU z-a?Y-5p84`${OwpDVEPgM)y(P`0X&PJH95#iSws>7^h(HZ;+}u&=f$IknfFaL~pQR zjoB6RR_$L8RM05wQ+9aKP~|oQr})D8MFYUFE{Y31y)ZtQob70)!!Sa12`$RTDWjDz zAr!p15Ug5Q$!RUN$?n)bgp9$4PcQ`Dz*k89v~5CjkE3}n0LQZ)!|`lS|IhF}rkHdT z!*C15KKmU#`8d@Y`psG*IcB}9aHBLV!ZRGt&T~8)hSk*F*A`rgNLz^uuKga%V%N~- zk0DAt9=JHD2hj`g$H9Jp)_}vA>an_h76D$7MdE5M{u>P8+7x|}J+#Of(pRFKn>Vm) z7i`e;7ZexYq@G|W_yuqx>HibNY;dV{vRv%y+&qY~8|gg9ERZm?Xv&@uYM{+le4~0A zCye-N6pA8Y^2B{yxXvw%d)pvhqQ5PiO+AhKIY<-Qk29^Yt47ZJ2b~(P%?NN}03 zY+0Yd)8JvkhV+J`Jd3;q)&$UR{5Sa2-8R=E+0k4@#LvNyG@UVUSRPf^xPjGO@5 z{uILC^H5VbL%o@8?=Yc@0b#3V8)`M4rCfaCG};tm+n+u!LCv`YPvuYo<5?92F2(`xe8jm2E-(Q;&YV_XHv~8#q?0}1!Q&IhRRFA^} zKcfVN_YC7;&tmyp@Iw@=MVw329v^>z05O%u=m#$sVl^M!Oa#@Ss9`G)01<5zAXG+y z@Hqh3)Of3#?l-YX6Ib<7cI|%L<1`MVGL{MF+RD_!Y&*3unF>Q1frW4^hTPv)Q3*^) z^8f#VN%bvsrUSd4Ujx1cK9=t~rOc?pwN&qb?Qon#xfHh!qQ9`&=cjo|oRGlX`CDml zvq%m30bpm-CPR*tfWrLc*UPj8&I7{`WT&XhL9x-H>Nl^f6xq9hiMX%lh*MhC~RrGkUR)# zWs*XRrka|ulLhx94wg5^vvR4{C&#XmGN-*B47o=kBj{uot^Crnz==q>014p_Or8&% z0V8<)h9q)Ly>~ul6ZT-;r&KR0y1Ee&NEiz6& zGF!-@(wDT;leSFM!Z~s3y-Z>(M!gwh)B~X#&_Rg?kn<@21;k&-ebfuh1%FU%4|}OE z`SBUh5!}b|jYEwzyCkO>*1WwxjyGP&$&P6Ii?FdYdGQ8SC!`M(A)!|C)X$vRt@dq%6B;t z!N+y^nTmfQ(>nJsB2Xyjk*ZdrzirHRa2` zCj%}0M6(;cCvy_Gpe`uz%0}1)ut)%&H(+k~o(zRXdY&-1cu$5+*DKsVeow}ob|tb{ z0ayiC1K0rA4A=_T4?x}g3*M8V%pC0v`0oU?0fJues+-$+PX=8-v{}$Wq5wiIm!>)v z2U!O?$9{$>J!t^r#94Ho(3}S1EKN(%l%RZT!KaR7k>6c@6i`L6y|OMIp}FXASNF#$^RomduNcExT-a+(-$3@6+++CR}zn=%#3 z9ewN{Oeg$c2VmE<<)5- z=rE|m2m$>7G(v>3!!xM`z`k%_JV#SyZFXGUxG{U9vlxP74r`q~2C7j_r|dl8F4IYS z44(!U+^$b?CbLzB5zo@G+4no#*P&X(xPT?)EXN+&1=#x{4GwI#J2eGcJMwQa*aZhx zm-ZiPq8DZ0b+Dw$tXq!e2^jw`mG_(f7|p?$%#1ce`4){CC{ z!n^V<&=uJrfOZWSA{YnpNE!6yTl_D*frJCNaOWu;GDv6TAKe@9Vn+?7f_SJVR}@L-*>_xS~Y0ygwZ;E6`nL@I#QLw{sxE2}YxSh#U!c~g%K?E;?9?yj6AqZ+ zO%8HQ2~tlMKp8l#WcMUa{=kT7wkyzWK_WQp7ocU@=LIECPDq`G3$fVs#U)PL{k1rM zW;hAiy_l%4ucd#7>0cfGaZ1wqkl=TUI)M+R?ic5^1o1F!$5TyE`R#%LHV@}dvotlu zeiVSJqg_eyoxOJvBh3}(45LL%*;?+_TBE(R9`kzJ&w*tVpx783H!ZxzG6Wz1WQEsQ zW1T6u6F~bV^|)rL zgvViF)EgZQw+G-kXSj+jMKGo7t(}D4I{N3jYbTX=9sP3!?4%N}qknG6<^-o{C#{wm z@b(F|op3}_5BjQ24c1=R$sd7+qBb?sC3?*%6qWWmuG)SUSOQQuJVf#{-#WlC39{@b z?PD|Gj`jScEPH(2{;^prkPNwuINLGVHvA>iDyz_dx3@iMLOkX^-uT zyJ%-!pE%$A8_@ChtleePLE&dve1x*FAJNR9esKtrB1t`4EacZ4c|$6)`-= zp=s~*4SZlk_`(s?1ndBQH=(O^FM5L#Zm39d&yn9 zxQm8x&OShN8ZL#jS`$eDjB_O9kZ~gs(!ca`TCq+=RRB*P%ix@4m(X5W&4CEfFDC<^ zI9iY(6E+3Eok!PV5$}xOfi%`r@;FSR%L#Z5>J%!+HOhUM2W@CL&$}Da&>iP_6{TnC z8$z@KP6Y#P2f67-yFw#@H!DF*g*c002;Q?hq1&Z!S@q%~ri00prEoObNILUaq#d~VH5=_=&rsE6YOwT_O; zu;1W}e+5a=24N935@=q=#mxj*xgs=~V8v0QH3%5Iijqv*gXp*ojBplzE)4dOMIZ>B zfi5HJ>|BF{(r}rBy~*Jmv<|VF4x?cr6>LA?OkxrG(P>TF;N&heG{E44?y3?kgikET z7c%UFD}~&F=q|SKbRa6Md#t@5hOT$S%Uey(kZSDah>5@AWIHcSFYc% zn50~X06NeV?im1!0*N6RDvB>DiVpzZ4p_-IF}p5(%P4%1-hG9g{qfdy*$& zCwaAWagCjJVJ>v6>DVXiB<}zwd6(EpUNAe!6Ln1Tg4~ll0XNBGr*`ZlPk>2Y&~-Ds zSv0Hb`~f8r7ZC;4(x{6YeCSSFzd)G8)-T*>W`zawXjUp{{epL520c?5z?IrL0-Obw z=eEMcm~A+BY(qQ6b%qPn>zSG{|F@^%Q6~smzX>+TxytsOXQ`*8dkge}+B9mBoRX4e z_~Mio`pv#ca0-#qetuX3xvi(<+D|1of5LGw91pXO&2Go9;JE%WKG-X97L0)G7MNQf zJ>A}6yKZa*4bR!aWs%_Af=IYYxc(~QS%Py`d)!yUecJjqxUQprkX(YUhWTnG8_taL z3G#2R1CIAs#b1~_7n@ZLljr(C`jrOW)H z-WBm89KtfLDAt0PRHW;uV90e?f^&fgL%NM$i%NHTId{L*m*TNq?$%^W-e7F3L zWdXQ|aj5emMu>AVrQ=?`ZsjCi*tspcHddzvPqm70lS72{ueG0h1&Rx#y|B&4-T~>? z6%9cL8XqApE`SVl9b{L{to0a_k3+24DqJ3b{PUb79r)o?h`*%HdRWC*qd zFcOYag;)ee%^_Zt3I=m*1)J*#r?WW*$6dqfl!pb+0xMq*Aay?A!m_o-OEb25d znkn8L^QSjOOk#)9iOg{hn-+$A*@8A1Zu`cGEc(vEC7zR+9grB_h*~rop#D*_NPx5L*GA&Kp5PONv*4D64 zg<9h3^e*R2oF6!@qBHn(e=n9Q`&p{gJbxWk+CY_d1l)?k;?0M5zo&MBOxi#pv`7z; z(A`sxe0huOeh>$JIJRPN&`)~uE;uzP8(x00HUsO{&jz#%MRe!0S3xS$BpuqJ6VXF) zDv+ZYtb~`RK+ETzMo65YfCq!rrVv{C*jT51Rptg-X~$ocf9U)X^Cpjme-M-=2M?o` z+pWW3^(ZOql9zJ?P=MaPZqosDe7HPMcTw2~NY?Su>Jn3Eiws*M)+idEFt1Btn>j=` zE(2M%g)1qbOX1bR=lZ6uXC3|6MA)W#lo%FGcRx(F={jLir-g7$w-?)VLpqzTn3}GL zZMs37O*h2Tbl;%r)mF4Ox3`xqRCqVr#YFRN&Grj)Vi+#Hnk|WITXL)T25hq>IzRfB zt=*}VCF+72E^iIMX#aG zA0b~ztj%7d8LL4J4kU&afuW%Q1W&gNc!2nWSo)IXEGEoczv1Qv@JIhXnOP}<3Qxp zzChr-i#3Cscd(|&>Cc+M&TCJSe~7b%%n0ZA?5EiI4QqxuKWEKh&eNe< zsc`OM%~0ny)>Jv)W=*a0HJG-&#`Xn9=Ni^2*13u`CNGl?~GoD*0x&l$^_g-$JNTAT{jT;v?inkCLKn1sT6<=`*pUF7;+ zC0PSm>oT%3td;f@oIh4k0P2dJ=UMA2vVP85SCjQ5Yh6Ru1FUr|S$DG54PQ=cnW{3yTSKDJkv^Aw2F)*Jp4x>9f& z#z#l9mW7yRIl1$7;WmD%%X-5@>H^eNmqY5dWocLTnSR0{bpV}Ax9u}s={T7Vro(CI zaGp$^Cl0$Y)pkM$Jz)b;U6BgonCFlja+<-yZ6-XOgXf{x!*lLb+H-I~9TWBK6MxSx z{BW7VYnjI$fplxuY*~k6`$M=bE+EnIam5#OPGZM(jW~aMe1jv-SGbL-_>vAnDqQUb zTzhN~Rs8HzjfYk6jw}=bTOWj|dbN7y(gtfEBh+e?T*iWDBPK_X%qneo7ByL$AH%@sw(?dRRv`v$HR|wR8^JsF3q(fzUC*Y z2Ug6`uEzeLYY?hzU`KUfQuYH^Tl5m6UFtX*xA-%(1+I#CH?AT_pFC7bw1*$PDE?m| z_*`H4C#g--X`*{y25}9Go^S8pqbrcZInD zqhJ{}S=`P27UVrb{QR{SKc7MkJ4&h=97l&9;kcP@6$aupZE~bXuCJc>#>3L3mrLq? z9ZTb=i`bQ=>xnOM@2vIX0SC|lf}(*RJNgs??ZC7K+Z7{rVX>8*+=$Dm_P(wF+%mNK z(J}Bn>7IV~ztV%21Hu3Q^`IpvHT9rW`u}4+=&dU3{~JAMB`W2AWe>WDxTX)G_rJRb z}f0P*46g3t@gA{_OuQ5w6*rMHTJYE_Ow+v5Zv@WPKW5{-ne`bTg2EH$Bgt|+~~w6 zt37%1a$jgl41%Uafi?h28~a#!qg}3dCChzB+pYu(pBRPt7X-?}_CkiNw!BGNenqg* zA5*#Uu1_8DVUFIOM=zsrwQH{5G}nG;TC_RCE%(L6L2tMd?{GLUWIK+y-oh#Re$xt? zPP<;QnO8uI@HE#8o;2;&O$+|iJwg6lzUxhGxMi4jge45RfZo@}2%jVc0$S4&k#@H5 zNeS7_!l#D8oa^tZ7(X|#X)(rCPpZPlr{Jqwvck$FI7VStC7V2xH#Y?%IuLN(t5uiX zYb)J)PjNuIY3sv#mi2-hR=a5nXc4ui^xSpnq#-`gvje@QO&Rz=TuR7p-C%tH`+o6U zOiPO^1Sx;SrX1)=+2dQ<==$K{Jz89|+#q}+ABoK6H@$={hpO?{?D3mDC0W>OZttci z;Or)^7~~bPY6c3#d0lLp1bch@R^&6O+`w2a(=%f2)~!{h zh6LwD$QC$EYw(~XE&#=^F7<7#=b5&sEZHKFHTOt&y z9wGS)knAMhK!YTJV>c^NC$AZLbm(bzHJXi=7R#!%0XPX0LfIg;w<~^XFB96DS!??* zyM#}C#aVY57GkkvH`Urrdz+l(1|6t_#0ap3$sQbkq-j6G z;JUNsn04^j)))aB>TdNTd}}{-p!E)W{9${1EsERpGQtgxUtMLb-*4JPx62&ys~yRk zcn6l^`LH!hlB*{4*=ySa1xwV~IO5kjk~avqL3FUU&AbdU1_z=0sVX!;a|Vl&k7-e| z4C&!0dKqJ%b=AVlZuhsDHu&1+uk~$@Ut=p>!<2pCNLx8(OgkM?n!zU*oT1*|8gJ3Dz}xMYRA=A^C=YaOuKb} z&3p#6R{9w>6nkgyH+{yGk9FOV-ER8K1p%2e)SsNnu0R!mHHt$aJ$Z_l3~!*?rj zT;Hhurd8Nnfc8gu%XZqOU=_2-55O6$%D9BEP=(+&J!I+REsoO4K+}qByD-~6Ho#$8 zWnbuPpX!eV1otlW5ew~=VxMW)P6k?)8PRco-!4Wp9`G38Ilx80S-^~H2m%1wVQ2SI zES+N*WHv)nrdDC6y|kI+G9A!9a&S8h219G{=rIrl|AL|Rnd%PjGaUmQ2b=($1bhTI z1vm|;2Yd`T^YcE_CkBitR2+N!DvSTV7~c_i>oCSwoW1loX`Co+wvL3*!NZUccp!VQ zCR{hA-I{589Yw7*pV#i`&;pcidC$=-}p6kOlz3B;yH`<%TKvcNxpyT7*1EP5BK)D3a ziRlcf;>XOZj<2c|1bw^XLQR`UxUE*W>tlO7PH5k!?ymI{TT_OnKHHvr-fsQcUV1JY zVkq|b)xyfR*zWIr>ipP1aKzS2<@0d1nN}w`4%xowRr51%Deh4&rVbDCbn&a9Q33s3 z{FS2RM?U)xmLeCsnTe;LuY;uh~u8NkD*ArO9oq zWou4V@$ben*FqZ)DQ9c0;ZiOtG+Req9oy^a(9_{u5?gB!fdR%%E%2AOAg1*`W2*_* z=+NEWskSy+?@(JC(B|yc^G(Mo4b3%NMo(U2Y#r_C?TVI&nP{cRic_gn&?y zjKSAlx?{hon(gqCH#n@-Jg9uITemDptxD?OU{BtJlx({Nm@uI;bXYeFw?&}abCg{b zzJ1DOUddD`?$)%T&-;P;yp>25-N8yIXxd?4$aZ_ZY^F`<_BNy2+d|z++4iwx+f5tV z2(rQLk5BHpSyu8t15MJtN$PPJ0J$cZ;c+?f14*yW0T4tJ!+gR=S<*`I@QcYi4`C(VyHAPhWaG%OeaIRM@$V#?+`~}w$N5Ksl&B2*0H~}9*vdP=HVx_3g}T})8qKb zMd^9?DUMC2*?J5c;-*dPKzeg_lG;kaPQ!?m?4}>A_i~(MH???}i5o_}nTdwcqJiKT zu4nLUR&hK7e!=NLM79H5hi(IVoOaVW96<(Nv75karRQA@EU$U<8RBqBwU|PD9Lbp8 zY|XX@SY*Oo2Ylj#)u!OG2eWNMh{;zm<@-kSd^*RI(Z2geV=Ni%$27ft1=H{T(=dZv z!m~q8!|JU0PBd3g@!d587!6!A17e+!vcskGW99~^eL=IvQ-k2>LA>g~nnxgtNCydL zmbR42T0g7!8m*jJGK`K{xH$8jH4W5q5vPIXF3!N3iRh~+Rzq1m#6XNotE;B-?P=&V zw+f&93!*#F*i4P=X#;xdjmXwf+CZ6~A5;~@1VY}%>1cL$D~_5fMQ>nL71Ym>ytn52 zL68$OH3YU+X?-{c_L9rckPhiIc8&ZLWZ*xtr?+idZ{)xz4UUkbgPrYVHiQeGo*>_t7 zrFS^ut6j0>8nw0eKAz+eO}eBbbo3Xg;QhA74#fXoXmo;JeR9f@epVrf*tF z<{oEXe8|3%N^z*#YwDFP{Jz>HaI2DCnJp}XOW9Zv{S(ta3H>wDzXbZ1LH`P?*!$4q ztaYTZ52F5TvLqvnwfzfFjPO(VPquG_WMJl?g`z(!zRs0Fld9&RrC<0#Xp|`iL2P>k z2#;P97br|TlPG*Q&eqWxmO>Nx21jgmphrz7WaflilkFf+HFb)r` z{(<{kzJa?bSw1t%f>02Q!!3`N-6D(M_Hr<8%WmkfocaNqg>T@Vmfd^`g|u3B45EWUyJ9S3)^C?2s4(i{b1hk)1-LM($r%*Y`oh6)4Z#7iG~jP&6$ zK6uc9Zo4pyuO$G>C1D?$rtY!T8u#=uvNmYffSQ*-eq4gv88hh)4@;l9qUjvn4uWn( z$Ah4wh)my>Jz_F_h@Sox2MJ5zwnL7ZT|}dy`~OC0a%2>bwoCc07{(h2>i$u z5O~T(@h}7o{m>GGQrtnQ_%N(1h?5NxLZ=crg8ePH*)bt347Z5thVCAEB(O%a8~2hR zAN4v4<*0Y|!Nvf(akz;-&I=P!LD;7g{`rCo-ERrwFu%JK^M1gb@C18!VUIW2$>r81 z*o}Kqq3)YT!pg@{Zk$;11U$zz;afA=n^Ph3mdfhIyt$%T*?&Ss@oYx~un^lG;lo1o zKjI4uRlpG+SbRX9BSd*e?caz4K*)!IiWp=Lg=vHtr1=o{oQ_a!0P!Pk#E%f!KcJc) ziu)TzOX!Gd%s6Os%gBaCJ+Ps{LMSG(V0;~?hn9qewH_aOD)2PssnA*9M6x%|A(*@* zfb7Ga4Ce6Ds4T-EWjjoMoGZ)pU6kk2{lNL4r#J^a#X0CH&Osmc#`)5H9$s?PqA)|; zg$eO03{js7;~#h$?d;Tz@CV1R_>)Qalj-Z&4gLvr)X9$p*0k;h;V~Da3q9qey?`X1 z+5Rh-1m7S!b;0?45lQzzayAGjjr%RWcBm4t4tGAZ5y#^6b8kNmgup+xAInSI*lX^W z>6$y%Gp9gbb!jjjUn~vwEjfVyVP$)8{FJzSAbLpLYxG>Izq`tGApx(|%oQX!=X_2Z zdl#^%a)}&I*8(|s;3oZOTLa!?vG^??G}g7h{O1u?e_MQruM4l$gj;!V#PA5&!WH9? zCka$l8d*!2@To{xAYSlr`OgxFJeh(6kfckoyq9*7rH?k1bwZP5T!Z0saF12%HkbD2WP90`-ULpdxwPEf+n`q@GZE4c*xcyp{0Ed&&MKNeyF@D zv;4|Ea9+r>HHmFC2Q=})#rFVX0p7YPdeDl8+7}GQC!c-G438LuOv2+)Vpe9I2YFgL zly}X<0}{fw(}H=>u6dQpywrx@R=usk*V4NJI%83P3wxu8!`0TS3m$Yj zaFLwmIs2I*@UnnTSKD29r7a}Pw*@alVK;3b1dUOxAg8Zgg`j9=t!Y=gR3G$2yFxr+ zBwf7l#z8vdP{1mf{`rxH1#I1sKn9owi)aa5|AJ%(>6igixW~kx&MgCI*?=H*4j;ru z3=$S;@81T|E|kCz#B~L*a@Moy&H_ez$n*`)>JaQwbS6W58IOl`Xkvty9O@i+MFCrH zCIP8(#sjU`_`)`N=}BQ_IyeCDmLLn9{ZD2es&w2(Qn8jx_0IXYb>e8AHb&FBWJbj`R@N@DDmKC`PC3fihqBp=W}U4c$lL?e73X^H%Bb>Rs0ANoosZP_7NfJ zIrhdb$pP6iN7`ZB(7BH?3Z-Y?8)3oADI|#s?+kldgKLJm^rYiHa-z`XWnT8>?y3Wq#*+6BAH zaxW_quh!a@qu*>Phb#82cySEh=;;;lds02Bi=+>5C4lU``e)JNGC8fnAFk0f&ekBro z8PNj?-+~Cz$ba;H%l#CdgsOH?c=t6Z7YNHaIGs4`am&OJXYs@F@B*eswT`{_Giall z+M)nQ&9qex#?BAhGlJ%!OBq)aD?|sLo0^h{NqOJ_OFSg+(C==Ges}tNVv@^yAfR!1 zFUx}v!5a$6Ioy4Y`liS~>dS?`zF$Y}hiwmR`=T1~G!yPbACn)5YOwUisa$(|k#FnA zj+z;>(!E9X*!-$Sx6jz)USL#Zg<*4YId0-4I_hzs8kd9wt-CR%GnW3#10WBG3lT>v z4_GF1j#gJ-{Zz-EnlD8uf%T4nUG&a{qsGxHKg4V1U9nwkrzbCt%J0dauofVqH0faQQ!0NVk_0p|hy-agE|00m$)AOSE7un4dW z@DgA!v;q7BfFEEW;9-CQU<4!p@&F}(-veF&Yz6EC&~G%#HU-fAm!gC2q!>oD zsF)Ew`4l616$*&EhuQDt){HZ}E&ZTV^%~4OaceCpI%!-C!xYEn7MW*Tatrb^^HMVN ztma~dnK5G=Q#{&gu@vMdS~4x<1h?r-arC0xVt1e!Gh)56Yc|AZE*dG$x6XgmTqG{Y z7C*|yE*6^?%{H5}%vpmeaJMiClTx|{=;ohgUXVN6+%*XEgYW$Hmku25yK8@}DKQC8 zwRHP#?DqX-x9=ajeP8bOeXiU07u~)ax_wK^7w?LSdnNw$7t*r6jd-4YU)@6(dTZVD z^S0j&sSnT3+wSGec-#AXeS~--!t}O#hxxy54<^MN?w_~)cFGmvO~YSd_dD>#^EL-gN4Bj8$e&%qAM8a9Cm-r+^!&=_n zJ~nz>aY9i6T2XO9(HL{4#ad)eC^8qD^DPMQh-u11(*!wG2|)#DA|sj!9PXRU;Xq}e z#_P%7ls~&5%bZYV9%M4+XXav` z4!NM28`%tZm<5j#PPYolFrKit3YC$yI6refP(nWq+KIEw9l2%$6(SGQ5hgc3*OHr= zm-}0E(r(`jbB+h?e~6M-*ju4=9X-5o@}dOrx{hu)BpH)Yn3p-*JReMp;t>zbNE6S_ zD<}ptbLH#q@8z3OFh4(6jH=5k&YeT`?n#08Cf~epMjG(o>UKf4CG*ids+3MNINdlSK0~3qc1DZ`}$BPna7bKxOaX_Zt?0$tVWhGmAKqgEC&s>E=sw zcBVDYa$|~jrq5Q{jpB32ccMq-0{gR-K=^fOv+l-9?iRG~f@}_l1;iVuvjvZ`wNH*2 zZcZTkEFHs?03HBnwK_(x*D?3QJ_;}b5Ds`4P*Q?0xcm!)nFUw^81@ju42Ov*j2sW%64E14e0q4A zE{z-2%)-~zx2XaqC>&I0NICjoVU!+=`A zUO+Wq2Vgs3D_{#?Ghh>717Iy+4PZ536<{S`1z;JV5>O7X0CE5sfFytxAOVB|t~Mcm zzz)C~KnWlfpap~g+MK`%uobWYuokcyundp|mSgDI&$PlrpTIa$(?T&n~RFj^)pN#91|r?n3R~vxzHz*IBw!tuTLg+QhfBd ziJdM}A|!G}pMdCmab{s*UM@F<5$9wUi|1!%nZ=oKw^+>c3oT+xfjF-KgPHs`EVATcJGw3e^QM=y8@)QpZssa)N)pNg zdRuaUbV2@X^T=OM56XvdlTaQpNQv<4%pl9{FH?~}x+NN5!8x5F#5v~7LJnJ`Ba6I6 z85ibyMP%!(GhW0^=`UODu`;5&4BPio45(>(+l!x<~7Pa0b@sz z4!opliq~0gbm{r*a9032a0}edux=We7Zsx2fMbX@$x~HSy zf_dG;-<&S)NLiVdOrX$*t8%Yq$u{~T^KY;vK*$i6PjPoJs6fnU=jWn9f$6BeiQTRF z)?%7%EX@2DHhIuq!qV`Dd~eQ2trg_c)DUH$uq+L47&fzLj+FuyvjnHGYN~6{34aVrvF|npGW8=n+e`G@Z z#7PO0rz9pp{wHR$&dZyhUr_j)qGF46!NNt0fBUs&s>ym&Xdd7#TdS^kaMrorlQ*{SV$X1 zwAh7va?wd=7iN{hEYpKx%i=vt2MAH=H z=w4wWfu0{DzV2@r{`o?r=-2#t z;){DY;JW%3Gdcfh4)Cey_`|{Muljjvkj%$?I{$oqe%+rZ{`DOFKXv&>Er4y8~iaq^>6r|UmH^U2vyKl{Ali*sK#e)aV?&ZhIO3*UbC zee=a1E?xeyrM2zKPd{J%?x%rvE>hINaQyojClr%O4jP zHGh6oF&#}YS@;bX$Kxj^%VPYP`1ny-S)*XVF98?Pq5;^W#(I$5zGfyCEa};yVNot^gv8TMGt4pOM~kov%!SF!XRXMG(r1t^ zrO6;IN(YdSc#A0wicfKw@tOHdBJIm(!GqE(%4KayIo6_Lx7$>6R=(N&k%Z|uImZ{| zv%ZN|x0z|7xD4Vk2+trKg<;^&NQX|I7(J1JId0+@v7| z5&VH0Pz0tx7htx8UrdSNFJZ=i|)8<4hf2Fup@Q zZt(Z`k<=2|jR5aBOcx2jt@8}Pl^?MD6- zj(*4c7qoV-r+s@LNt)AXSzvF{`5Us&WPp#Jl|wO<9LTZeb>7Euei;b45zRb z+HFOZ0189(LMEcJaf4ug0Oxh&=ApT_--T#Ka_4i%fgP5IP~ul-lslEAlT2ttqc=EvOEnK$Gl{E zvdI1gXzdm5akvQ(?nb{JnJ90WC{BQBTz;X|qKd(>yan^L*l`mRl9N>IX4MOr_u&Mr zV6l6LDTCocai6BneI^n!V5)p4SuIE^){GN?MD{E(x>Hhu+xIO@o^B(YKfcqd##&FD=&URpL|{%_MlSIMS=Kyr z98kyu0*slLpp@55z16yVhhcZnZYtKRZV&`Q9yJIurMQ)qAz~QG z5cDi}GE7|R?ZRxfUQoxN?dEx0Oh*4t51-I{{z=yaLz{I0Lv0xK9W=0~P^R0k#2Z0Sy2# zW}mYGYXIi}L;CtKF@Sl1=K%)+-vLDZd>8{D9Z(8b1K15{1n}?lVTJ<60~P}|0FDFv zpxaFhhz6JePXhi5I03i-@aylx3L~zHxs}F;*NM9<_<;(HtfsvWA4OWX@BM}=5EMF-oxC>3}8Z;`@n{S7%?-L z83HB?gY?S-%!Ammeh6|d;gF9R!Hi@^F%m|~$QU`JV3bS*6UnF;H50{XATI-%8^*vG znP_G-6T`$ZCT0vXmWgA=G2@v>mF%BoojlHK_7Ka;8>^y?MtH>4Syt}6%?La9RD5VlM z9;c3Y9X<+@w2mpr&(57=?1+b=L`SDcq-=Sl9A*kmO#4>_^^)}dRpGm5>_ta~+phz2 zH*Q`*(jzgr|kyv*VgvO&6nTumG^YR|eoIS6zyfI_r5=JM-j*B&=jEgZ% z8a>_=lQeE31lK3VnAl26r8=ef91(6S2~&19&OL9DglWteHvch`y5>E;0K*@~$?Kwa z6tinNZd?MAh5u(MKqI*q8+Q^gI@&az80{tjIuP`Pqml8Z33cP=n}qF>X16Gb3v(^A zbE2)5f*4Ge%|%@iO`k}$nOq2Y1dNer%IwvHu3@M!nORvL#_G<5C`W2Sbc)BDZ6R|o zCqP@GSy^XVlSi8-N5{rdhHifvxx4tsdHb^B%U!%DUgsTW&V#sKXQ1fOritS{p*RM; z6%t&Co1@Xucsp}IDLSz1@XpM;RW2UVbf+AWLf7K)HG0s-g^Y>pm5xc-)I>d5cT_TA zKy?BldIfd2#$OrQ3-eoMaHC?m^S%*|=%YK4^91OI*$uU&jR02v92VaF;q4{EaRu9K{}l7@oDJK1wB;}#kza}+q5pcVNau1qaNPipn<#y{CZ=)Gp z--F&(VqPWe>`8AUMNUMU))PV4+VNC@SmnYEflFxo+Axj z>l1w6z`bKx;*H~0#P<$s!9p)R7yHFVBh%dvcV5%63sErJh&u!D_m0D(;5$K7Lk;{R_j2`6k}W3QD1q9fU<-a-JVPwcodj6a|^fM`te22_7! zk{g*sbMm9Q_xMq|6qigPfYK!%AvYWyVE>i_avuyJcO`(nqut*z?(YPc6laRtJ<)AW zg-Pj815n;LQf1Sb4^s>%1YoP5!On2g!Uw#EonwZ1 z$^E?!CgHaMK>57}pm5s&gdeN&66R?D`G~g83(=Q;lt$_gxMv7+I84f$fk`;! zT*N&@m|B>WW)MuGm9v>Wj$wAdq`IkuNyi~GVdAKR34@6v4(7u5kXeJd7bcEmm<=#- z6vG%{ieU<14u&cE4suX13%`Zj2FwhYi(w|f{4Go)%&Rc9FiFT`I7}G-#-He>KQ2@8 zO@IGJr2d0R-&{zUL*nK_vj0IO|IJz5lm*S7qJ{fJGj5*#l67p1$ru19pP6+=%%q>0dq#GB_!IS?HC%yg^AZlT z;8sqKF2)_w=eijG8i%-tIT=7tYPb7Mcy`B?UXJ#pFZvPp$FE@A`5E`jp{+In`BQi@ zsjfZYymiEo8^!Afni!!EN()c{6aWceIA9n+3;0DM5(Rou4+Gy=dKqO*W{z)3(I z;4q*TuoqAb*a6rM*b3MTSPNJUSP7u;%K+dm(IP+|APbNRm;i_a!~#@+FhB^PHzq$G zT2NU>q8!1Xg#fSA|05`K|A=;!2F3NH1uHwT^1=JfG|!>=ff3LSo-BunCmh;oT&FpK z7*GZ%FXZAkU*zO06G#cwZTu2qZ!i8@l&b+iYXc7&-R(5z&;X_bXkPI=;4grafJ*>~ zFEA3oM8JFi#iuw?0Gh`w1Uv`W3OE7y0YJnY1&9aa0XlwbeT^OVTE9;FPl67+aZON% zJzY0s?z52>uWao1J-1oI9FUL;XCK`VKxW*9?ib;uY9hrCkQ`7hxsz2LZ z`m=N2z?Z&RHht>T+Fc2@At4hVF+ci??Wwo@SC#f{9P!!9M~>I>KYg{Hrug(L7sYn; z4doC>>Do_lVS4`eP@snbJrwAnKo13aD9}TJ9t!kOpoaoI6zHKq4+VNC@Nc95wgBl+zdeJnnRUhb4PCxzW$#PJ4%O_)bmmVNzf=avqGfLpkK4`FZ)px*<^B8&y0z z$2>o?cm(t*b4uSxdt+2)@%)hsq(h(pGe0*QS4rJBH+4g#BPB!heFC(jJZb3@q7$NH zarty?Dg@D4OV4)?J$m?|r#iaCn;ieklL#nX!Qiq{oe z6n{}1Rh&~e72hc?D}I7X34djfvY#?UIZ!E6>Xjy?O}R|@jB>T|CFNG-`^su%t@60? z8|B>*kr7iPiXtA1_dl6E zhH}F>gVXSffe~{X7BcDM(odz$Ql9KCnO^pQyjcF2{3ZDY`EL~EikB4cDLzw(l@g^< znV`&27Anh?E0t@NTYz<)vO(7j^%x?(STE5V^$Ge6eWAWwzf!+ezeQiIuhTc^o1r{I zWDpx92BRUt@TlPrhNH;)dqbNOaa?gq@rmLK z#a9ZK;(Nu9iYtnC1rK#qqw6y%tp;bvY_Xldf5zN!88P&DT|-4(91g^@sJx^ z-XvH$M0!ptkpCo)QGBkP6|Of<93{U%xR}Gs{%O4poQu#7S`w(R5QNu4tc1ZR~u1Wl*@zM-wwzNpPNcx1dO1e(^w)8#e z4(V~}Y3b+EucQ~GKS-}g+oio^cgXIP4M6=$WJ+0-%qWYMjh9W5CCk!exw10Q=PB7A zWG~BJm%T09Av-9mlQqbGk?}yW=j3bTugEva-;!^Ye*n52kk`pi%RiHUCI43bqx=`} zL_bjSKE;Cyi9(|otC*me>2Ad~#d5`3wBHX{3ZGXzs{DiU73EvX_ml^fA1Ti$FDP4- zzo4ZKMq7=Jm=Q5MVqV0;h{}jJBmNxmw}{;l4H4$ZqR1yBpO0K0c`EYrNLS=w)x)X? z)kM{!Dx1o#+N$EKgVbZx3F<}ar`5;RzEQzZ*-?2>PeyHyIudm@$`uu+8LnBZsRReT zr1_I3S(l?L)Gg5cPG{47tGlH0M{9dXuhd8D^LhH!%htt%bW|IY9u(Yz3M z17P%$43vaP9+pH&VkPmC6iE(RSgGW3NtNVz$%~Tpl4{9^5)tYmQJROk(8y-V=E)X< zu20CGk!_Rhk{yyQkuOJ2pi!96)6G@;ni(}O$`Vz9*78!+ zJ5f8Lc1P7leHe8r>QdB|D88n*rmyC1&0x(ijaCz*8K;@5nWdSn$pb~oG%sjg*KE<$ zXu`BR47G-z4Yb=@jdBi_%#f^=6w8*#9+$l)`wLpXRbD1vCx27^z9Jdzqegi}sf`#N zQ5dlibyOR1A>zk~s}X*YrpWQAt5uQjM;?y+DzY^)RAp6_sa{jPsoJjEr8=NGuKHZ{ zm1=={i+aC$q{aXo9@nfyt-PjrNAtDjJ58IWuXccTq&7kOgm#^_uWlsjsb1Hr%hNB? zJM=H=x1$fN)qk#ULmk~`7-|@9kfNUE7*-nA8EUAWRx-?X7>`RfOIjpR(sJou=`fi= zmVh3NCl{fe7AX2F&npK-s3HszVuqWf6)l`c)c5WV+0{bv0;`uFr7==bSc^nAl3=&_zfzr7Ca`c1>13GcPgp#@_w zcuOLA4}5e`@{#16MXVwYy-5OQ1ybcWWva4L z`K3}2fxvZKoIgm+iUo=%6>lg$Qrw}uPx+HFDB|6S->H_Vo>T2pWkgj)ZHjs~Y8%=G z;xquzcZNtqrDAEAbeL2tjgwB0CPaY50n$Wi8DjJ7Bn zl}_a*&1STht(xtc9hz#*UQMm$u%=FPQd6%vt7*_QYMh!2nr4)*O>-5BuJ~GkHb^Vd z25UpKp<1yvOgl_FTr1Hkv?{GuYt+VSq**F?M!WkHcOkM&C?cYE!sue5^cG* zQoBsMLc3DCO1oOSM!QzKLAy!2S-VBMRl8lgLtCxgtF6@@*4AlHYU{OUwGG-vty6nJ z+pN8;ZPQ+bnk~LgpbOH8biuk1U8qj13)3;pxXT0*H0qqXtL!`@7~_&cAB(;(RX@%T ziNPf^6&aXYtySz$R1+hKq2~++BMFfh(O1s|E+vvpk}WJAJJ7!NN@^vCC3TXM!0N1| zft?kJqPHhBlZAWig zALYaxB}5ad5o^NG(@Hc7O@by#ld74i$CAuL$#cA0Zrc(F(dMMCCfgTFV)4ZQ literal 0 HcmV?d00001 diff --git a/vendor/JXInput/0.3.4/jxinput.jar b/vendor/JXInput/0.3.4/jxinput.jar new file mode 100644 index 0000000000000000000000000000000000000000..dbb035a872f930561d1c196853fddfa674291e08 GIT binary patch literal 73232 zcmdUY31D1TdG0^bjP7W3B}*g8mMqyG@3ySPOYFo;9Ltg%%aLSb$#z5t&R81TlSmq) z#S2it5SH@FR!V8Y9vn<5YZ7m`kdzi)p#{3pg}&1Eb)!(0_qx2kZh7B#&bfE)+_^K7 z?2z`!p1Yp?p7Wo7{}0_)8jcD7UUjX1tGY0UatTX+&roMu@4&u}|M;57AvftOk@VTm z^*quX65+27S=^-koddo5dIpEu`}g%HC(XF8@DFb4bDs?`qLwmnW+m?)2Z>P zMDN5%`})dQe=VO|_p+PL7UbaPjc@^u(E&>Go-~q5Z)9y}TL1b$2>B zmN|u*n5FGda{Ba+#8~=7$HQBYZxZ>Elg|Cjbb4&ceQ-84GLF=|uZ-Q_)^)JIzh_`* zM1L6X{4glWO=$+CNRC8-9HZ&U)X20N&LX)N7s#DDo0^y|lCPmaK75cOxt0{k z#ZP_ZMHL-+Hx)V) z(!aOo@bQEDj`w!+Su`XSLx(#D2KzdPdJhhSB#QdXWtlDw6`e{=4_!Eu3Q6g@_2@$s z_p15oK{q;u2ZvKrnK2A}W+EgFLF^GA38F)fA5i@A%50^Q_mhcc<;S^Jvtp{1g2on z_a2l)vTp1+~sBKHun+TVh#+7@Qvi$#G1Fx^?UOvI}}} zdNMt6YA43-baJZeG}d@_?20Y&fDth39_k_XPc^*v|JJy-_|0*Snsd21$IQ9HoE1Dkx++4+Y!#x^ zIXRiU(3hT?=E@!K?sXF_7(c2pBKJvb{Jy>JP1&yWM0$F+S_DS{g}Oi<=*jKOY&WT1 zCe@f#zR9qr(7eh?hlWKaQ&TA*3sp0!Lk2>jCp9QE+fjC0H3;3U8&O2heFpv1jS0y% zz^tHY>Y}L!?su{%;zs8~6ArA?gO)ru-O-g9Ka-ij{;=~F3#%JVjishjPEAhZ?p${( zZCj7wuhqTH`C=itqd;dJRQJIBCPQvlYjx{4OPT+y=FwCJvpF*Q|e*&wa9tdX_0 zB&EZa6EZRvpkc|VEt{D&#lw2$U&lkcbcAG6(AOOG&{i5od3wlpoV4YXoVF#+5?f?# zNHzzRQ+!s~^02g8@`x>CvelMVvf7q$nXn{d%NcovEt7&Nx-qEWVxz`ZP1`cVrfrb3 zww#mG_`+(Z&0Vq~SrJsYSv>}X1;AV^*QxX?xm2)x01mhevm3d_%rWKLf(qA!r>UZc zRH$1|WMnLroJ8R$4~J|xv6%of8AzQ+mjRN{hVX>C$;D&b z?uXYMU^gt_HK(u@U{4PQ0Z3CenHtZWO#!7^fek`{sl+%PaJ888U7ayy)fw|woiXch zwn58aS%9u-!(9!|z+)uRa!o>?!-W8e!!$RqYt>88a!*OgRVn?XNw5(Fr_R4pQA;9= z7V8urkx1yXxLkZy!p}+Mvns=SE+&)V9FQwew(`hzDN|Wcbo44KD97=-#7cKAzAhC{ z$cmd{4==tZm3>II;i^;}LlSj`Z|C8&o;3=s_qjr|=YFhk+EW}-tsNpOU&%rz#E&soxQ94BwE2A$d&dc(o`b&q+h#sx)4H z{<}+`mb&Y**eUT2*=o8~tvUrn0EKfE9S zs$90oT_(?3Gf+*;gRj%<8HZ{$4jY_I+hvEzwA@rwuPa!BF=GWwj^Pk@TD?cgt>*XNjqzCR+v5E;*))kIFsnFyCbcrS+yPL-C2HrNq4|cdw%ERrPgQ zu1oQuQU8AR%z^J?*6`Pg(G3CayKG zRv%Bw?$KwUgKI2VYsor=tSEfGcl5lbaKq#3(nU-n>v|O&GN{R|&@Fkq4i@5NhUD@- zY_Jg4+rU7pZ7k(#OIpmH*Cy>YR`Eug9DtClncIlv07QphQiQt#paxhpuMKfBeU^}| z0^Q;_(sbQI4x9&SyObSCU?wx{A2q<;+1z?y)YD!`-~(1-l2&2X#W^JSf^m)t&Sc@l zh0u)b)Fz}L?_mLfUQ5#zEXL+5QmUsOHW2V#bixKR*X@>PkmeaFy)I$B=m49659?G_ zI1`4Jgf)B&DNanm5+a{LT95>aH&ZZGnN!vhKy;mIscB6d%gu^>Sjy`pdRfZqB&JLB zEt*f*KfL%}EExXUQQ_=UK+|JB3S@l@q|l;rEQAIg8e?cr6A#TiEU{#%CCe;Hyg2K_ zzZ|$;6t9Tiez}cZu)@YX09$2+jg4^?*0ij#vGHO3uAA!!1TKT3OsHF52wcy4+-F$| z*@WI%uW4spfZ>^`k1xtuH6MdmtpDZDu9$l{qKdn2k<-5F#hL6mJi%Mx2HN--AQ39W=JEieQ7;7>01mrG zz0?&zxpVhY&zJ?SjM+Jkx4t~cyYkdO%NlWa0|;q&!GI+k8P{Ca^$!GcMRHe#VRS~vHSh(MxM42YbZXFxmE)dyO{#q^xjk7(a$<25 z;C&es)TMd#3Uo15LohpBt}xjpb6`k&D|EY^&!sNRiY~-;4rEdPf5eIgU(}Z4@(@`& z8^~-@*f$QK&dEx`)g~Uc%Z5244`0y6FP@l?ui2#@J!MpU`K5wYik=1can89FN#3XRDfT8e$ZSv zb@QysAwJSmooAEjvE+#{&AkO@#-4zR$Jvy_BU*qYpgTOtG+G7Dup#nl(o=c~c+xCP zPkBbv^TNmQa_Jkc!(LFI%K#M7Uy7X!L#M>Bb4m<5r-YveZx;akVU8hnEAB{w@Xx+3 zA#4!WrR0+?lLjQ9Nkwvoe=(J+?0S~e0flJNEXJ+?LIE4hH3^d@B1fpqVHsfZ7AniI zSK^%ICJk6Ss;p18U>}NpLCUX4jF%N(5c`T$^0Mj+vfzqTgLQ)qE%wDHWDU-drt4Dk znAGzT*dFD>>e)4k4=Q%fAL!JTp47EEbtO{UPU^ax)YYEU^*VJmQZH~)FEptg;%|%G zVR}Jwiz54I&U>2s1@z5HGQ?z&~J8VT+Q|IC#Y<46Wk+v zO!?jts+|Nr)S{#EJLeAqt>ACIsD)a(KGfoTIkX#q5Hxf1Zze*}EJuKy^YKyM90SJ7 z8=wQtG7KgTZ-5arQ@XW;f~{r>wwfu`YL??XJQS5=j8G6lfO5dVlTkSplhcy6@6^FFWGF*>B{_zf1Nc*+ z;Em#Q02wHK-~q5XDh-5Dgq?nhlyNVN@nnEnUcNNc?<3i?5$_t(7AmZQbo>Y)>dUMkz%}|I+KiaClktantQfzVBHGp2_rLd8rU8g9QgL25ESZ``sf_^KgLM zrq3a97(9ao;C%7i1eOT?ay52-@RmoO`60%bKjPbSSUx_iWO)osCaCr;h~aD1#3*-& zfeTbmM(je1^2E8VHkVk>+0H%64dCg{ZGD4vPi@x4mNeO1m*Ck$2qp;|i?KYA@>-CE zk4nKFr~>wpL&=dxprb@!%5XB2a}|WE%Q}q}?mlcK}>r zXay)kon0(9^jv8u;=Y9P0X(ts+zSW{oQQ%)=)7)5GX7Nqv4xNsg5~RKJ?S~{ILOf8hSn0hcVyD4&6XoKLh%xr3zd*=hE z9%nl~o>DT!2aB_4^(FL21V`TU5f`eDiYH2vw*ito{e5bTcq8{iLx|^4HWUv!^FZ$~ z@-TeFD|;cNczh?;y3@QWJSfeNbzSK+O=l=7^)U+7bMff+x*Rez!pN zq2TmRGXlojqxc#MgYLk%<1ZH^-u#2@f7g$h%^&u)+54~Y&7k=Wa0tj-j(RFJjKmli z25JZz4nZTU3j=U*XY{h*u`&rgbK0wfy0pNoHo0s}GRV-O@C(LDP&0By*3-d&F;&Vw zoWpuFk%Hx7;K)sIgmMBtzveIG&s`0qpfc(KQtsUKeVmRYG&O%OOJ>*u&;~%-xD{MW}n=^MY(4&QlQZ?i^ngJmB6^Jrg}oe|lws z+3wA+?P$F1B0Sd`u5P+4r0=B&v6<^6Y6B&WDY0S!`ljem2Yh08#prcX3aHO@!avlc z&RU8`=#&*)7hXYGnRRxXcUKU&5w57Y28$424ctx_`cv7$kym?jhc(vfTYne-c_A38 zBK%QjXx2&Z4sCKw&AhoU!fnBGqUd0&mAL(u8x`=a=CT|g`^et6F2z#hZ%%`vM#89d zuA;%EQGxV9CTMC!i5bCsf`>ZZ)&u{LML==Y@?63VWgmE4QxHRtucnZq{^VCXb7&B3aROpT>dXMns%g_I?@AC8C z`y5s%Y-X@1xrqW#z%iztHG+m)oQtfyul)RndjTf++k=F&PJM6hRwaRDj|C%bcgLVN z0R0dEK^~UyK-DK=>(H5h!I^@lQ#l*!kqV-oI3%HEC?@e zkU_G4En(BC1M9(G#8vpc?~^4hYgsB1q09=LOL=`m>=Mxws8)|Bn5qP~sukw3uImMw z+-|J2=saoG%U;qW?i* zY{3CUvy;v9pqFPc%68Rq6=uc^EUdW|3UuDkhARi!r1#1&TnpwDh)m*i!K0CAYQMN)#ZS> zz-nq`Ef0{T*UEYxT7ch>=iSPiHeR(?(Ds0bO+0LlaYN=|E7A6CJlt7imK=2e-=#yixZ!jprtXlQLZJ+bTOM5&t2WaLN z;3E=)$HtR-=d9RPf=cmCln6i)pa>iyUjTM6Xt)(}9+ot6j}kA~K)5?C*=s{;2fi>2 zlqv1qZwXij2jo5;`fSLJQ1t-Gs)IJfKQFQ5FvP95J!3KSqxtiAE(qEjSuMB7W0_q! zIuCjCN$7zjWBTOig5we9T5%-LC|=}pp7Oa)v(u}d*`>B5XUF%luWy+(F>es9(Y`W( zX2Mj0Xd2@1OeBtfnA_^C1<({IFT*`SHxM2`&=t7aX3)HrEP@y&f(RfUCaM@As#pe8 z(IO;|UXgN*)m1B@wJzg>D1$uOp9Lg`?PBZ(#c})H8#^Ss-5X#K+rk=)+#Xqi$Kla! z)U_(D4}Zw0e{YL6M6N6S?y~p3U#jaNkX`TriPlFSlg%30T*AiHt9GKs2JA1@tf1by zA~m=m3#%fDwVeDqs0plOA_Lbek*K-Y_p`1mqVi&`dkmt&}R zQ-|svUhUzblebX*ZZ=K}qS9kg@f!{XEV-8o+)xEyO8*6M>SxE5>jI1V+HpEAh*JSP zDhFA>p$d74tLzoi+TY4`!C{L!-_3Hjr5qT{!bS;(68Y#fVV zd6_K_%FAzy<3qLn*4rl6ZXdrf+H(&{k~;cmkw=9sh#7r5oM_q*Z?a`X`-9kG%c!I* zj|Yns6M(U{fe8G=g*-*fZ)?wCa62Tc>)*jRk5HIUaTgLkVm?sbOoLo`wn2Fjwf-xhP;V!K|cEkq zJ_m0Nj&B93+3~LyruooWc}l|S7{O7aFXbS{oWy5QGO5>xRpK(^MWF$A@S zhpMYm4V$>W(9=@2_=8e+Q{wamQHxvkvW_x=DiEcMzz?J#Vl!|U&2n1`;*w&*IC^qZ zqQfm4)?JhOtFq8IC}3Ku_|yBvN~C4|i`=vul*0#K2CDt(4E0FPF)l|2STQts%5;1^ zECJh}Wx_u~_@=~A|21j!R=*X5Z(eC(UuoM-5>Ia;%Ep1cfij!7H;(fMPj5_G^rk5! zz6@JsXMX(=PyJCKi_R?RP<_Ej-IQjya9E;TIG8JR&s;_Lo%H9W6$@=xpuvPmp1_1A zjky9CAI)f2;uys_kAw002hW{&9i}6HJ5fN;3Zf@bt&t9=mM7DvX0!&q650T9nejVX zQ;g8XWP57fC$Av3K|6SW69||hR-n0BW&=K`CF|#?YE?eoJJktas%N1Lw;_PnBsth6k0K3Endm-ZPIT z%p+;HmzfYzL#+6DAnxm_$_*x&;c|jKPYDb}ICVULM-QG5^}pM|45A7+xX@sFZoQ?? z3iePEIH0M2c1EYhdDj=JEAOk&zmNMhHECT0_It?n4TY)*n57U+Y3^bf7KY|7#tnBd z4&s$&?{ro{Sq3?bTBd=)#66*jW*{!Y)h0+msT#4`Re5V^CF$Bm>ae9D{2-`T(yk3z z0SE2GXd=w)2LYZ4_Pa=ZD(2&3vK7}QO45M~>k-nhaC`&4@JAx7~!*Yux zY=k#BmpP`z)Y{gp$<^4!eDc`mS4Rg<0v_|X2?^&hWIiGjoJBZlfn$eq!26XvK+aks ztFdsYtpo9EiE`AUR&kLTQ`UKZ?_g2?xH^U7Ay?lyK5}D<5*(ULPJm{+>w$u+DPRg@ z0TtjtRF!i$12iO+?v9Z*t+{LtsH-o?p9qXx8-oDhR%nWase`$MfC6RYa7SitNeMqw7V9zn^&!O20qfM29b z-vW^fxoB&f-Y3zf$R(+`DP_PktY=kqH>G5_wXHGS5NWW$h#Pc}jKtgu2*cDfxBzOb z5NMU4_6k4HYW-~TtH*%n@z;Tbg@9JxR^kI$(D{ehnu;JeETCdHw7VVmuVtNm$2x}x z=Zio@26~S6fMuSyXSpP?+M^w=545CQojpMG`Rs}wjU$I3>nJi3W9O0=%r@#GJWv*M zR9_o`YjfXf#DMec`c}pr_e0|Ie2XE+UnT57fNMS_Fzj&Vq)&q0x%BIQh{XIAQu*{E zVFxEPN5yTM?^{7MUZ%eg6wD%0TLDz2-clADP%cyaIfd{UGdc=;=C8V(2*%-b%XYrh z!>jXsULsqKO2c0HID$-{LY(RX0-K`!4g`4fnHL(rD(Vl(mHz_RZ~{<)i@N+;hd+*$ zM?ouTsqClE^~C~*Tv}$LT z|IBM-$P)Orsn%JJ@(CmzYiQ0sOf&Xjnz2{Yj2&D~Y9GRaJt7bBkmR!yEOmspqdcUT z_#_L5MSF>ywj>>uhiQlTh?O;JFCRaYnNrj$a0X>xb-u&IOzAj^01BDOEu+9+E5`>? z=M;W=GBY`j00SoJcxp7AWE7ST_vMyuq>qgQEmV*0_udS9ZvaxGQeI+`tN6S)i9$=B{AZNsS}a}Q1^k%cp5GVoEd+L(Bs@5p{d&kS+hR)T}yPQEi3l`J%)EXm!H zvw3yLndA(8>ud%#sVny<;kQ=`q4ZL-jcN%{IZ>{XcPgWD`aM2t$vIoj%LQ9rDX+5S z)ja$Z53k{~*RmO}mDkyFQC`n09Nr+0^6HIqB1_=VK09oQaeVE>_{`KaV+;)(95}wW z?_k$`y#x2MH*YH7ABZz77vKcKV`WC~9b*rK!Zcpjt$8}YL;R!VNvK3Lx28>A*gd*M zDpk2lH|py1Bhvgtuc3v*lbLA%6e_k7Oxw2x%Sy{2;tgP5^R#xna__IoK=_6>}7fOGKR~N;i{^tYf^DVY}{4SZ!xrQ7vQ=YrPN%3GaYDG z)PmUz4nF@Nn^Wv)wt*UVz|S13eF)u@i8)`9*yXDd>ytP#8BOXTYA*6R!<2ZHg@g}pPu>wn$6!T{0d=Xh(Sl=^!C%! z<72y)cOUE;8a~vM*gw?YmpF7}Z(na$Vntg=$FVJ49Ua|6-TK8H?He~G)Us9x4`Ok3 z^bD-n&Dd_cm=jlt#IF54o!#mR*F(KSeLcH(b?CEt-Qm99wfA86Fj4}`m{5_{P9==n zdU_-|fW2``Hv`C}$Fbtcx5Cz+m`3EhG_8qFCPz}0F$I>})h5;snBVRJ%k8>4Q^~Fl z)52V`xU1^7udD}^#9tv(bnYc8)Y<;j*jVPs1YI&u`K2e{fI1BsB*PX_%~BaI*Fix_ ziEoDFLAbmtyXTJ{H>HzmFr8A}dI^{!_B%^X7DkD)DjVk#ul}O=}v4`mA5`}&; zrik{c)FWejL%&LVnc>YDUcDm5pawCSmKjUVR=}ysd19;=EP16RuOgED>au%(^!)RG zhN(f^_^0^xHO%?in7mFd^6K?Gyup%3WAa9MQ-!=)-Vy^;{Apgj)sp`flWlDD&&b=# z_LMLG*P-sV20nUw*>l>&K+5)1qj*)rHhG67@1!fqck%GEmb}}NpJQ{;wQhNjB|i^P zHAAk>NM^iaYGy(q!*r-J)iGm+x?@mH0cYfaIYl!k9##_(J5SyY;%+?mPG)A#Aa%74 zzA-og9KXf1mUD8`C$cHlsAvLX-y`VV4(~~p6(5o&?VGL4mXOo^D%OGM%$yUg& z>N&a{492oIGdY@?>`PwA%phvU`{e_+d{90FGQ~gsUCD{F$*C<6mmQK11N+kY!nS-w zo}eD=0N8Q)eJC(TSjIQw8q7BCczf^?htya25LiVOkC(ouc zla_qamQTs2S?Fg1Mt(2oiBSNj!84~*lNb@z_bgt22wD`=TYyy`lF#z+Ia{8Rr)_yg zu2^!_hQRqHHVk5K*z$RK$*r)cEV*gRFUuD!`Jye)%5$vbS8Vx`{A!VY22gI6{F*Ia zmao|I-{seB`KtW-oUvvWoCe~k_TnWc0FKv5|C(cr=5C`8Xs z7ui)aS3fg0B`QOsqC-y=PG*9ecSzO-z}$d@93?+!2uKFNgHiH;)j%S|^Imm253qU?%!iq< zGklW z=h#?ZhRPo3^qk1++lgQ{m)Lk-gRj}6^r53c$hTK`ku_$WEkNLW1P+eKYkrzGxuWQh z{HMvp1LX6!z(x#U?wOsS!)!)+3)#sSG~gKY023z{poGYeLSE_9jiFFN#6564h`TQE zg-JZ$c~e55&`bJ2s+ZydYIvllBh?@?%Qo-|N`X94rLIoOLE~Q)+x3JCJ04RYdG@3- z>D8vPC3GdL7k1c9^UL7+)2GvCt7C8j+_#}LUOl)W9IqMN5Q)bJHy9kl0NGTesXMW_mOF5AI&gNQ}Mrsa)jHR4FE zRL*`IBM=s?Dgkz~dPiAf*-cq9d{fqHhQ+!%S$|CsRjHMIY=mJRL%yICRMgI^Mi9Uq z4$ETD?TOd#FH&#RDN2Z@neq4-7%S}S<2Pl~FyhB-MkBVs58X9*0LXm=k;EPSCdJkg z8Q>+RoRI?HHLHUBaPt=cwZ;G>SXs-*@F~q ze1HtRy(yi;jgf1zmqTz>x{fuLX_iSjgFu=#ufU|>H(YpAx-mvQsCr*b=;io-P3|=+ zk3K5Bd)49iHy~=^ZxgZx0SXrx%0)(f!nLjRv!ER-lt@B3R)EeAi66yo2rmO$714)XE~@`eM5 znE=Aep>wk6^Eva?K{nk#Cw`?QI$f6{A(n5#?d_+r|0ycgZPk_ver6?u+ z!ZaP>dq);?`S2-rz4jy*$u#22K*a>0_iGl6D zhlfrW`cjMIE~f8N5s9m$hc__qE0KGnjOqg115sTNjTk0<0LTq;#YP0bE(k&4#|dmZubFnvEGis` zGdiZ+1r24u!^_4MwKWq>qsHW)6^NE?aA&{)O(A466hpNMS>}#udy)J+Bj#0wTIMlV z!EgrpW7qQPTk^`z)@wKC1)Rd>JCbJ;oM1P4n6P^l@*r;uY<&xCBLyanO?c=vieJUh zEvu<<+)smbWvzbj7QqEo;lT+D48!PckM0;-e;BciWXJ{{iH}`1Nb)z~%yRlQ0!K2? zdyiXM;G)lAf;vilbD9T5X6mdY*e8<0}=KgKl4t z++8V#A%=oZapg_A?^saastG8D=JT~P6Sr3esVwa(a3S`g#h(3`s%~+$zjDXchUg_q z>6M1+Ax=&lR{(CW!45%Gd$GH7n~fWkQ-tQ|Mn#EvR+>B;kVkLD*gZi0xUyO|PYWm+ zOYbW+5Slp|srbu`^`M-h+RPo)4t8*C`35Vf;fy!+B#@YGs|z7XEp8SLr#LtZUR@#>}IAYUT0<` zI%Y17$DI~!Es_xn-(>WXp7?&XPPKQsDg4#?P>6vahgUf9L0i#+q9}yB%6w>pGQEI} zRfINH5&D-};sgY>2!W&H$f+?g?yfP|O&x**I}l#zHWp#U`2OTnm*WN5rGLyKcL*7P zezzFC>kx1D6lIhmXWdp@y;P-#h5DI8N9TwkRJUmeby8P&m2I&RAh`CN;ddaEEvhf8 zk&Q(z+uH@6%J3cIrbl2%MGp@Sz9I>Xzt*&+ex>8`+|jhvfj_B#nf1|FNWYRXbE#Fa z0J9=Mzp@&|*P7Q^RMqR&E7Xv0^5U649YL;$qP2D(?@qJ}J>wFL!0xtf`?n=Av2&H#L>K_>~Onzz6oe5&mH8 z$9T)%di;v+>o2C()F_m*K%h%5{;nx5Y<1bNQ*j~)hnq@?so0C11}*T!sEWop zg#cTRq!JIC_?}aV%p{Yg&Ll^t+@Xd#Ol2&Um4~x}4%Pt93+3ZeP$-`mW%6B}33#kN zdG`v$8XKF=>@XjHk2@PiQ!91{JlxgMxqD9E?(lu~?(^8?`D2u%pee67$FzTS;H7Vm zhoMHDG?m?R!%=Ai*+$<~^#4uMuqFhq;u)d{czCX$-;OB#JFn)ZUnc9Lf(YU(=?Sq+ zT2)9XOL4X>+2r9(&gKo+V7ytsm-7t_LT|{M4I_Okd@WL^{4Ov`)V?v6L^v<4`?Plk z$|Tg3h;U324Cl53-WY8v-NGfKO+Fu#!4f7yNn%GrX-VB}L+NcVQ+I(!-kMN|YGNcg zLo)`<9>kwPl5QsHkv;JBrCb0)h%l#561e3BvN<$@Z00h1pmu-f(>hib^L0VN!zgN9m|TeV=Z6yzVa615#@y07Y~p2<{EH(@KTVY^W0wDjE$Swc)sizRx7P=P63T)$SkX#*Y16`~Jgq94gc1 z0bKqe%x!#ueo&2T@GP!MTo>%yv&XLe#qV_kc=6X(41j6m*_r1)5C(=k+#yn_7N&^c zX2K4U5|TwxfyH82meNaKLU}xi%1WL=#e_+?gpC{(t`juv;(=JRyA95RS@ZYROVqs8 z;~&|W^c03#mL3SeEsv{rOYTx|EEjIU+0%3iKnc-qnHpES3F_dp6z)nPAub4+a>qIl zHU-iIIcrQ8@)LkgM}nE1vsE7KpG~(?5l=53fNBjI`9kf_r5$I9<^-o4PDjRqML@F$8QE6wg4&H2}<~|V| zONDsw0IE6q@y&x)x9Gc;3J=@h$C~ja;0AAp0x-o8E!#6#fLn;I?EoRiXEOFK556_( zxHAUCQofY$mU}VPT3tkJKOHOIP0jX#h}eBZ!1|=ykzo~ZWUp{zPxG8_83^-k$78VO zR^1+2_Rt&vpQkT5pf?!$c~WaV)fW#228IXDfq|aJsjfimMzqM89CRVJ656mq@XnJ6 zKx#IxgmZw4fu5q(2f)SwUk${qBE($~2NuW&Km!4Np;=iQ2z`I}x$oU`0ZrnskY{GKVh#DD z4Id6ACsJdpHu+FO#41AY6l%}aP_HhI$XW1d0;oBCIz6=t9LZqCiUP&sbGnS@0xGP9 za#Cl(fZi(TVxP%OfJHEPI&%&f`-(hvuB*JEro6&S7W7Qef*xdMe`@-4W)z+`lzS;R z_9)z=;Dez@K}(@PvsQsN2QA?9DYwkWWOZB9IhsVoFA&XveB1(cV8POo$SnkF3mOc@ zk|VVLU$to?zQe&_s8*m%t&FeCCN!{cOLqngJS-hTHB?;wUI+dV?Q^F`WHAoNNL%FHJC^tc^nm6|`O&>N` zOAdjXqTIRx{|p4k>=W0}Z7;q9^PDX~1Fst6S(arpXGTFO>Dj3So)+!64$GhoOiZhy z*w7J%Ug-TYY|Be|cz}nODQi%AN`44dpY%^WqI?D$6Q}bXQ&eB+IMA0oks9+l5`Ng0 zM_BS03td5dn{k=o0aa$G_)>@fWQ*W{@{D%mfE87;1DGYO@!-pW2l#h@p(vd02X(x_ znp%~eaabYV8y|S6C3tW#xLJ~$Z=V)rK>&P)!aM;;jj za~Y%Ls;sJ)=?ULU8Z{h((HUGRj68y(jo`b=d8~#Q&trJdGm$(oMqwj;C#V-ge1N7J zyCtpk+nt7AtIR}l@&cx2odSJI894hKn>eItil+;PNKR(2#;~yy%u^+XAQ`gt{>)^m z$1Mc|LFxYl1lr~y>UK(2G?vy*LX+kPYaO7vkwCS^DUsG``!W;LD2{$8c!|mB*>==R zrB{d7gUW%*LR{_7Or~Fn#Ben@mOf?7zVa}dC{h{}XI38AEwl4HIB9ogMtw&Q*;yaN zNkeZrF@`dkv7z)CM|mI*SHt!S5JsIOy+>dnLQScfgqeBbc%Kk?7br~tb9p1xhe9op z)*H~a5%}IJy$oZK_g9ZXeJT4iTHVOUn-M*|1+2123#4CVJXkG|Y(=4lR6YO;i`b5E zBP<<2mOduyd1Z&>IjN+z10rGoacYcIC#r!mRX0Xp(NS~x`QN1?v%^ZG@;`PUx*P$Q#OvN)3UMEQdyp^)78C+Ink&)8z=$U@=Y9BF z8~vQtRbZQ4NcX2;?v>NoSh+Ov*<#){@z88h?PfWq_ngCN-}WZd_X2D}9>$Zw4t?7Y zv{hjKVN>Qp>w?vU{D`floRUF5%*Ln3VFNwCwia;oKevI$TFLzqd1#@rf;O9(`e1uA z*ko>x*A&dI_Cat1=JWVchzc|a&^)5lmn#Um+`IXJO-yR-kBw_bd1S-#*QN-3l4VV; z!Rn$^d$C^rdi8V3V>ySpCL@NTG5P{ENV^JoSV{wySL6l*tgGb+*B?;#0~Bx;SORId zz{;UQw#>i4CjaPiO9D71e|wQ|J`2pHCX-`o7xXQ$z2)GV>zIf!s2wGE3tgXT`UQu_ za*JGYi(GOz8deg&rLrzcHWd^P`4Bv+YWlf`84D~|ZXq~$bi8W@=GWYklm_~3FU$f_ zRSK+w*?A&`kwgel99biYF-RLhW*a@5qH;&3hEfcKj=(o}B)|^?QjY#(92J8e-1*%M z;JSxAwoXi$+xg&NWBKPm-r`mY&Ms1?=E)1fGAXpY16e7zj2r|+2dl}lWP0IV<`l`+ z9E2f&Yh%zOjVa6%fKX+S4ji@ra-2976dplIo5n1%K8Ong61p+>0+OsF;s*?u`=A$) zKz-*!au2q23tKv^kpN*Hm1XIAj(qL2d~%)#(6@)>l{~<` z&0%>p4?o3Q?bXJT*HsAo(21fSn?SC={(NT-^c3T&#Mnu z^1&Fk+YedtVJbO%gm0eUn~(Bvi3d6-VX()`mVBJ#_b;-%PgKY+$tQXE6x;b}7J|bT z`7}%Tj3u9qVa2Oa_#9h?mL8^Sou^{3QGSLuS7P|8*Vw@8?E8(Ve4dZr!<%5{b7UaSN*Ou{ej@xh0N-6BP*qD$L$^k8IgZKwwwx>! zKgkVWg&0;ZXCNzhd?ljLw~aX zJLl`Rd_%s;6u)K5Z`04t@6gXq)?%m|ULPl>z+zyU-?ioUE)Nko%K$3N0yFOMkKK@!{p1?}@W01TS}3UieF z31bxl6}B#9G#$>I!@aR)2{fW4!$@-pXY-iyg7SQ4;Z_#ajwpoE){zaCnw(C<#f^tu zR*;Y8utDh`1*-kp2bJc%dF^do@S(&&b9Zf3s(enZ_b~ZfA&C*6c=?Rnhgt&D8sR2c zh}i;sYG#I6NuK6x8lHhR8eSXS*^Px?V8+Yr8eWCWY{C1$^o13*Gygqg7Uq4Ppn8th z#y<)Ab&lF0(KO_HNjN!&QiTH;6gRxrJO>h_ceb3TSnXhO(;2W@{g?(}vbGEIv~NLp zT1O9Xj^H$_pt0IBXMLhTCy`n=jb5RJ_F%X#NpJ31mydgqe@wrE=L$!v??C?(%Il$V zeuz=vLd+)4!5MRtDy}*t9$MzHfItH7yv_jB^Nc;l(*w7Is?E+DkIt3j-RLmL0FrBq z!ScNyS8?J;>WrwL>inQN19`%I2@xiB#=fS`5K^f#umE+&mW(q^T~5j=98crU)vJPd zv=lU^(yU_iEBDgMUMh>)a-@ub*8aYf;B52 z+>iw%TdPaK9aFb3s(C^_suDM;u+C4)J8nwtFkNkw>nGQw4sMa^>E6gZxk2InHCZ&! z1}=L;8`yG>!5d_?}W_n9PXUK8CDNAv=?5ZRh!)@{9aFqmKLh+T_>90+X zN2`vZ@wYHdT|8rv2EXC85jDKaB((-r<6LCo-mM!Yeca zvV2dCn@x>d+#2x&E|yqh)Tyz<)VS5DQKi|YYy2hs4MW6-%!C-nnY_#-3W0*%oqdR~ z2<`gEB#w*ilv>nYl^vI#|32QsElR+9sDJF#?;#Kgc)#VU?819pbqNuEQ}sWB)fht6 ze~THXKH(L)J9|lY+vaHpE_dU@-g8CvWS_3b<qI2%#oUuOccK5<9IJ;3GX;x4&b6gr@SWj>0}*FA$%9_(}~vm z60LUC?|b_rwQ~-WdWAOJ)di?VhTmkP)9TuV_`zzc2!GDq}3XeFZ!R>vf#9 zQiVemV>K0(DR*p}xiIlpeNzq&#}AcO!@t=}5Pry+07H1kkd|A(Zy3Y`*nsm9oNIAD zigTCB?Nfdj``YQJ_m+ZPjbBkEN`p@hfxPKP^oGo-JS`qbfud4RIS-^jwMNC8$_I=# zLxU5Df0n>bMM;2M?Sj@oW`vguoUIZ7-KEI=po=sCug9|qm^6o)pZ;pjuPEe zN)4TBtg$G}F>;&@^F!n5Qv)!vH3&ryZfmf%k4LcTc*M{9N_2g1F!Ln1K4S;sY}E%K=Rc7eB~gv< zs&psaE|r_AtulZ=Nf1vyY2At6trUzW6GkV>6mL*QIsjg67*Xl^{Fc@|S1U$SDP--QYm<*&rO-`zIiR4EHl^JI%k|Pwg2-K=|27JE5a$vTK?ua zbGQ7LpScw$Gb1xo_mU+IIJwkA4(RW(kFTB20nj>EMbP<7+bu!UR{2);C|Rn8{6uE$ zW@;3UZAe$drb4SqR4M1y__`tA6KpZx~JTaU+X^h7E93*B7 zXY}pC;avR4Oljb$LKH&>6UEF@nk!Hx#8qLHW*udcX$q<|GqPk@sk$u0RScV0pi1*| z+p0D-BL#mOk#O$VXYP~^?TmpX@h%=9i9IgwF2@04*b#XTuYR5f2x5=RFYo|S>~TSu zmE-b09^TKlABe$;)CVp35LX0*u?yrQF#*TGl1n5KF305K6umwnpNLWP$}FGa0Rq?K z@);gJ%LAmXzeFkP6Y?|<&s4}2xf%nd3@Pgk`MeUW-jHAB%@?BbMV=vCy&=y<FOJLaS@NwI)P8=S+5dof|1c_l#Phc;`D2Eh`5(Oblc;=$ zDgM-wKa0V~HS*pie;$?p8I`|a1xWmtG0<;#zC->hDu2zg|0V_j$e%Lh-}3N1cIEqg zfnFS!zl%{KV#$vz`Eg7hlHcS*#CW0j0y_~M_-KzUMq+tKAj##ptLO;y$p;j@YW!$= za(X5?=14v_2bP1-15AWsOmdH}e{$rEaQ4Uf}Zl7}k?%oPCZ-x_%lj&1%G2%=F&lhnh;U+gx z{#S!`0!6~Qm#V>JoBPd0nw&4fQPxn=Ls%}!A6$hC%o(AoP?0G$>tQZ*!)&pBoGsu5 zremFAm3aR4b{0P+R>Ib3C zp)FPj54U1^gtoDjcVg{??!v+dZMQ=^I0*A%UF6OHwFMb>Ce8vp;6UNoQ1vifQDHlt zOub?TG@%0cGz9MTGc$5=d?i+kz$3;acI!EXpsCW@SNq^18`~Uqr}=Y-O<-QFH?JIc z9YHiaL|kNX73qnynMYE6usnmzHAmv-uwGT8>$FF0XP-GCzG{t^)Y z`)GP9t*pb0&B&a!Fy~;pHaZF{9Z?GnBJGvSXW@=3H&E-AwsAv|`4HbJ~Mna^+qrRd6j#2r=GSb4WoTmW8$c}Gogg_PAOFJHPVxNcr?vuK+ zM$=PgR1A9$Z^?0D7EYZ{Ps?(U$0J~!jEW6G4iHgrNJ@x{;;eNcc&0p^e-v)>4~U;S zPna`MLfn_oyjPup+Nv{9G<62{iZi|cB4j&`uf$ys*fkKe%J!BG&2WFi$WvuJSdeln zLqjNKD8&q%=|#K}763P8!Ep6vB!FKA*PZyQ5dB>j*<|bu;1VLP6fdA|fnd;D=p@9e zO~P*=Ay{zor51!$X1!1jsD`X+ky4+iKI2}!!o8Ywucq9q)$Y|=_iBxMwa&eQriLkb zg}PGJC2)BKHdg8eB7WR7>YHwLvsm8@s+%T#b4=YZBsH6i5n1B&4djC9+sDy23di4% zz9Gbx1&RGKgs@7KNFVZ8kk2jeZ^acwbd697Pzofg_$rK718uls1sIJLZ7{i5-4;ie z)cb14@s?8$1+Nh;du?O5#`>+RvaT^4haSnQ#xP7hffha~D_L4K)G1VIC{TEl;&zqO zYS1^P)k)LpBiE&siYaYPkE21CC5-kmo>#c(G55YhtE#j%qh|x5wkN40vyl+7SOwPpYx*~13ybDja)3oKL z?7-#DE6|sT-+fhf#B6KhOl{rH?d}5E-zIMldaw0E@cte0&Y<^3(=l*h6i{rt(JAXTF*lZZ{b*@T3UI4cMZhmD!b>a+94`}bitLWvT-a^ z_A9_mihH?Gsjzfn>Y{hz$P~6EYkV*X59r7o>UQst$mP=A8H}ze954`BQ*S(4D6`@* zbcX=?Ff)eH%V>oaHibK&La?+7gvZL?6BKM*!xh%CIUsy=b zU^pnR-*53<-ZGlT@vscQia0^u7 zA|Y`7%UWO`tgcKf67UQV3(q6rs1y6WACzitjVg57 zdhB*O%M)U3Krcga)GGfG+N2@x;VJ&at zLlO;e)|OzlYis!hxvNBPVW5YQor^GUF@&>=LHn#_niizxf?0|wi3Njc_c#n#ooVc# zGtT7Kz99q3hWWjdW)YUUuHRR-7MwGeW z0K-o64L8D#G3Rbs8sz%@SA^Fc;I4E#9FLfZ8?C$uwFYmDzSgI5JkZ`G(H(E3Slwf{v!$YBkE*HLUj=gbHb&lH>F+*wrwSlZ`0{T(c^ zv1Kj85Sw!8&>x1d^l`E}B)7nA3&0%aV$o(;PPI;WG}9bCo7%u*p2L{9^RPY}X3bL$ zps1r7T7rFCtAJ{}qXJ-22Rr31ssR}t2s8uZAONgZ&@>zNOoP)JgPkyCy}?dYtS{I% zL>!2#9Xc{e!XyFFP{vqfmWoBz1XG8o8-7d&Kh*_#f`@_PbVI1(bD>RnNkHw!9CSv< zdSeoHha^unJefuqg5S~mk}lc}5mp^_K=&H=rHg5lI`0sQ$Yjiarz5JdLbuR(h0{{Z zGLz98wFzXD?G(MiO_5)8Yr%KE9plobEpLU30J;e%=(8~kEkw&GDZvXl#7}qf-h+bay?2j=h z_>0Qns0^0vHn)}xS#rdpFS^LMCJ*SNrF6U(Btv9eqcm~N{PeOzX)15Lx){%3BzG1V z^vYoi&x(&Z8M;%Nj|@6#+;Ev~TzHty?q*~buY-4y{i>)M*NoomOSi_JegQe_ z%=0+udCYLngH1yjXqb_oTbw=rqL71Y<(MM)z)1B>Sq08*z?$X8yP*?OluoShY>7bH zyjD?aQ>l@e$@KJv4io$8+q!N|y*hMg6yTH;C8<}8CC*Ne%@Pi}x>wHZ@SIUF`JUk|dBz98nNSe%<8fr9 zq}|vQ2%yOl4l(#jL0ndKQZu*ccD#all z!2$fe%Henwf?qz%jK;zUY!_+OjR>Ki*eOK*5x9M9*;^kWldl5j?Gf72l|3o7Jl$ZN zbq6uuX7QD!Us<`YqV?9}60MKAY0Im&$Lg)eq`V=vegv0z!^>0KV~l|nX^4%mv$(1P zHN2F$8+q3dxh^%^BRWmwl#}Kc-Y?7QqmL{0Z{%EVBB!7QC@9*p09jaW37iF1U6wMi z8Mc!VA8D{rNO?b@J4^dB~`6W23^AyvZ0h8Ouo8o0wZQF!&05Z>&3Opls;OofY_OoI49kn?3?x z(wH%^%Q!D+dUM88-qs@NE3)a`^0&cft)816#-zt*5nRuk_xXHHyx0M+S~`0*8W%$I z!gaFHVOJp1PeA4pXS3h!X09=r)wFPOBR-JH?cxGqoz=JBfBF8;Uo62l;jaTtm;>^t zNi5%v-%J8R~w+rQZs=cbGGM^^?S-q2V$g zve2fs^nAz@s9D?KY#^A;+zFuozKZDJq-5R2jp}w8rUIP~V#~x8nf;ufRSNW0N53Fo zvl(~O)og%Cw;9Wndf97AcP|0(DE;CSvV_2|bP0m_QQmbxeM|`pRSC@~p$v9qO33p!O=d0|(u8>#=a);|Vm2q{U$vrEbSLUe;go5V zHnk2q)oa)DEP~A^cv_RKTy>*)Goc%^Ar|3fDOYVU&G#**mw#&bUZ4#`9RN&f^9X$gp5Y`Rh-IxhhZ*dyU^KZZsA!Z4flmB{++=XxG-J`Y2)IDeNeZos9RwZC(qcVExoP<#JAZwda&Ial-_D~GEF zLeF9uY$rYD?GHL1*BP8Rdqs0*8_S%(=F4fK^A#;2kyH0S6)0g;N3LMB!J?&+xv&4& zo;$Gcf;JAVGg53s8k}O(h>R5|=ix1*MO#B}6Z(&>d7?-u%5Je(gK~@dlLAG#s%XWE zYIGW<`qqHi5;R7$wkWrlg9VCFyz^qMAp)-dI7V+OP>fmJd87U8eLwn*J24piEp-aQ z`O?Mb3Y0_^lg1JJtqQljd&R#YFMkRAoWDyKw_w`|8Y4{-1(){ruYBoO{}e^=x7sNR z=SvsI!NLeC&Ep0qxX5q6`t7IRjUxD4o>L?|83q<<6flE}d)r4p(fv1AZ~U#zDK1$a zTwIRgZg8P>Prv%RA!O%|8;$dK>Ehe4l?8R%6xt8BTyQrUTEiDJ0tJ=o1sL7Eg+KZy>>plq;@P+7lw1xNFnh_xrocPD^vreo_U3O(PT7A4I5m6O zvrdRBOJDoFGJJae?#!uR4;I6$6)2eMQN<1(`;N-*oIi*P_{**2eQV}d33uTFANU7v zdE}WNVjl8G0?zrnbnzZw|FiX^FLNrm?F&9IJp4`+$=^n&Oq?%WoZb{%tlk>ToaD4o zCd9#|zqKOX^$C>5-(5MSAI9enYIJbvjun6)S@S7kzRCM zdR5h@Q7(Twa?1Y^P?}kL;VHj(KmO{yuWVS2^~+!GJo-n70B5bovlxnW=HfpuEW3_Q z@aO2uuuqpRX13o#CB=L6*hluhbt!toUv6cOVjySjk?Mv4d#jQ&)0yeX^r?a%@O|ay zKimtXlD|FdlKH!I@%dfzt_<^fEIkFa&qC|*ix<{h_#wa+e|w#(aK3c$W1aJ@?S#^) zE?!@K><8`NgfN)Ddvoghho1S?XFxxKlZ+Lwbm61lnn5@phV=2l=XHJatTcG(zW%{; zCtimU0NC8WOBdhq z(s@-BTzuk7wbogRx)-jd0}q-_(J;4Pe7VPiINXT*_$d{ z#epr|v+ls>-tg(EA7IS+Tjh*B&X+F!)N%9RCKUJb$^f@$746DSZ$=e>0PNQ>T+>)0qOe!keD{=*53U z_xa1+u-^Up;No4f$jCzOOI_&7jHX;EN$|vcu;cvwKLD=IU+(t)*Ke4mo~(`PF20k(_u+{@VQEWU{sW{!{a- z&HJqw-Y$3n`@=_M>pOaFUiAeR?{_trE&iv!I(zX$u2Z2x)4=aIEn9xm*XLEfaiiw{ z9Des!+48^j&3Tn?oL%|L_j@ABmjBk@nOFJ7FOk1|zf+iO`NzLCpYnshuHO(KTl!bO zA6)vZW&!>V_!W|~Rb2W}kt!Tb+TeEkRYS9dX8w0@p$>1bu%f8H;eKVJY#kr@=i+r7 z)hb4WOTo?e%Pq4-zYD^sAezu=zA4%(#q_t^FU83g{%57d3(wsnBNU^_KK#4h0QwGE H!6N?;_hS`? literal 0 HcmV?d00001 diff --git a/vendor/JavaWinampApi/1.1/cpp/Makefile.win b/vendor/JavaWinampApi/1.1/cpp/Makefile.win new file mode 100644 index 0000000..206b141 --- /dev/null +++ b/vendor/JavaWinampApi/1.1/cpp/Makefile.win @@ -0,0 +1,34 @@ +# Project: wpcom +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = +OBJ = WinampController.o $(RES) +LINKOBJ = WinampController.o $(RES) +LIBS = -L"E:/java/Dev-Cpp/lib" --no-export-all-symbols --add-stdcall-alias +INCS = -I"E:/java/Dev-Cpp/include" -I"E:/Program Files/Java/jdk1.6.0_11/include" -I"E:/Program Files/Java/jdk1.6.0_11/include/win32" +CXXINCS = -I"E:/java/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"E:/java/Dev-Cpp/include/c++/3.4.2/backward" -I"E:/java/Dev-Cpp/include/c++/3.4.2/mingw32" -I"E:/java/Dev-Cpp/include/c++/3.4.2" -I"E:/java/Dev-Cpp/include" -I"E:/Program Files/Java/jdk1.6.0_11/include" -I"E:/Program Files/Java/jdk1.6.0_11/include/win32" +BIN = ../../wpcom.dll +CXXFLAGS = $(CXXINCS) -DBUILDING_DLL=1 +CFLAGS = $(INCS) -DBUILDING_DLL=1 +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before ../../wpcom.dll all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=../../libwpcom.def +STATICLIB=../../libwpcom.a + +$(BIN): $(LINKOBJ) + $(DLLWRAP) --output-def $(DEFFILE) --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + +WinampController.o: WinampController.c + $(CC) -c WinampController.c -o WinampController.o $(CFLAGS) diff --git a/vendor/JavaWinampApi/1.1/cpp/WINAMPCMD.H b/vendor/JavaWinampApi/1.1/cpp/WINAMPCMD.H new file mode 100644 index 0000000..068b55c --- /dev/null +++ b/vendor/JavaWinampApi/1.1/cpp/WINAMPCMD.H @@ -0,0 +1,62 @@ +#define WINAMP_FILE_QUIT 40001 +#define WINAMP_OPTIONS_PREFS 40012 +#define WINAMP_OPTIONS_AOT 40019 +#define WINAMP_FILE_REPEAT 40022 +#define WINAMP_FILE_SHUFFLE 40023 +#define WINAMP_HIGH_PRIORITY 40025 +#define WINAMP_FILE_PLAY 40029 +#define WINAMP_OPTIONS_EQ 40036 +#define WINAMP_OPTIONS_ELAPSED 40037 +#define WINAMP_OPTIONS_REMAINING 40038 +#define WINAMP_OPTIONS_PLEDIT 40040 +#define WINAMP_HELP_ABOUT 40041 +#define WINAMP_MAINMENU 40043 +#define WINAMP_BUTTON1 40044 +#define WINAMP_BUTTON2 40045 +#define WINAMP_BUTTON3 40046 +#define WINAMP_BUTTON4 40047 +#define WINAMP_BUTTON5 40048 +#define WINAMP_VOLUMEUP 40058 +#define WINAMP_VOLUMEDOWN 40059 +#define WINAMP_FFWD5S 40060 +#define WINAMP_REW5S 40061 +#define WINAMP_NEXT_WINDOW 40063 +#define WINAMP_OPTIONS_WINDOWSHADE 40064 +#define WINAMP_BUTTON1_SHIFT 40144 +#define WINAMP_BUTTON2_SHIFT 40145 +#define WINAMP_BUTTON3_SHIFT 40146 +#define WINAMP_BUTTON4_SHIFT 40147 +#define WINAMP_BUTTON5_SHIFT 40148 +#define WINAMP_BUTTON1_CTRL 40154 +#define WINAMP_BUTTON2_CTRL 40155 +#define WINAMP_BUTTON3_CTRL 40156 +#define WINAMP_BUTTON4_CTRL 40157 +#define WINAMP_BUTTON5_CTRL 40158 +#define WINAMP_OPTIONS_DSIZE 40165 +#define IDC_SORT_FILENAME 40166 +#define IDC_SORT_FILETITLE 40167 +#define IDC_SORT_ENTIREFILENAME 40168 +#define IDC_SELECTALL 40169 +#define IDC_SELECTNONE 40170 +#define IDC_SELECTINV 40171 +#define IDM_EQ_LOADPRE 40172 +#define IDM_EQ_LOADMP3 40173 +#define IDM_EQ_LOADDEFAULT 40174 +#define IDM_EQ_SAVEPRE 40175 +#define IDM_EQ_SAVEMP3 40176 +#define IDM_EQ_SAVEDEFAULT 40177 +#define IDM_EQ_DELPRE 40178 +#define IDM_EQ_DELMP3 40180 +#define IDC_PLAYLIST_PLAY 40184 +#define WINAMP_FILE_LOC 40185 +#define WINAMP_OPTIONS_EASYMOVE 40186 +#define WINAMP_FILE_DIR 40187 +#define WINAMP_EDIT_ID3 40188 +#define WINAMP_TOGGLE_AUTOSCROLL 40189 +#define WINAMP_VISSETUP 40190 +#define WINAMP_PLGSETUP 40191 +#define WINAMP_VISPLUGIN 40192 +#define WINAMP_JUMP 40193 +#define WINAMP_JUMPFILE 40194 +#define WINAMP_JUMP10FWD 40195 +#define WINAMP_JUMP10BACK 40197 diff --git a/vendor/JavaWinampApi/1.1/cpp/WinampController.c b/vendor/JavaWinampApi/1.1/cpp/WinampController.c new file mode 100644 index 0000000..1b6f46e --- /dev/null +++ b/vendor/JavaWinampApi/1.1/cpp/WinampController.c @@ -0,0 +1,587 @@ +/* meu .h */ +#include "WinampController.h" + +/* mingw */ +#include +#include +#include + +/* winamp sdk */ +#include "wa_ipc.h" +#include "WINAMPCMD.H" + +const int WA_CLOSE = 40001 ; +const int WA_PLAY = WINAMP_BUTTON2; +const int WA_STOP = WINAMP_BUTTON4; +const int WA_PAUSE = WINAMP_BUTTON3; +const int WA_PREVTRACK = WINAMP_BUTTON1; +const int WA_NEXTTRACK = WINAMP_BUTTON5; +const int WA_FWD5SECS = WINAMP_FFWD5S; +const int WA_REW5SECS = WINAMP_REW5S; + +const int WA_PLAYLISTLEN = IPC_GETLISTLENGTH; +const int WA_SETVOLUME = IPC_SETVOLUME; +const int WA_SETPLAYLISTPOS = IPC_SETPLAYLISTPOS; +const int WA_WRITEPLAYLIST = IPC_WRITEPLAYLIST; +const int WA_ENQUEUEFILE = IPC_ENQUEUEFILE; + +const int WA_VOLUMEUP = WINAMP_VOLUMEUP; +const int WA_VOLUMEDOWN = WINAMP_VOLUMEDOWN; + +const int WA_CLEARPLAYLIST = IPC_DELETE; +const int WA_NOTHING = 0; +const int WA_TRACK_LENGTH = 1; + +const int WA_RESTART = IPC_RESTARTWINAMP; +const int WA_REFRESHPLCACHE = IPC_REFRESHPLCACHE; +const int WA_GETSHUFFLESTATUS = IPC_GET_SHUFFLE; +const int WA_GETREPEATSTATUS = IPC_GET_REPEAT; +const int WA_SETSHUFFLESTATUS = IPC_SET_SHUFFLE; +const int WA_SETREPEATSTATUS = IPC_SET_REPEAT; + +const int WA_GETSTATUS = IPC_ISPLAYING; + +const int WA_GETLISTPOS = IPC_GETLISTPOS; +const int WA_GETTITLE = IPC_GETPLAYLISTTITLE; + +const int WA_VERSION = IPC_GETVERSION; +const int WA_FILENAMEINLIST = IPC_GETPLAYLISTFILE; +const int WA_GETFILEINFO = IPC_GET_EXTENDED_FILE_INFO; + +HWND hwnd_winamp = NULL; +INT position = 0; +STARTUPINFO si; +PROCESS_INFORMATION pi; +char messageReturn[255]; +wchar_t* wMessageReturn; + +LPDWORD temp; + +void initWinampHandle() { + hwnd_winamp = NULL; + if (hwnd_winamp == NULL) { + hwnd_winamp = FindWindow("Winamp v1.x", NULL); + } + if (hwnd_winamp == NULL) { + hwnd_winamp = FindWindow("Winamp v2.x", NULL); + } + if (hwnd_winamp == NULL) { + hwnd_winamp = FindWindow("Winamp v3.x", NULL); + } +} + +jboolean runWinamp(unsigned char* pathWinamp) { + + /* STARTUPINFO si; + PROCESS_INFORMATION pi;*/ + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + + // Start the child process. + if(!CreateProcess(pathWinamp, + NULL, + 0, + 0, + FALSE, + CREATE_NEW_CONSOLE, + 0, + 0, + &si, + &pi)) + { + return FALSE; + } + + DWORD dwResult = WaitForInputIdle(pi.hProcess,INFINITE); + if (dwResult != 0) return FALSE; + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + return TRUE; + + +} + +int getListPos() { + + initWinampHandle(); + if (hwnd_winamp != NULL) { + + return SendMessage(hwnd_winamp,WM_USER,WA_NOTHING,WA_GETLISTPOS); + + } + return -1; + +} + +void getPluginMessage(int param, int sendMessage) +{ + + LPCVOID message = (LPCVOID)SendMessageW(hwnd_winamp, WM_USER, param, sendMessage); + ZeroMemory( &pi, sizeof(pi)); + GetWindowThreadProcessId(hwnd_winamp, &pi.dwThreadId); + pi.hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pi.dwThreadId); + ReadProcessMemory(pi.hProcess, message, messageReturn,2056,temp); + free(temp); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_run + (JNIEnv *env, jobject obj) { + + initWinampHandle(); + + if ( hwnd_winamp == NULL ) { + + unsigned char path[MAX_PATH]=""; + DWORD size = MAX_PATH; + + HKEY key; + DWORD tipo; + + if (!RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Clients\\Media\\Winamp\\shell\\open\\command",&key)==ERROR_SUCCESS) + { + + printf("0"); + return FALSE; + + } + + if (!(RegQueryValueEx(key,"",NULL,&tipo,path,&size))==ERROR_SUCCESS) + { + + RegCloseKey(key); + return FALSE; + + } + + if (!runWinamp(path)) + { + + RegCloseKey(key); + return FALSE; + + } + return TRUE; + + } + + int version = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION); + return TRUE; + +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_exit + (JNIEnv *env, jobject obj) { + + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_COMMAND, WA_CLOSE, WA_NOTHING); + return TRUE; + } + + return FALSE; + + +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_play + (JNIEnv *env, jobject obj) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + + SendMessageA(hwnd_winamp, WM_COMMAND, WA_PLAY, WA_NOTHING); + return TRUE; + + } + + return FALSE; +} + + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_stop + (JNIEnv *env, jobject obj) +{ + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_COMMAND, WA_STOP, WA_NOTHING); + return TRUE; + } + + return FALSE; +} + + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_resume + (JNIEnv *env, jobject obj) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_COMMAND, WA_PAUSE, WA_NOTHING); + return TRUE; + } + + return FALSE; +} + + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_pause + (JNIEnv *env, jobject obj) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_COMMAND, WA_PAUSE, WA_NOTHING); + return TRUE; + } + + return FALSE; +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_previousTrack + (JNIEnv *env, jobject obj) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_COMMAND, WA_PREVTRACK, WA_NOTHING); + return TRUE; + } + + return FALSE; + +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_nextTrack + (JNIEnv *env, jobject obj) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_COMMAND, WA_NEXTTRACK, WA_NOTHING); + return TRUE; + } + + return FALSE; +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_fwd5Secs + (JNIEnv *env, jobject obj) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_COMMAND, WA_FWD5SECS, WA_NOTHING); + return TRUE; + } + + return FALSE; +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_rew5Secs + (JNIEnv *env, jobject obj) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_COMMAND, WA_REW5SECS, WA_NOTHING); + return TRUE; + } + + return FALSE; +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_increaseVolume + (JNIEnv *env, jobject obj) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_COMMAND, WA_VOLUMEUP, WA_NOTHING); + return TRUE; + } + + return FALSE; + +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_decreaseVolume + (JNIEnv *env, jobject obj) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_COMMAND, WA_VOLUMEDOWN, WA_NOTHING); + return TRUE; + } + + return FALSE; + +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_increaseVolumePercent + (JNIEnv *env, jobject obj, jint percent) { + initWinampHandle(); + int i = 0; + if (hwnd_winamp != NULL) { + for(i=0;i0?1:0; +} + +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_isRepeatStatusOn + (JNIEnv *env, jobject obj) { + jint status = 0; + initWinampHandle(); + if (hwnd_winamp != NULL) { + status = (jint)SendMessageA(hwnd_winamp, WM_USER, WA_NOTHING, WA_GETREPEATSTATUS); + } else + return -1; + + return status>0?1:0; +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_setRepeatStatusOn + (JNIEnv *env, jobject obj, jboolean status) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_USER, status, WA_SETREPEATSTATUS); + return TRUE; + } + + return FALSE; +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_setShuffleStatusOn + (JNIEnv *env, jobject obj, jboolean status) { + initWinampHandle(); + if (hwnd_winamp != NULL) { + SendMessageA(hwnd_winamp, WM_USER, status, WA_SETSHUFFLESTATUS); + return TRUE; + } + + return FALSE; +} + +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_appendToPlayList + (JNIEnv *env, jobject obj, jstring mp3filename) { + initWinampHandle(); + jboolean iscopy; + if (hwnd_winamp != NULL) { + wMessageReturn = (wchar_t*)(*env)->GetStringChars(env, mp3filename, &iscopy); + int length = wcslen(wMessageReturn); + COPYDATASTRUCT cds; + cds.dwData = IPC_PLAYFILEW; + cds.lpData = (void*)wMessageReturn; + cds.cbData = length * 2 + 2 ; // it sums white space + + SendMessageW(hwnd_winamp, WM_COPYDATA, WA_NOTHING, (LPARAM)&cds); + return TRUE; + } + + return FALSE; + +} + +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getStatus + (JNIEnv *env, jobject obj) { + jint status = -1; + initWinampHandle(); + if (hwnd_winamp != NULL) { + status = SendMessageA(hwnd_winamp, WM_USER, WA_NOTHING, WA_GETSTATUS); + } + + return status; + + +} + +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getListPos + (JNIEnv *env, jobject obj) { + + return getListPos(); + +} + +JNIEXPORT jstring JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getTitle + (JNIEnv *env, jobject obj) { + + initWinampHandle(); + if (hwnd_winamp != NULL) { + + char title[500] = ""; + GetWindowText(hwnd_winamp,title,500); + return (*env)->NewStringUTF(env,title); + + + } + + return NULL; + +} + +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getTime + (JNIEnv *env, jobject obj, jint mode) { + + initWinampHandle(); + if (hwnd_winamp != NULL) { + + return SendMessage(hwnd_winamp,WM_USER,mode,IPC_GETOUTPUTTIME); + + } + + return -2; + +} + +JNIEXPORT jstring JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getFileNameInList + (JNIEnv *env, jobject obj, jint index) +{ + + initWinampHandle(); + + if (hwnd_winamp != NULL) { + + getPluginMessage(index, WA_FILENAMEINLIST); + char* filePath = messageReturn; + jstring strReturn = (*env)->NewStringUTF(env,filePath); + return strReturn; + + } + + return NULL; + +} + +JNIEXPORT jstring JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getFileNamePlaying + (JNIEnv *env, jobject obj) +{ + + initWinampHandle(); + + if (hwnd_winamp != NULL) { + + getPluginMessage(WA_NOTHING, IPC_GET_PLAYING_FILENAME); + wchar_t* fileName = (wchar_t*)messageReturn; + int length = wcslen(fileName); + jstring strReturn = (*env)->NewString(env,fileName,length); + return strReturn; + + } + + return NULL; + +} diff --git a/vendor/JavaWinampApi/1.1/cpp/WinampController.h b/vendor/JavaWinampApi/1.1/cpp/WinampController.h new file mode 100644 index 0000000..7f2ace1 --- /dev/null +++ b/vendor/JavaWinampApi/1.1/cpp/WinampController.h @@ -0,0 +1,285 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class WinampController */ + + +#ifndef _Included_WinampController +#define _Included_WinampController +#ifdef __cplusplus +extern "C" { +#endif + +void initWinampHandle(); + +jboolean runWinamp(unsigned char* pathWinamp); + +int getListPos(); + +void getPluginMessage(int param, int sendMessage); + +/* + * Class: WinampController + * Method: run + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_run + (JNIEnv *, jclass); +/* + * Class: WinampController + * Method: exit + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_exit + (JNIEnv *, jclass); +/* + * Class: WinampController + * Method: play + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_play + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: stop + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_stop + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: resume + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_resume + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: pause + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_pause + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: previousTrack + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_previousTrack + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: nextTrack + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_nextTrack + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: fwd5Secs + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_fwd5Secs + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: fwd5Secs + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_rew5Secs + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: increaseVolume + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_increaseVolume + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: decreaseVolume + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_decreaseVolume + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: increaseVolumePercent + * Signature: (I)V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_increaseVolumePercent + (JNIEnv *, jclass, jint); + +/* + * Class: WinampController + * Method: decreaseVolumePercent + * Signature: (I)V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_decreaseVolumePercent + (JNIEnv *, jclass, jint); + +/* + * Class: WinampController + * Method: setVolume + * Signature: (I)V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_setVolume + (JNIEnv *, jclass, jint); + +/* + * Class: WinampController + * Method: setVolume + * Signature: (I)V + */ +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getVolume + (JNIEnv *, jclass, jint); + +/* + * Class: WinampController + * Method: restart + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_restart + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: setPlaylistPosition + * Signature: (I)V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_setPlaylistPosition + (JNIEnv *, jclass, jint); + +/* + * Class: WinampController + * Method: clearPlayList + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_clearPlayList + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: refreshPlayListCache + * Signature: ()V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_refreshPlayListCache + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: getPlayListLength + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getPlayListLength + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: writePlayListToFile + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_writePlayListToFile + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: isShuffleStatusOn + * Signature: ()Z + */ +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_isShuffleStatusOn + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: isRepeatStatusOn + * Signature: ()Z + */ +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_isRepeatStatusOn + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: setRepeatStatusOn + * Signature: (Z)V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_setRepeatStatusOn + (JNIEnv *, jclass, jboolean); + +/* + * Class: WinampController + * Method: setShuffleStatusOn + * Signature: (Z)V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_setShuffleStatusOn + (JNIEnv *, jclass, jboolean); + +/* + * Class: WinampController + * Method: appendToPlayList + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT jboolean JNICALL Java_com_qotsa_jni_controller_JNIWinamp_appendToPlayList + (JNIEnv *, jclass, jstring); + +/* + * Class: WinampController + * Method: getStatus + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getStatus + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: getListPos + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getListPos + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: getTitle + * Signature: ()I + */ +JNIEXPORT jstring JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getTitle + (JNIEnv *, jclass); + +/* + * Class: WinampController + * Method: getTime + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getTime + (JNIEnv *, jclass, jint); + +/* + * Class: WinampController + * Method: getFileNameInList + * Signature: ()I + */ +JNIEXPORT jstring JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getFileNameInList + (JNIEnv *, jclass, jint); + +/* + * Class: WinampController + * Method: getFileNamePlaying + * Signature: ()I + */ +JNIEXPORT jstring JNICALL Java_com_qotsa_jni_controller_JNIWinamp_getFileNamePlaying + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/vendor/JavaWinampApi/1.1/cpp/cpy.bat b/vendor/JavaWinampApi/1.1/cpp/cpy.bat new file mode 100644 index 0000000..2abdf4a --- /dev/null +++ b/vendor/JavaWinampApi/1.1/cpp/cpy.bat @@ -0,0 +1 @@ +copy /y wpcom.dll c:\winnt\system32\ \ No newline at end of file diff --git a/vendor/JavaWinampApi/1.1/cpp/libwpcom.def b/vendor/JavaWinampApi/1.1/cpp/libwpcom.def new file mode 100644 index 0000000..e17c91c --- /dev/null +++ b/vendor/JavaWinampApi/1.1/cpp/libwpcom.def @@ -0,0 +1,58 @@ +; dlltool --base-file C:\DOCUME~1\FRANCI~1\CONFIG~1\Temp/cca03628.base --output-exp wpcom.exp --dllname wpcom.dll --output-def libwpcom.def --no-export-all-symbols --add-stdcall-alias --exclude-symbol=DllMainCRTStartup@12 --def C:\DOCUME~1\FRANCI~1\CONFIG~1\Temp/cca03628.def --output-lib libwpcom.a +EXPORTS + Java_controller_JNIWinampController_appendToPlayList = Java_controller_JNIWinampController_appendToPlayList@12 @ 1 + Java_controller_JNIWinampController_appendToPlayList@12 @ 2 + Java_controller_JNIWinampController_clearPlayList = Java_controller_JNIWinampController_clearPlayList@8 @ 3 + Java_controller_JNIWinampController_clearPlayList@8 @ 4 + Java_controller_JNIWinampController_clearPlayListCache = Java_controller_JNIWinampController_clearPlayListCache@8 @ 5 + Java_controller_JNIWinampController_clearPlayListCache@8 @ 6 + Java_controller_JNIWinampController_decreaseVolume = Java_controller_JNIWinampController_decreaseVolume@8 @ 7 + Java_controller_JNIWinampController_decreaseVolume@8 @ 8 + Java_controller_JNIWinampController_decreaseVolumePercent = Java_controller_JNIWinampController_decreaseVolumePercent@12 @ 9 + Java_controller_JNIWinampController_decreaseVolumePercent@12 @ 10 + Java_controller_JNIWinampController_exit = Java_controller_JNIWinampController_exit@8 @ 11 + Java_controller_JNIWinampController_exit@8 @ 12 + Java_controller_JNIWinampController_getListPos = Java_controller_JNIWinampController_getListPos@8 @ 13 + Java_controller_JNIWinampController_getListPos@8 @ 14 + Java_controller_JNIWinampController_getPlayListLength = Java_controller_JNIWinampController_getPlayListLength@8 @ 15 + Java_controller_JNIWinampController_getPlayListLength@8 @ 16 + Java_controller_JNIWinampController_getSeconds = Java_controller_JNIWinampController_getSeconds@8 @ 17 + Java_controller_JNIWinampController_getSeconds@8 @ 18 + Java_controller_JNIWinampController_getStatus = Java_controller_JNIWinampController_getStatus@8 @ 19 + Java_controller_JNIWinampController_getStatus@8 @ 20 + Java_controller_JNIWinampController_getTitle = Java_controller_JNIWinampController_getTitle@8 @ 21 + Java_controller_JNIWinampController_getTitle@8 @ 22 + Java_controller_JNIWinampController_increaseVolume = Java_controller_JNIWinampController_increaseVolume@8 @ 23 + Java_controller_JNIWinampController_increaseVolume@8 @ 24 + Java_controller_JNIWinampController_increaseVolumePercent = Java_controller_JNIWinampController_increaseVolumePercent@12 @ 25 + Java_controller_JNIWinampController_increaseVolumePercent@12 @ 26 + Java_controller_JNIWinampController_isRepeatStatusOn = Java_controller_JNIWinampController_isRepeatStatusOn@8 @ 27 + Java_controller_JNIWinampController_isRepeatStatusOn@8 @ 28 + Java_controller_JNIWinampController_isShuffleStatusOn = Java_controller_JNIWinampController_isShuffleStatusOn@8 @ 29 + Java_controller_JNIWinampController_isShuffleStatusOn@8 @ 30 + Java_controller_JNIWinampController_nextTrack = Java_controller_JNIWinampController_nextTrack@8 @ 31 + Java_controller_JNIWinampController_nextTrack@8 @ 32 + Java_controller_JNIWinampController_pause = Java_controller_JNIWinampController_pause@8 @ 33 + Java_controller_JNIWinampController_pause@8 @ 34 + Java_controller_JNIWinampController_play = Java_controller_JNIWinampController_play@8 @ 35 + Java_controller_JNIWinampController_play@8 @ 36 + Java_controller_JNIWinampController_previousTrack = Java_controller_JNIWinampController_previousTrack@8 @ 37 + Java_controller_JNIWinampController_previousTrack@8 @ 38 + Java_controller_JNIWinampController_restart = Java_controller_JNIWinampController_restart@8 @ 39 + Java_controller_JNIWinampController_restart@8 @ 40 + Java_controller_JNIWinampController_resume = Java_controller_JNIWinampController_resume@8 @ 41 + Java_controller_JNIWinampController_resume@8 @ 42 + Java_controller_JNIWinampController_run = Java_controller_JNIWinampController_run@8 @ 43 + Java_controller_JNIWinampController_run@8 @ 44 + Java_controller_JNIWinampController_setPlaylistPosition = Java_controller_JNIWinampController_setPlaylistPosition@12 @ 45 + Java_controller_JNIWinampController_setPlaylistPosition@12 @ 46 + Java_controller_JNIWinampController_setRepeatStatusOn = Java_controller_JNIWinampController_setRepeatStatusOn@12 @ 47 + Java_controller_JNIWinampController_setRepeatStatusOn@12 @ 48 + Java_controller_JNIWinampController_setShuffleStatusOn = Java_controller_JNIWinampController_setShuffleStatusOn@12 @ 49 + Java_controller_JNIWinampController_setShuffleStatusOn@12 @ 50 + Java_controller_JNIWinampController_setVolume = Java_controller_JNIWinampController_setVolume@12 @ 51 + Java_controller_JNIWinampController_setVolume@12 @ 52 + Java_controller_JNIWinampController_stop = Java_controller_JNIWinampController_stop@8 @ 53 + Java_controller_JNIWinampController_stop@8 @ 54 + Java_controller_JNIWinampController_writePlayListToFile = Java_controller_JNIWinampController_writePlayListToFile@8 @ 55 + Java_controller_JNIWinampController_writePlayListToFile@8 @ 56 diff --git a/vendor/JavaWinampApi/1.1/cpp/wa_ipc.h b/vendor/JavaWinampApi/1.1/cpp/wa_ipc.h new file mode 100644 index 0000000..8bc8402 --- /dev/null +++ b/vendor/JavaWinampApi/1.1/cpp/wa_ipc.h @@ -0,0 +1,1620 @@ +/* +** Copyright (C) 2006 Nullsoft, 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. +** +*/ + +#ifndef _WA_IPC_H_ +#define _WA_IPC_H_ + +#include +#include +#if (_MSC_VER <= 1200) +typedef int intptr_t; +#endif +/* +** This is the modern replacement for the classic 'frontend.h'. Most of these +** updates are designed for in-process use, i.e. from a plugin. +** +*/ + +/* message used to sent many messages to winamp's main window. +** most all of the IPC_* messages involve sending the message in the form of: +** result = SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*); +** +** When you use SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*) and specify a IPC_* +** which is not currently implemented/supported by the Winamp version being used then it +** will return 1 for 'result'. This is a good way of helping to check if an api being +** used which returns a function pointer, etc is even going to be valid. +*/ +#define WM_WA_IPC WM_USER +/* but some of them use WM_COPYDATA. be afraid. +*/ + +#define WINAMP_VERSION_MAJOR(winampVersion) ((winampVersion & 0x0000FF00) >> 12) +#define WINAMP_VERSION_MINOR(winampVersion) (winampVersion & 0x000000FF) // returns, i.e. 0x12 for 5.12 and 0x10 for 5.1... + +#define IPC_GETVERSION 0 +/* int version = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION); +** +** The version returned will be 0x20yx for Winamp 2.yx. +** Versions previous to Winamp 2.0 typically (but not always) use 0x1zyx for 1.zx. +** Just a bit weird but that's the way it goes. +** +** For Winamp 5.x it uses the format 0x50yx for Winamp 5.yx +** e.g. 5.01 -> 0x5001 +** 5.09 -> 0x5009 +** 5.1 -> 0x5010 +** +** Notes: For 5.02 this api will return the same value as for a 5.01 build. +** For 5.07 this api will return the same value as for a 5.06 build. +*/ +#define IPC_GETVERSIONSTRING 1 + +#define IPC_GETREGISTEREDVERSION 770 + + +typedef struct { + const char *filename; + const char *title; + int length; +} enqueueFileWithMetaStruct; // send this to a IPC_PLAYFILE in a non WM_COPYDATA, +// and you get the nice desired result. if title is NULL, it is treated as a "thing", +// otherwise it's assumed to be a file (for speed) + +typedef struct { + const wchar_t *filename; + const wchar_t *title; + int length; +} enqueueFileWithMetaStructW; + +#define IPC_PLAYFILE 100 // dont be fooled, this is really the same as enqueufile +#define IPC_ENQUEUEFILE 100 +#define IPC_PLAYFILEW 1100 +/* This is sent as a WM_COPYDATA with IPC_PLAYFILE as the dwData member and the string +** of the file / playlist to be enqueued into the playlist editor as the lpData member. +** This will just enqueue the file or files since you can use this to enqueue a playlist. +** It will not clear the current playlist or change the playback state. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_ENQUEUEFILE; +** cds.lpData = (void*)"c:\\test\\folder\\test.mp3"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** +** With 2.9+ and all of the 5.x versions you can send this as a normal WM_WA_IPC +** (non WM_COPYDATA) with an enqueueFileWithMetaStruct as the param. +** If the title member is null then it is treated as a "thing" otherwise it will be +** assumed to be a file (for speed). +** +** enqueueFileWithMetaStruct eFWMS = {0}; +** eFWMS.filename = "c:\\test\\folder\\test.mp3"; +** eFWMS.title = "Whipping Good"; +** eFWMS.length = 300; // this is the number of seconds for the track +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&eFWMS,IPC_ENQUEUEFILE); +*/ + + +#define IPC_DELETE 101 +#define IPC_DELETE_INT 1101 +/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_DELETE); +** Use this api to clear Winamp's internal playlist. +** You should not need to use IPC_DELETE_INT since it is used internally by Winamp when +** it is dealing with some lame Windows Explorer issues (hard to believe that!). +*/ + + +#define IPC_STARTPLAY 102 +#define IPC_STARTPLAY_INT 1102 +/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_STARTPLAY); +** Sending this will start playback and is almost the same as hitting the play button. +** The IPC_STARTPLAY_INT version is used internally and you should not need to use it +** since it won't be any fun. +*/ + +#define IPC_CHDIR 103 +/* This is sent as a WM_COPYDATA type message with IPC_CHDIR as the dwData value and the +** directory you want to change to as the lpData member. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_CHDIR; +** cds.lpData = (void*)"c:\\download"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** The above example will make Winamp change to the directory 'C:\download'. +*/ + + +#define IPC_ISPLAYING 104 +/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING); +** This is sent to retrieve the current playback state of Winamp. +** If it returns 1, Winamp is playing. +** If it returns 3, Winamp is paused. +** If it returns 0, Winamp is not playing. +*/ + + +#define IPC_GETOUTPUTTIME 105 +/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETOUTPUTTIME); +** This api can return two different sets of information about current playback status. +** +** If mode = 0 then it will return the position (in ms) of the currently playing track. +** Will return -1 if Winamp is not playing. +** +** If mode = 1 then it will return the current track length (in seconds). +** Will return -1 if there are no tracks (or possibly if Winamp cannot get the length). +*/ + + + +#define IPC_JUMPTOTIME 106 +/* (requires Winamp 1.60+) +** SendMessage(hwnd_winamp,WM_WA_IPC,ms,IPC_JUMPTOTIME); +** This api sets the current position (in milliseconds) for the currently playing song. +** The resulting playback position may only be an approximate time since some playback +** formats do not provide exact seeking e.g. mp3 +** This returns -1 if Winamp is not playing, 1 on end of file, or 0 if it was successful. +*/ + +#define IPC_GETMODULENAME 109 +#define IPC_EX_ISRIGHTEXE 666 +/* usually shouldnt bother using these, but here goes: +** send a WM_COPYDATA with IPC_GETMODULENAME, and an internal +** flag gets set, which if you send a normal WM_WA_IPC message with +** IPC_EX_ISRIGHTEXE, it returns whether or not that filename +** matches. lame, I know. +*/ + +#define IPC_WRITEPLAYLIST 120 +/* (requires Winamp 1.666+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_WRITEPLAYLIST); +** +** IPC_WRITEPLAYLIST will write the current playlist to '\\Winamp.m3u' and +** will also return the current playlist position (see IPC_GETLISTPOS). +** +** This is kinda obsoleted by some of the newer 2.x api items but it still is good for +** use with a front-end program (instead of a plug-in) and you want to see what is in the +** current playlist. +** +** This api will only save out extended file information in the #EXTINF entry if Winamp +** has already read the data such as if the file was played of scrolled into view. If +** Winamp has not read the data then you will only find the file with its filepath entry +** (as is the base requirements for a m3u playlist). +*/ + + +#define IPC_SETPLAYLISTPOS 121 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,position,IPC_SETPLAYLISTPOS) +** IPC_SETPLAYLISTPOS sets the playlist position to the specified 'position'. +** It will not change playback status or anything else. It will just set the current +** position in the playlist and will update the playlist view if necessary. +** +** If you use SendMessage(hwnd_winamp,WM_COMMAND,MAKEWPARAM(WINAMP_BUTTON2,0),0); +** after using IPC_SETPLAYLISTPOS then Winamp will start playing the file at 'position'. +*/ + + +#define IPC_SETVOLUME 122 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,volume,IPC_SETVOLUME); +** IPC_SETVOLUME sets the volume of Winamp (between the range of 0 to 255). +** +** If you pass 'volume' as -666 then the message will return the current volume. +** int curvol = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETVOLUME); +*/ + + +#define IPC_SETPANNING 123 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,panning,IPC_SETPANNING); +** IPC_SETPANNING sets the panning of Winamp from 0 (left) to 255 (right). +** +** At least in 5.x+ this works from -127 (left) to 127 (right). +** +** If you pass 'panning' as -666 to this api then it will return the current panning. +** int curpan = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETPANNING); +*/ + + +#define IPC_GETLISTLENGTH 124 +/* (requires Winamp 2.0+) +** int length = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTLENGTH); +** IPC_GETLISTLENGTH returns the length of the current playlist as the number of tracks. +*/ + + +#define IPC_GETLISTPOS 125 +/* (requires Winamp 2.05+) +** int pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS); +** IPC_GETLISTPOS returns the current playlist position (which is shown in the playlist +** editor as a differently coloured text entry e.g is yellow for the classic skin). +** +** This api is a lot like IPC_WRITEPLAYLIST but a lot faster since it does not have to +** write out the whole of the current playlist first. +*/ + + +#define IPC_GETINFO 126 +/* (requires Winamp 2.05+) +** int inf=SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETINFO); +** IPC_GETINFO returns info about the current playing song. The value +** it returns depends on the value of 'mode'. +** Mode Meaning +** ------------------ +** 0 Samplerate, in kilohertz (i.e. 44) +** 1 Bitrate (i.e. 128) +** 2 Channels (i.e. 2) +** 3 (5+) Video LOWORD=w HIWORD=h +** 4 (5+) > 65536, string (video description) +** 5 (5.25+) Samplerate, in hertz (i.e. 44100) +*/ + + +#define IPC_GETEQDATA 127 +/* (requires Winamp 2.05+) +** int data=SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA); +** IPC_GETEQDATA queries the status of the EQ. +** The value returned depends on what 'pos' is set to: +** Value Meaning +** ------------------ +** 0-9 The 10 bands of EQ data. 0-63 (+20db - -20db) +** 10 The preamp value. 0-63 (+20db - -20db) +** 11 Enabled. zero if disabled, nonzero if enabled. +** 12 Autoload. zero if disabled, nonzero if enabled. +*/ + + +#define IPC_SETEQDATA 128 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA); +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SETEQDATA); +** IPC_SETEQDATA sets the value of the last position retrieved +** by IPC_GETEQDATA. This is pretty lame, and we should provide +** an extended version that lets you do a MAKELPARAM(pos,value). +** someday... + + new (2.92+): + if the high byte is set to 0xDB, then the third byte specifies + which band, and the bottom word specifies the value. +*/ + +#define IPC_ADDBOOKMARK 129 +#define IPC_ADDBOOKMARKW 131 +/* (requires Winamp 2.4+) +** This is sent as a WM_COPYDATA using IPC_ADDBOOKMARK as the dwData value and the +** directory you want to change to as the lpData member. This will add the specified +** file / url to the Winamp bookmark list. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_ADDBOOKMARK; +** cds.lpData = (void*)"http://www.blah.com/listen.pls"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** +** In Winamp 5.0+ we use this as a normal WM_WA_IPC and the string is null separated as +** the filename and then the title of the entry. +** +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)"filename\0title\0",IPC_ADDBOOKMARK); +** +** This will notify the library / bookmark editor that a bookmark was added. +** Note that using this message in this context does not actually add the bookmark. +** Do not use, it is essentially just a notification type message :) +*/ + + +#define IPC_INSTALLPLUGIN 130 +/* This is not implemented (and is very unlikely to be done due to safety concerns). +** If it was then you could do a WM_COPYDATA with a path to a .wpz and it would then +** install the plugin for you. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_INSTALLPLUGIN; +** cds.lpData = (void*)"c:\\path\\to\\file.wpz"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +*/ + + +#define IPC_RESTARTWINAMP 135 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_RESTARTWINAMP); +** IPC_RESTARTWINAMP will restart Winamp (isn't that obvious ? :) ) +** If this fails to make Winamp start after closing then there is a good chance one (or +** more) of the currently installed plugins caused Winamp to crash on exit (either as a +** silent crash or a full crash log report before it could call itself start again. +*/ + + +#define IPC_ISFULLSTOP 400 +/* (requires winamp 2.7+ I think) +** int ret=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISFULLSTOP); +** This is useful for when you're an output plugin and you want to see if the stop/close +** happening is a full stop or if you are just between tracks. This returns non zero if +** it is a full stop or zero if it is just a new track. +*/ + + +#define IPC_INETAVAILABLE 242 +/* (requires Winamp 2.05+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INETAVAILABLE); +** IPC_INETAVAILABLE will return 1 if an Internet connection is available for Winamp and +** relates to the internet connection type setting on the main general preferences page +** in the Winamp preferences. +*/ + + +#define IPC_UPDTITLE 243 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_UPDTITLE); +** IPC_UPDTITLE will ask Winamp to update the information about the current title and +** causes GetFileInfo(..) in the input plugin associated with the current playlist entry +** to be called. This can be called such as when an input plugin is buffering a file so +** that it can cause the buffer percentage to appear in the playlist. +*/ + + +#define IPC_REFRESHPLCACHE 247 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REFRESHPLCACHE); +** IPC_REFRESHPLCACHE will flush the playlist cache buffer and you send this if you want +** Winamp to go refetch the titles for all of the entries in the current playlist. + +5.3+: pass a wchar_t * string in wParam, and it'll do a strnicmp() before clearing the cache +*/ + + +#define IPC_GET_SHUFFLE 250 +/* (requires Winamp 2.4+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_SHUFFLE); +** IPC_GET_SHUFFLE returns the status of the shuffle option. +** If set then it will return 1 and if not set then it will return 0. +*/ + + +#define IPC_GET_REPEAT 251 +/* (requires Winamp 2.4+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_REPEAT); +** IPC_GET_REPEAT returns the status of the repeat option. +** If set then it will return 1 and if not set then it will return 0. +*/ + + +#define IPC_SET_SHUFFLE 252 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_SHUFFLE); +** IPC_SET_SHUFFLE sets the status of the shuffle option. +** If 'value' is 1 then shuffle is turned on. +** If 'value' is 0 then shuffle is turned off. +*/ + + +#define IPC_SET_REPEAT 253 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_REPEAT); +** IPC_SET_REPEAT sets the status of the repeat option. +** If 'value' is 1 then shuffle is turned on. +** If 'value' is 0 then shuffle is turned off. +*/ + + +#define IPC_ENABLEDISABLE_ALL_WINDOWS 259 // 0xdeadbeef to disable +/* (requires Winamp 2.9+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(enable?0:0xdeadbeef),IPC_ENABLEDISABLE_ALL_WINDOWS); +** Sending this message with 0xdeadbeef as the param will disable all winamp windows and +** any other values will enable all of the Winamp windows again. When disabled you won't +** get any response on clicking or trying to do anything to the Winamp windows. If the +** taskbar icon is shown then you may still have control ;) +*/ + + +#define IPC_GETWND 260 +/* (requires Winamp 2.9+) +** HWND h=SendMessage(hwnd_winamp,WM_WA_IPC,IPC_GETWND_xxx,IPC_GETWND); +** returns the HWND of the window specified. +*/ + #define IPC_GETWND_EQ 0 // use one of these for the param + #define IPC_GETWND_PE 1 + #define IPC_GETWND_MB 2 + #define IPC_GETWND_VIDEO 3 +#define IPC_ISWNDVISIBLE 261 // same param as IPC_GETWND + + + + +/************************************************************************ +***************** in-process only (WE LOVE PLUGINS) +************************************************************************/ + +#define IPC_SETSKINW 199 +#define IPC_SETSKIN 200 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)"skinname",IPC_SETSKIN); +** IPC_SETSKIN sets the current skin to "skinname". Note that skinname +** can be the name of a skin, a skin .zip file, with or without path. +** If path isn't specified, the default search path is the winamp skins +** directory. +*/ + + +#define IPC_GETSKIN 201 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)skinname_buffer,IPC_GETSKIN); +** IPC_GETSKIN puts the directory where skin bitmaps can be found +** into skinname_buffer. +** skinname_buffer must be MAX_PATH characters in length. +** When using a .zip'd skin file, it'll return a temporary directory +** where the ZIP was decompressed. +*/ + + +#define IPC_EXECPLUG 202 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)"vis_file.dll",IPC_EXECPLUG); +** IPC_EXECPLUG executes a visualization plug-in pointed to by WPARAM. +** the format of this string can be: +** "vis_whatever.dll" +** "vis_whatever.dll,0" // (first mod, file in winamp plug-in dir) +** "C:\\dir\\vis_whatever.dll,1" +*/ + + +#define IPC_GETPLAYLISTFILE 211 +#define IPC_GETPLAYLISTFILEW 214 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE); +** IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index]. +** returns a pointer to it. returns NULL on error. +*/ + + +#define IPC_GETPLAYLISTTITLE 212 +#define IPC_GETPLAYLISTTITLEW 213 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE); +** +** IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index]. +** returns a pointer to it. returns NULL on error. +*/ + + +#define IPC_GETHTTPGETTER 240 +/* retrieves a function pointer to a HTTP retrieval function. +** if this is unsupported, returns 1 or 0. +** the function should be: +** int (*httpRetrieveFile)(HWND hwnd, char *url, char *file, char *dlgtitle); +** if you call this function, with a parent window, a URL, an output file, and a dialog title, +** it will return 0 on successful download, 1 on error. +*/ + + +#define IPC_MBOPEN 241 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_MBOPEN); +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPEN); +** IPC_MBOPEN will open a new URL in the minibrowser. if url is NULL, it will open the Minibrowser window. +*/ + + + +#define IPC_CHANGECURRENTFILE 245 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILE); +** IPC_CHANGECURRENTFILE will set the current playlist item. +*/ + +#define IPC_CHANGECURRENTFILEW 1245 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILEW); +** IPC_CHANGECURRENTFILEW will set the current playlist item. +*/ + + +#define IPC_GETMBURL 246 +/* (requires Winamp 2.2+) +** char buffer[4096]; // Urls can be VERY long +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)buffer,IPC_GETMBURL); +** IPC_GETMBURL will retrieve the current Minibrowser URL into buffer. +** buffer must be at least 4096 bytes long. +*/ + + +#define IPC_MBBLOCK 248 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_MBBLOCK); +** +** IPC_MBBLOCK will block the Minibrowser from updates if value is set to 1 +*/ + +#define IPC_MBOPENREAL 249 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPENREAL); +** +** IPC_MBOPENREAL works the same as IPC_MBOPEN except that it will works even if +** IPC_MBBLOCK has been set to 1 +*/ + +#define IPC_ADJUST_OPTIONSMENUPOS 280 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_OPTIONSMENUPOS); +** moves where winamp expects the Options menu in the main menu. Useful if you wish to insert a +** menu item above the options/skins/vis menus. +*/ + +#define IPC_GET_HMENU 281 +/* (requires Winamp 2.9+) +** HMENU hMenu=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)0,IPC_GET_HMENU); +** values for data: +** 0 : main popup menu +** 1 : main menubar file menu +** 2 : main menubar options menu +** 3 : main menubar windows menu +** 4 : main menubar help menu +** other values will return NULL. +*/ + +#define IPC_GET_EXTENDED_FILE_INFO 290 //pass a pointer to the following struct in wParam +#define IPC_GET_EXTENDED_FILE_INFO_HOOKABLE 296 +/* (requires Winamp 2.9+) +** to use, create an extendedFileInfoStruct, point the values filename and metadata to the +** filename and metadata field you wish to query, and ret to a buffer, with retlen to the +** length of that buffer, and then SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_GET_EXTENDED_FILE_INFO); +** the results should be in the buffer pointed to by ret. +** returns 1 if the decoder supports a getExtendedFileInfo method +*/ +typedef struct { + const char *filename; + const char *metadata; + char *ret; + size_t retlen; +} extendedFileInfoStruct; + + +#define IPC_GET_BASIC_FILE_INFO 291 //pass a pointer to the following struct in wParam +typedef struct { + const char *filename; + + int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used) + + // filled in by winamp + int length; + char *title; + int titlelen; +} basicFileInfoStruct; + +#define IPC_GET_BASIC_FILE_INFOW 1291 //pass a pointer to the following struct in wParam +typedef struct { + const wchar_t *filename; + + int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used) + + // filled in by winamp + int length; + wchar_t *title; + int titlelen; +} basicFileInfoStructW; + + +#define IPC_GET_EXTLIST 292 //returns doublenull delimited. GlobalFree() it when done. if data is 0, returns raw extlist, if 1, returns something suitable for getopenfilename +#define IPC_GET_EXTLISTW 1292 // wide char version of above + +#define IPC_INFOBOX 293 +typedef struct { + HWND parent; + char *filename; +} infoBoxParam; + +#define IPC_INFOBOXW 1293 +typedef struct { + HWND parent; + const wchar_t *filename; +} infoBoxParamW; + +#define IPC_SET_EXTENDED_FILE_INFO 294 //pass a pointer to the a extendedFileInfoStruct in wParam +/* (requires Winamp 2.9+) +** to use, create an extendedFileInfoStruct, point the values filename and metadata to the +** filename and metadata field you wish to write in ret. (retlen is not used). and then +** SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_SET_EXTENDED_FILE_INFO); +** returns 1 if the metadata is supported +** Call IPC_WRITE_EXTENDED_FILE_INFO once you're done setting all the metadata you want to update +*/ + +#define IPC_WRITE_EXTENDED_FILE_INFO 295 +/* (requires Winamp 2.9+) +** writes all the metadata set thru IPC_SET_EXTENDED_FILE_INFO to the file +** returns 1 if the file has been successfully updated, 0 if error +*/ + +#define IPC_FORMAT_TITLE 297 +typedef struct +{ + char *spec; // NULL=default winamp spec + void *p; + + char *out; + int out_len; + + char * (*TAGFUNC)(const char * tag, void * p); //return 0 if not found + void (*TAGFREEFUNC)(char * tag,void * p); +} waFormatTitle; + +#define IPC_FORMAT_TITLE_EXTENDED 298 // similiar to IPC_FORMAT_TITLE, but falls back to Winamp's %tags% if your passed tag function doesn't handle it +typedef struct +{ + const wchar_t *filename; + int useExtendedInfo; // set to 1 if you want the Title Formatter to query the input plugins for any tags that your tag function fails on + const wchar_t *spec; // NULL=default winamp spec + void *p; + + wchar_t *out; + int out_len; + + wchar_t * (*TAGFUNC)(const wchar_t * tag, void * p); //return 0 if not found, -1 for empty tag + void (*TAGFREEFUNC)(wchar_t *tag, void *p); +} waFormatTitleExtended; + +#define IPC_COPY_EXTENDED_FILE_INFO 299 +typedef struct +{ + const char *source; + const char *dest; +} copyFileInfoStruct; + +#define IPC_COPY_EXTENDED_FILE_INFOW 1299 +typedef struct +{ + const wchar_t *source; + const wchar_t *dest; +} copyFileInfoStructW; + + +#define IPC_GETUNCOMPRESSINTERFACE 331 +/* returns a function pointer to uncompress(). +** int (*uncompress)(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen); +** right out of zlib, useful for decompressing zlibbed data. +** if you pass the parm of 0x10100000, it will return a wa_inflate_struct * to an inflate API. +*/ + +typedef struct { + int (*inflateReset)(void *strm); + int (*inflateInit_)(void *strm,const char *version, int stream_size); + int (*inflate)(void *strm, int flush); + int (*inflateEnd)(void *strm); + unsigned long (*crc32)(unsigned long crc, const unsigned char *buf, unsigned int len); +} wa_inflate_struct; + + +#define IPC_ADD_PREFS_DLG 332 +#define IPC_REMOVE_PREFS_DLG 333 +/* (requires Winamp 2.9+) +** to use, allocate a prefsDlgRec structure (either on the heap or some global +** data, but NOT on the stack), initialze the members: +** hInst to the DLL instance where the resource is located +** dlgID to the ID of the dialog, +** proc to the window procedure for the dialog +** name to the name of the prefs page in the prefs. +** where to 0 (eventually we may add more options) +** then, SendMessage(hwnd_winamp,WM_WA_IPC,&prefsRec,IPC_ADD_PREFS_DLG); +** +** you can also IPC_REMOVE_PREFS_DLG with the address of the same prefsRec, +** but you shouldn't really ever have to. +** +*/ +#define IPC_OPENPREFSTOPAGE 380 // pass an id of a builtin page, or a &prefsDlgRec of prefs page to open + +typedef struct _prefsDlgRec { + HINSTANCE hInst; + int dlgID; + void *proc; + + char *name; + intptr_t where; // 0 for options, 1 for plugins, 2 for skins, 3 for bookmarks, 4 for prefs + + intptr_t _id; + struct _prefsDlgRec *next; +} prefsDlgRec; + + +#define IPC_GETINIFILE 334 // returns a pointer to winamp.ini +#define IPC_GETINIDIRECTORY 335 // returns a pointer to the directory to put config files in (if you dont want to use winamp.ini) +#define IPC_GETPLUGINDIRECTORY 336 +#define IPC_GETM3UDIRECTORY 337 // returns a char pointer to the directory where winamp.m3u is stored in. +#define IPC_GETM3UDIRECTORYW 338 // returns a wchar_t pointer to the directory where winamp.m3u is stored in. + +#define IPC_SPAWNBUTTONPOPUP 361 // param = +// 0 = eject +// 1 = previous +// 2 = next +// 3 = pause +// 4 = play +// 5 = stop + +#define IPC_OPENURLBOX 360 // pass a HWND to a parent, returns a HGLOBAL that needs to be freed with GlobalFree(), if successful +#define IPC_OPENFILEBOX 362 // pass a HWND to a parent +#define IPC_OPENDIRBOX 363 // pass a HWND to a parent + +// pass an HWND to a parent. call this if you take over the whole UI so that the dialogs are not appearing on the +// bottom right of the screen since the main winamp window is at 3000x3000, call again with NULL to reset +#define IPC_SETDIALOGBOXPARENT 364 + + + +#define IPC_DRO_MIN 401 // reserved for DrO +#define IPC_SET_JTF_COMPARATOR 409 +/* pass me an int (__cdecl *)(const char *, const char *) in wParam */ +#define IPC_SET_JTF_COMPARATOR_W 410 +/* pass me an int (__cdecl *)(const wchar_t *, const wchar_t *) in wParam ... maybe someday :) */ +#define IPC_SET_JTF_DRAWTEXT 416 + +#define IPC_DRO_MAX 499 + + +// pass 0 for a copy of the skin HBITMAP +// pass 1 for name of font to use for playlist editor likeness +// pass 2 for font charset +// pass 3 for font size +#define IPC_GET_GENSKINBITMAP 503 + + +#define IPC_GET_EMBEDIF 505 // pass an embedWindowState +// returns an HWND embedWindow(embedWindowState *); if the data is NULL, otherwise returns the HWND directly +typedef struct +{ + HWND me; //hwnd of the window + + int flags; + + RECT r; + + void *user_ptr; // for application use + + intptr_t extra_data[64]; // for internal winamp use +} embedWindowState; + +#define EMBED_FLAGS_NORESIZE 0x1 // set this bit in embedWindowState.flags to keep window from being resizable +#define EMBED_FLAGS_NOTRANSPARENCY 0x2 // set this bit in embedWindowState.flags to make gen_ff turn transparency off for this wnd +#define EMBED_FLAGS_NOWINDOWMENU 0x4 // set this bit to prevent gen_ff from automatically adding your window to the right-click menu +#define EMBED_FLAGS_GUID 0x8 // call SET_EMBED_GUID(yourEmbedWindowStateStruct, GUID) to define a GUID for this window + +#define SET_EMBED_GUID(windowState, windowGUID) { windowState->flags |= EMBED_FLAGS_GUID; *((GUID *)&windowState->extra_data[4])=windowGUID; } +#define GET_EMBED_GUID(windowState) (*((GUID *)&windowState->extra_data[4])) + +#define IPC_EMBED_ENUM 532 +typedef struct embedEnumStruct +{ + int (*enumProc)(embedWindowState *ws, struct embedEnumStruct *param); // return 1 to abort + int user_data; // or more :) +} embedEnumStruct; + // pass + +#define IPC_EMBED_ISVALID 533 + +#define IPC_CONVERTFILE 506 +/* (requires Winamp 2.92+) +** Converts a given file to a different format (PCM, MP3, etc...) +** To use, pass a pointer to a waFileConvertStruct struct +** This struct can be either on the heap or some global +** data, but NOT on the stack. At least, until the conversion is done. +** +** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE); +** +** Return value: +** 0: Can't start the conversion. Look at myConvertStruct->error for details. +** 1: Conversion started. Status messages will be sent to the specified callbackhwnd. +** Be sure to call IPC_CONVERTFILE_END when your callback window receives the +** IPC_CB_CONVERT_DONE message. +*/ +typedef struct +{ + char *sourcefile; // "c:\\source.mp3" + char *destfile; // "c:\\dest.pcm" + int destformat[8]; // like 'PCM ',srate,nch,bps. + //hack alert! you can set destformat[6]=mmioFOURCC('I','N','I',' '); and destformat[7]=(int)my_ini_file; (where my_ini_file is a char*) + HWND callbackhwnd; // window that will receive the IPC_CB_CONVERT notification messages + + //filled in by winamp.exe + char *error; //if IPC_CONVERTFILE returns 0, the reason will be here + + int bytes_done; //you can look at both of these values for speed statistics + int bytes_total; + int bytes_out; + + int killswitch; // don't set it manually, use IPC_CONVERTFILE_END + intptr_t extra_data[64]; // for internal winamp use +} convertFileStruct; + +#define IPC_CONVERTFILE_END 507 +/* (requires Winamp 2.92+) +** Stop/ends a convert process started from IPC_CONVERTFILE +** You need to call this when you receive the IPC_CB_CONVERTDONE message or when you +** want to abort a conversion process +** +** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE_END); +** +** No return value +*/ + +typedef struct { + HWND hwndParent; + int format; + + //filled in by winamp.exe + HWND hwndConfig; + int extra_data[8]; + //hack alert! you can set extra_data[6]=mmioFOURCC('I','N','I',' '); and extra_data[7]=(int)my_ini_file; (where my_ini_file is a char*) +} convertConfigStruct; +#define IPC_CONVERT_CONFIG 508 +#define IPC_CONVERT_CONFIG_END 509 + +typedef struct +{ + void (*enumProc)(intptr_t user_data, const char *desc, int fourcc); + intptr_t user_data; +} converterEnumFmtStruct; +#define IPC_CONVERT_CONFIG_ENUMFMTS 510 +/* (requires Winamp 2.92+) +*/ + +typedef struct +{ + char cdletter; + char *playlist_file; + HWND callback_hwnd; + + //filled in by winamp.exe + char *error; +} burnCDStruct; +#define IPC_BURN_CD 511 +/* (requires Winamp 5.0+) +*/ + +typedef struct +{ + convertFileStruct *cfs; + int priority; +} convertSetPriority; +#define IPC_CONVERT_SET_PRIORITY 512 + +typedef struct +{ + unsigned int format; //fourcc value + char *item; // config item, eg "bitrate" + char *data; // buffer to recieve, or buffer that contains the data + int len; // length of the data buffer (only used when getting a config item) + char *configfile; // config file to read from +} convertConfigItem; + +#define IPC_CONVERT_CONFIG_SET_ITEM 513 // returns TRUE if successful +#define IPC_CONVERT_CONFIG_GET_ITEM 514 // returns TRUE if successful + +typedef struct +{ + const char *filename; + char *title; // 2048 bytes + int length; + int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit +} waHookTitleStruct; +// return TRUE if you hook this +#define IPC_HOOK_TITLES 850 + +typedef struct +{ + const wchar_t *filename; + wchar_t *title; // 2048 bytes + int length; + int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit +} waHookTitleStructW; +// return TRUE if you hook this +#define IPC_HOOK_TITLESW 851 + +#define IPC_GETSADATAFUNC 800 +// 0: returns a char *export_sa_get() that returns 150 bytes of data +// 1: returns a export_sa_setreq(int want); + +#define IPC_GETVUDATAFUNC 801 +// 0: returns a int export_vu_get(int channel) that returns 0-255 (or -1 for bad channel) + +#define IPC_ISMAINWNDVISIBLE 900 + + +#define IPC_SETPLEDITCOLORS 920 +typedef struct +{ + int numElems; + int *elems; + HBITMAP bm; // set if you want to override +} waSetPlColorsStruct; + + +// the following IPC use waSpawnMenuParms as parameter +#define IPC_SPAWNEQPRESETMENU 933 +#define IPC_SPAWNFILEMENU 934 //menubar +#define IPC_SPAWNOPTIONSMENU 935 //menubar +#define IPC_SPAWNWINDOWSMENU 936 //menubar +#define IPC_SPAWNHELPMENU 937 //menubar +#define IPC_SPAWNPLAYMENU 938 //menubar +#define IPC_SPAWNPEFILEMENU 939 //menubar +#define IPC_SPAWNPEPLAYLISTMENU 940 //menubar +#define IPC_SPAWNPESORTMENU 941 //menubar +#define IPC_SPAWNPEHELPMENU 942 //menubar +#define IPC_SPAWNMLFILEMENU 943 //menubar +#define IPC_SPAWNMLVIEWMENU 944 //menubar +#define IPC_SPAWNMLHELPMENU 945 //menubar +#define IPC_SPAWNPELISTOFPLAYLISTS 946 + +typedef struct +{ + HWND wnd; + int xpos; // in screen coordinates + int ypos; +} waSpawnMenuParms; + +// waSpawnMenuParms2 is used by the menubar submenus +typedef struct +{ + HWND wnd; + int xpos; // in screen coordinates + int ypos; + int width; + int height; +} waSpawnMenuParms2; + + +// system tray sends this (you might want to simulate it) +#define WM_WA_SYSTRAY WM_USER+1 + +// input plugins send this when they are done playing back +#define WM_WA_MPEG_EOF WM_USER+2 + + + +//// video stuff + +#define IPC_IS_PLAYING_VIDEO 501 // returns >1 if playing, 0 if not, 1 if old version (so who knows):) +#define IPC_GET_IVIDEOOUTPUT 500 // see below for IVideoOutput interface +#define VIDEO_MAKETYPE(A,B,C,D) ((A) | ((B)<<8) | ((C)<<16) | ((D)<<24)) +#define VIDUSER_SET_INFOSTRING 0x1000 +#define VIDUSER_GET_VIDEOHWND 0x1001 +#define VIDUSER_SET_VFLIP 0x1002 +#define VIDUSER_SET_TRACKSELINTERFACE 0x1003 // give your ITrackSelector interface as param2 +#define VIDUSER_OPENVIDEORENDERER 0x1004 +#define VIDUSER_CLOSEVIDEORENDERER 0x1005 +#define VIDUSER_GETPOPUPMENU 0x1006 + +typedef struct +{ + int w; + int h; + int vflip; + double aspectratio; + unsigned int fmt; +} VideoOpenStruct; + +#ifndef NO_IVIDEO_DECLARE +#ifdef __cplusplus + +class VideoOutput; +class SubsItem; + +#ifndef _NSV_DEC_IF_H_ +typedef struct { + unsigned char* baseAddr; + long rowBytes; +} YV12_PLANE; + +typedef struct { + YV12_PLANE y; + YV12_PLANE u; + YV12_PLANE v; +} YV12_PLANES; +#endif + +class IVideoOutput +{ + public: + virtual ~IVideoOutput() { } + virtual int open(int w, int h, int vflip, double aspectratio, unsigned int fmt)=0; + virtual void setcallback(LRESULT (*msgcallback)(void *token, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam), void *token) { (void)token; (void)msgcallback; /* to eliminate warning C4100 */ } + virtual void close()=0; + virtual void draw(void *frame)=0; + virtual void drawSubtitle(SubsItem *item) { } + virtual void showStatusMsg(const char *text) { } + virtual int get_latency() { return 0; } + virtual void notifyBufferState(int bufferstate) { } /* 0-255*/ + + virtual INT_PTR extended(INT_PTR param1, INT_PTR param2, INT_PTR param3) { return 0; } // Dispatchable, eat this! +}; + +class ITrackSelector +{ + public: + virtual int getNumAudioTracks()=0; + virtual void enumAudioTrackName(int n, const char *buf, int size)=0; + virtual int getCurAudioTrack()=0; + virtual int getNumVideoTracks()=0; + virtual void enumVideoTrackName(int n, const char *buf, int size)=0; + virtual int getCurVideoTrack()=0; + + virtual void setAudioTrack(int n)=0; + virtual void setVideoTrack(int n)=0; +}; + +#endif //cplusplus +#endif//NO_IVIDEO_DECLARE + +// these messages are callbacks that you can grab by subclassing the winamp window + +// wParam = +#define IPC_CB_WND_EQ 0 // use one of these for the param +#define IPC_CB_WND_PE 1 +#define IPC_CB_WND_MB 2 +#define IPC_CB_WND_VIDEO 3 +#define IPC_CB_WND_MAIN 4 + +#define IPC_CB_ONSHOWWND 600 +#define IPC_CB_ONHIDEWND 601 + +#define IPC_CB_GETTOOLTIP 602 + +#define IPC_CB_MISC 603 + #define IPC_CB_MISC_TITLE 0 + #define IPC_CB_MISC_VOLUME 1 // volume/pan + #define IPC_CB_MISC_STATUS 2 + #define IPC_CB_MISC_EQ 3 + #define IPC_CB_MISC_INFO 4 + #define IPC_CB_MISC_VIDEOINFO 5 + +#define IPC_CB_CONVERT_STATUS 604 // param value goes from 0 to 100 (percent) +#define IPC_CB_CONVERT_DONE 605 + +#define IPC_ADJUST_FFWINDOWSMENUPOS 606 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFWINDOWSMENUPOS); +** moves where winamp expects the freeform windows in the menubar windows main menu. Useful if you wish to insert a +** menu item above extra freeform windows. +*/ + +#define IPC_ISDOUBLESIZE 608 + +#define IPC_ADJUST_FFOPTIONSMENUPOS 609 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFOPTIONSMENUPOS); +** moves where winamp expects the freeform preferences item in the menubar windows main menu. Useful if you wish to insert a +** menu item above preferences item. +*/ + +#define IPC_GETTIMEDISPLAYMODE 610 // returns 0 if displaying elapsed time or 1 if displaying remaining time + +#define IPC_SETVISWND 611 // param is hwnd, setting this allows you to receive ID_VIS_NEXT/PREVOUS/RANDOM/FS wm_commands +#define ID_VIS_NEXT 40382 +#define ID_VIS_PREV 40383 +#define ID_VIS_RANDOM 40384 +#define ID_VIS_FS 40389 +#define ID_VIS_CFG 40390 +#define ID_VIS_MENU 40391 + +#define IPC_GETVISWND 612 // returns the vis cmd handler hwnd +#define IPC_ISVISRUNNING 613 +#define IPC_CB_VISRANDOM 628 // param is status of random + +#define IPC_SETIDEALVIDEOSIZE 614 // sent by winamp to winamp, trap it if you need it. width=HIWORD(param), height=LOWORD(param) + +#define IPC_GETSTOPONVIDEOCLOSE 615 +#define IPC_SETSTOPONVIDEOCLOSE 616 + +typedef struct { + HWND hwnd; + int uMsg; + WPARAM wParam; + LPARAM lParam; +} transAccelStruct; + +#define IPC_TRANSLATEACCELERATOR 617 + +typedef struct { + int cmd; + int x; + int y; + int align; +} windowCommand; // send this as param to an IPC_PLCMD, IPC_MBCMD, IPC_VIDCMD + +#define IPC_CB_ONTOGGLEAOT 618 + +#define IPC_GETPREFSWND 619 + +#define IPC_SET_PE_WIDTHHEIGHT 620 // data is a pointer to a POINT structure that holds width & height + +#define IPC_GETLANGUAGEPACKINSTANCE 621 + +#define IPC_CB_PEINFOTEXT 622 // data is a string, ie: "04:21/45:02" + +#define IPC_CB_OUTPUTCHANGED 623 // output plugin was changed in config + +#define IPC_GETOUTPUTPLUGIN 625 + +#define IPC_SETDRAWBORDERS 626 +#define IPC_DISABLESKINCURSORS 627 +#define IPC_CB_RESETFONT 629 + +#define IPC_IS_FULLSCREEN 630 // returns 1 if video or vis is in fullscreen mode +#define IPC_SET_VIS_FS_FLAG 631 // a vis should send this message with 1/as param to notify winamp that it has gone to or has come back from fullscreen mode + +#define IPC_SHOW_NOTIFICATION 632 + +#define IPC_GETSKININFO 633 + +#define IPC_GET_MANUALPLADVANCE 634 +/* (requires Winamp 5.03+) +** val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_MANUALPLADVANCE); +** +** IPC_GET_MANUALPLADVANCE returns the status of the Manual Playlist Advance (1 if set) +*/ + +#define IPC_SET_MANUALPLADVANCE 635 +/* (requires Winamp 5.03+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_MANUALPLADVANCE); +** +** IPC_SET_MANUALPLADVANCE sets the status of the Manual Playlist Advance option (1 to turn it on) +*/ + +#define IPC_GET_NEXT_PLITEM 636 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_NEXT_PLITEM); +** +** Sent to Winamp's main window when an item has just finished playback or the next button has been pressed and +** requesting the new playlist item number to go to. +** Mainly used by gen_jumpex. Subclass this message in your application to return the new item number. +** -1 for normal winamp operation (default) or the new item number in the playlist to play. +*/ + +#define IPC_GET_PREVIOUS_PLITEM 637 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_PREVIOUS_PLITEM); +** +** Sent to Winamp's main window when the previous button has been pressed and Winamp is requesting the new playlist item number to go to. +** Mainly used by gen_jumpex. Subclass this message in your application to return the new item number. +** -1 for normal winamp operation (default) or the new item number in the playlist to play. +*/ + +#define IPC_IS_WNDSHADE 638 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,wnd,IPC_IS_WNDSHADE); +** +** 'wnd' is window id as defined for IPC_GETWND, or -1 for main window +** Returns 1 if wnd is set to winshade mode, or 0 if it is not +*/ + +#define IPC_SETRATING 639 +/* (requires Winamp 5.04+ with ML) +** SendMessage(hwnd_winamp,WM_WA_IPC,rating,IPC_SETRATING); +** 'rating' is an int value from 0 (no rating) to 5 +*/ + +#define IPC_GETRATING 640 +/* (requires Winamp 5.04+ with ML) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETRATING); +** returns the current item's rating +*/ + +#define IPC_GETNUMAUDIOTRACKS 641 +/* (requires Winamp 5.04+) +** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMAUDIOTRACKS); +** returns the number of audio tracks for the currently playing item +*/ + +#define IPC_GETNUMVIDEOTRACKS 642 +/* (requires Winamp 5.04+) +** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMVIDEOTRACKS); +** returns the number of video tracks for the currently playing item +*/ + +#define IPC_GETAUDIOTRACK 643 +/* (requires Winamp 5.04+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETAUDIOTRACK); +** returns the id of the current audio track for the currently playing item +*/ + +#define IPC_GETVIDEOTRACK 644 +/* (requires Winamp 5.04+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVIDEOTRACK); +** returns the id of the current video track for the currently playing item +*/ + +#define IPC_SETAUDIOTRACK 645 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETAUDIOTRACK); +** switch the currently playing item to a new audio track +*/ + +#define IPC_SETVIDEOTRACK 646 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETVIDEOTRACK); +** switch the currently playing item to a new video track +*/ + +#define IPC_PUSH_DISABLE_EXIT 647 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PUSH_DISABLE_EXIT ); +** lets you disable or re-enable the UI exit functions (close button, +** context menu, alt-f4). +** call IPC_POP_DISABLE_EXIT when you are done doing whatever required +** preventing exit +*/ + +#define IPC_POP_DISABLE_EXIT 648 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_POP_DISABLE_EXIT ); +** see IPC_PUSH_DISABLE_EXIT +*/ + +#define IPC_IS_EXIT_ENABLED 649 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_EXIT_ENABLED); +** returns 0 if exit is disabled, 1 otherwise +*/ + +#define IPC_IS_AOT 650 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_AOT); +** returns status of always on top flag. note: this may not match the actual +** TOPMOST window flag while another fullscreen application is focused +*/ + +#define IPC_USES_RECYCLEBIN 651 +/* +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USES_RECYCLEBIN); +** returns 1 if deleted files should be sent to the recycle bin. +** returns 0 if deleted files should be deleted permanently. +** +** You should check for this option if your plugin deletes files +** so that your setting matches the winamp setting +*/ + +#define IPC_FLUSHAUDITS 652 +/* +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_FLUSHAUDITS); +** +** Will flush any pending audits in the global audits que +** +*/ + +#define IPC_GETPLAYITEM_START 653 +#define IPC_GETPLAYITEM_END 654 + + +#define IPC_GETVIDEORESIZE 655 +#define IPC_SETVIDEORESIZE 656 + +// >>>>>>>>>>> Next is 657 + +#define IPC_PLCMD 1000 + +#define PLCMD_ADD 0 +#define PLCMD_REM 1 +#define PLCMD_SEL 2 +#define PLCMD_MISC 3 +#define PLCMD_LIST 4 + +//#define IPC_MBCMD 1001 + +#define MBCMD_BACK 0 +#define MBCMD_FORWARD 1 +#define MBCMD_STOP 2 +#define MBCMD_RELOAD 3 +#define MBCMD_MISC 4 + +#define IPC_VIDCMD 1002 + +#define VIDCMD_FULLSCREEN 0 +#define VIDCMD_1X 1 +#define VIDCMD_2X 2 +#define VIDCMD_LIB 3 +#define VIDPOPUP_MISC 4 + +//#define IPC_MBURL 1003 //sets the URL +//#define IPC_MBGETCURURL 1004 //copies the current URL into wParam (have a 4096 buffer ready) +//#define IPC_MBGETDESC 1005 //copies the current URL description into wParam (have a 4096 buffer ready) +//#define IPC_MBCHECKLOCFILE 1006 //checks that the link file is up to date (otherwise updates it). wParam=parent HWND +//#define IPC_MBREFRESH 1007 //refreshes the "now playing" view in the library +//#define IPC_MBGETDEFURL 1008 //copies the default URL into wParam (have a 4096 buffer ready) + +#define IPC_STATS_LIBRARY_ITEMCNT 1300 // updates library count status + +// IPC 2000-3000 reserved for freeform messages, see gen_ff/ff_ipc.h +#define IPC_FF_FIRST 2000 +#define IPC_FF_LAST 3000 + + +/* +** General IPC messages in Winamp +** +** All notification messages appear in the lParam of the main window message proceedure. +*/ + + +#define IPC_GETDROPTARGET 3001 +/* (requires Winamp 5.0+) +** IDropTarget* IDrop = (IDropTarget*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETDROPTARGET); +** +** You call this to retrieve a copy of the IDropTarget interface which Winamp created for +** handling external drag and drop operations on to it's Windows. This is only really +** useful if you're providing an alternate interface and want your Windows to provide the +** same drag and drop support as Winamp normally provides the user. Check out MSDN or +** your prefered search facility for more information about the IDropTarget interface and +** what's needed to handle it in your own instance. +*/ + +#define IPC_PLAYLIST_MODIFIED 3002 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window whenever the playlist is +** modified in any way e.g. the addition/removal of a playlist entry. +** +** It is not a good idea to do large amounts of processing in this notification since it +** will slow down Winamp as playlist entries are modified (especially when you're adding +** in a large playlist). +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYLIST_MODIFIED){ +** // do what you need to do here +** } +*/ + +#define IPC_PLAYING_FILE 3003 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when playback begins for +** a file. This passes the full filepath in the wParam of the message received. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILE){ +** // do what you need to do here, e.g. +** process_file((char*)wParam); +** } +*/ + +#define IPC_PLAYING_FILEW 13003 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when playback begins for +** a file. This passes the full filepath in the wParam of the message received. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILEW){ +** // do what you need to do here, e.g. +** process_file((wchar_t*)wParam); +** } +*/ + +#define IPC_FILE_TAG_MAY_HAVE_UPDATED 3004 // sent to main wnd with the file as parm (char *) whenever a file tag might be updated +#define IPC_FILE_TAG_MAY_HAVE_UPDATEDW 3005 // sent to main wnd with the file as parm (wchar_t *) whenever a file tag might be updated +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when a file's tag +** (e.g. id3) may have been updated. This appears to be sent when the InfoBox(..) function +** of the associated input plugin returns a 1 (which is the file information dialog/editor +** call normally). +** +** if(uMsg == WM_WA_IPC && lParam == IPC_FILE_TAG_MAY_HAVE_UPDATED){ +** // do what you need to do here, e.g. +** update_info_on_file_update((char*)wParam); +** } +*/ + +#define IPC_ALLOW_PLAYTRACKING 3007 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,allow,IPC_ALLOW_PLAYTRACKING); +** Send allow as nonzero to allow play tracking and zero to disable the mode. +*/ + +#define IPC_HOOK_OKTOQUIT 3010 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window asking if it's okay to +** close or not. Return zero to prevent Winamp from closing or return anything non-zero +** to allow Winamp to close. +** +** The best implementation of this option is to let the message pass through to the +** original window proceedure since another plugin may want to have a say in the matter +** with regards to Winamp closing. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_HOOK_OKTOQUIT){ +** // do what you need to do here, e.g. +** if(no_shut_down()){ +** return 1; +** } +** } +*/ + +#define IPC_WRITECONFIG 3011 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,write_type,IPC_WRITECONFIG); +** +** Send write_type as 2 to write all config settings and the current playlist. +** +** Send write_type as 1 to write the playlist and common settings. +** This won't save the following ini settings:: +** +** defext, titlefmt, proxy, visplugin_name, dspplugin_name, check_ft_startup, +** visplugin_num, pe_fontsize, visplugin_priority, visplugin_autoexec, dspplugin_num, +** sticon, splash, taskbar, dropaotfs, ascb_new, ttips, riol, minst, whichicon, +** whichicon2, addtolist, snap, snaplen, parent, hilite, disvis, rofiob, shownumsinpl, +** keeponscreen, eqdsize, usecursors, fixtitles, priority, shuffle_morph_rate, +** useexttitles, bifont, inet_mode, ospb, embedwnd_freesize, no_visseh +** (the above was valid for 5.1) +** +** Send write_type as 0 to write the common and less common settings and no playlist. +*/ + +#define IPC_UPDATE_URL 3012 // pass the URL (char *) in lparam, will be free()'d on done. + +// pass a string to be the name to register, and returns a value > 65536, which is a unique value you can use +// for custom WM_WA_IPC messages. + +#define IPC_GET_RANDFUNC 3015 // returns a function to get a random number +/* (requires Winamp 5.1+) +** int (*randfunc)(void) = (int(*)(void))SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GET_RANDFUNC); +** if(randfunc && randfunc != 1){ +** randfunc(); +** } +** +** This will return a positive 32-bit number (essentially 31-bit). +** The check for a returned value of 1 is because that's the default return value from +** SendMessage(..) when it is not handled so is good to check for it in this situation. +*/ + +#define IPC_METADATA_CHANGED 3017 +/* (requires Winamp 5.1+) +** int changed=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)field,IPC_METADATA_CHANGED); +** a plugin can SendMessage this to winamp if internal metadata has changes. +** wParam should be a char * of what field changed +** +** Currently used for internal actions (and very few at that) the intent of this api is +** to allow a plugin to call it when metadata has changed in the current playlist entry +** e.g.a new id3v2 tag was found in a stream +** +** The wparam value can either be NULL or a pointer to an ansi string for the metadata +** which has changed. This can be thought of as an advanced version of IPC_UPDTITLE and +** could be used to allow for update of the current title when a specific tag changed. +** +** Not recommended to be used since there is not the complete handling implemented in +** Winamp for it at the moment. +*/ + +#define IPC_SKIN_CHANGED 3018 +/* (requires Winamp 5.1+) +** This is a notification message sent to the main Winamp window by itself whenever +** the skin in use is changed. There is no information sent by the wParam for this. +** +** if(message == WM_WA_IPC && lparam == IPC_SKIN_CHANGED){ +** // do what you need to do to handle skin changes, e.g. call WADlg_init(hwnd_winamp); +** } +*/ + +#define IPC_REGISTER_LOWORD_COMMAND 3019 +/* (requires Winamp 5.1+) +** WORD id = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REGISTER_LOWORD_COMMAND); +** This will assign you a unique id for making your own commands such as for extra menu +** entries. The starting value returned by this message will potentially change as and +** when the main resource file of Winamp is updated with extra data so assumptions cannot +** be made on what will be returned and plugin loading order will affect things as well. + +** 5.33+ +** If you want to reserve more than one id, you can pass the number of ids required in wParam +*/ + +#define IPC_GET_DISPATCH_OBJECT 3020 // gets winamp main IDispatch * (for embedded webpages) +#define IPC_GET_UNIQUE_DISPATCH_ID 3021 // gives you a unique dispatch ID that won't conflict with anything in winamp's IDispatch * + +#define IPC_ADD_DISPATCH_OBJECT 3022 // add your own dispatch object into winamp's. This lets embedded webpages access your functions +// pass a pointer to DispatchInfo (see below). Winamp makes a copy of all this data so you can safely delete it later +typedef struct +{ + wchar_t *name; // filled in by plugin, make sure it's a unicode string!! (i.e. L"myObject" instead of "myObject). + struct IDispatch *dispatch; // filled in by plugin + DWORD id; // filled in by winamp on return +} DispatchInfo; + +#define IPC_GET_PROXY_STRING 3023 +/* (requires Winamp 5.11+) +** char* proxy_string=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_PROXY_STRING); +** This will return the same string as is shown on the General Preferences page. +*/ + +#define IPC_USE_REGISTRY 3024 +/* (requires Winamp 5.11+) +** int reg_enabled=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USE_REGISTRY); +** This will return 0 if you should leave your grubby hands off the registry (i.e. for +** lockdown mode). This is useful if Winamp is run from a USB drive and you can't alter +** system settings, etc. +*/ + +#define IPC_GET_API_SERVICE 3025 +/* (requires Winamp 5.12+) +** api_service* api_service = (api_service)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_API_SERVICE); +** This api will return Winamp's api_service pointer (which is what Winamp3 used, heh). +** If this api is not supported in the Winamp version that is being used at the time then +** the returned value from this api will be 1 which is a good version check. +** +** As of 5.12 there is support for .w5s plugins which reside in %WinampDir%\System and +** are intended for common code that can be shared amongst other plugins e.g. jnetlib.w5s +** which contains jnetlib in one instance instead of being duplicated multiple times in +** all of the plugins which need internet access. +** +** Details on the .w5s specifications will come at some stage (possibly). +*/ + + + +typedef struct { + const wchar_t *filename; + const wchar_t *metadata; + wchar_t *ret; + size_t retlen; +} extendedFileInfoStructW; + +#define IPC_GET_EXTENDED_FILE_INFOW 3026 +/* (requires Winamp 5.13+) +** Pass a pointer to the above struct in wParam +*/ +#define IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE 3027 +#define IPC_SET_EXTENDED_FILE_INFOW 3028 +/* (requires Winamp 5.13+) +** Pass a pointer to the above struct in wParam +*/ + +#define IPC_PLAYLIST_GET_NEXT_SELECTED 3029 +/* (requires 5.2+) +** int pl_item = SendMessage(hwnd_winamp,WM_WA_IPC,start,IPC_PLAYLIST_GET_NEXT_SELECTED); +** +** This works just like the ListView_GetNextItem(..) macro for ListView controls. +** 'start' is the index of the playlist item that you want to begin the search after or +** set this as -1 for the search to begin with the first item of the current playlist. +** +** This will return the index of the selected playlist according to the 'start' value or +** it returns -1 if there is no selection or no more selected items according to 'start'. +** +** Quick example: +** +** int sel = -1; +** // keep incrementing the start of the search so we get all of the selected entries +** while((sel = SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_PLAYLIST_GET_NEXT_SELECTED))!=-1){ +** // show the playlist file entry of the selected item(s) if there were any +** MessageBox(hwnd_winamp,(char*)SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_GETPLAYLISTFILE),0,0); +** } +*/ + +#define IPC_PLAYLIST_GET_SELECTED_COUNT 3030 +/* (requires 5.2+) +** int selcnt = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PLAYLIST_GET_SELECTED_COUNT); +** This will return the number of selected playlist entries. +*/ + +#define IPC_GET_PLAYING_FILENAME 3031 // returns wchar_t * of the currently playing filename + +#define IPC_OPEN_URL 3032 // send either ANSI or Unicode string (it'll figure it out, but it MUST start with "h"!, so don't send ftp:// or anything funny) + +#define IPC_REGISTER_WINAMP_IPCMESSAGE 65536 +/* (requires Winamp 5.0+) +** DWORD id = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)name,IPC_REGISTER_WINAMP_IPCMESSAGE); +** The value 'id' returned is > 65536 and is incremented on subsequent calls for unique +** 'name' values passed to it. By using the same 'name' in different plugins will allow a +** common runtime api to be provided for the currently running instance of Winamp +** e.g. +** PostMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)my_param,registered_ipc); +** Have a look at wa_hotkeys.h for an example on how this api is used in practice for a +** custom WM_WA_IPC message. +** +** if(uMsg == WM_WA_IPC && lParam == id_from_register_winamp_ipcmessage){ +** // do things +** } +*/ + +#endif//_WA_IPC_H_ diff --git a/vendor/JavaWinampApi/1.1/cpp/wpcom.dev b/vendor/JavaWinampApi/1.1/cpp/wpcom.dev new file mode 100644 index 0000000..2c226a4 --- /dev/null +++ b/vendor/JavaWinampApi/1.1/cpp/wpcom.dev @@ -0,0 +1,69 @@ +[Project] +FileName=wpcom.dev +Name=wpcom +UnitCount=2 +Type=3 +Ver=1 +ObjFiles= +Includes="E:\Program Files\Java\jdk1.6.0_11\include";"E:\Program Files\Java\jdk1.6.0_11\include\win32" +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler=-DBUILDING_DLL=1_@@_ +CppCompiler=-DBUILDING_DLL=1_@@_ +Linker=--no-export-all-symbols --add-stdcall-alias_@@_ +IsCpp=0 +Icon= +ExeOutput=..\..\..\JavaWinampAPI +ObjectOutput= +OverrideOutput=1 +OverrideOutputName=wpcom.dll +HostApplication= +Folders= +CommandLine= +UseCustomMakefile=0 +CustomMakefile= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 + +[Unit1] +FileName=WinampController.c +CompileCpp=0 +Folder=wacon +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c WinampController.c -o WinampController.o $(CFLAGS) + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit2] +FileName=WinampController.h +CompileCpp=0 +Folder=wacon +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/vendor/JavaWinampApi/1.1/cpp/wpcom.layout b/vendor/JavaWinampApi/1.1/cpp/wpcom.layout new file mode 100644 index 0000000..fc89c00 --- /dev/null +++ b/vendor/JavaWinampApi/1.1/cpp/wpcom.layout @@ -0,0 +1,17 @@ +[Editor_0] +CursorCol=32 +CursorRow=359 +TopLine=338 +LeftChar=1 +Open=1 +Top=1 +[Editors] +Focused=0 +Order=1,0 +[Editor_1] +Open=1 +Top=0 +CursorCol=73 +CursorRow=143 +TopLine=127 +LeftChar=1 diff --git a/vendor/JavaWinampApi/1.1/java/com/qotsa/exception/InvalidHandle.java b/vendor/JavaWinampApi/1.1/java/com/qotsa/exception/InvalidHandle.java new file mode 100644 index 0000000..4785982 --- /dev/null +++ b/vendor/JavaWinampApi/1.1/java/com/qotsa/exception/InvalidHandle.java @@ -0,0 +1,40 @@ +/* + * InvalidHandle.java + * + * Created on 9 de Outubro de 2007, 14:18 + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.qotsa.exception; + +/** + * Exception to throw when Winamp Handle Fails. + * + * @author Francisco + */ +public class InvalidHandle extends Exception{ + + private static final String defaultMessage = "Invalid Handle. Please Verify if Winamp is running."; + + /** + * Creates a new instance of InvalidHandle + * @param message Message to print in the stack. + */ + public InvalidHandle(String message) { + + super(message); + + } + + /** + * Creates a new instance of InvalidHandle with the default message + */ + public InvalidHandle() { + + super(defaultMessage); + + } + +} diff --git a/vendor/JavaWinampApi/1.1/java/com/qotsa/exception/InvalidParameter.java b/vendor/JavaWinampApi/1.1/java/com/qotsa/exception/InvalidParameter.java new file mode 100644 index 0000000..3499308 --- /dev/null +++ b/vendor/JavaWinampApi/1.1/java/com/qotsa/exception/InvalidParameter.java @@ -0,0 +1,40 @@ +/* + * InvalidParameter.java + * + * Created on 11 de Outubro de 2007, 10:53 + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.qotsa.exception; + +/** + * Exception to throw when any parameter is invalid. + * + * @author Francisco + */ +public class InvalidParameter extends Exception { + + private static final String defaultMessage = "Invalid Parameter"; + + /** + * Creates a new instance of NegativeValueException + * @param message Message to print in the stack. + */ + public InvalidParameter(String message) { + + super(message); + + } + + /** + * Creates a new instance of NegativeValueException with the default message + */ + public InvalidParameter() { + + super(defaultMessage); + + } + +} diff --git a/vendor/JavaWinampApi/1.1/java/com/qotsa/exception/package.html b/vendor/JavaWinampApi/1.1/java/com/qotsa/exception/package.html new file mode 100644 index 0000000..b2aafb7 --- /dev/null +++ b/vendor/JavaWinampApi/1.1/java/com/qotsa/exception/package.html @@ -0,0 +1,20 @@ + + + + + + + +Package containing the Exception Class used in the WinampController Class. + + +

Package Specification

+ + + + + diff --git a/vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/JNIWinamp.java b/vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/JNIWinamp.java new file mode 100644 index 0000000..8da725e --- /dev/null +++ b/vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/JNIWinamp.java @@ -0,0 +1,227 @@ +/* + * JNIWinamp.java + * + * Created on 23 de Abril de 2007, 20:41 + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.qotsa.jni.controller; + +import java.io.IOException; + +/** + * + * @author Francisco Guimarães + */ +final class JNIWinamp { + + static { + System.loadLibrary("wpcom"); + } + + /** + * Verify if Winamp is started + * and if not started, starts it + * @return True - if successful run Winamp + * False - if not successful run Winamp + */ + + protected static native boolean run() throws UnsatisfiedLinkError; + + /* + * Exit Winamp + * @return True - if successful exit + * False - if not successful exit + */ + protected static native boolean exit() throws UnsatisfiedLinkError; + + /** + * Play Winamp. + * + */ + protected static native boolean play() throws UnsatisfiedLinkError; + + /** + * Stop Winamp. + * + */ + protected static native boolean stop() throws UnsatisfiedLinkError; + + /** + * Resume Winamp. + * + */ + protected static native boolean resume() throws UnsatisfiedLinkError; + + /** + * Pause Winamp. + * + */ + protected static native boolean pause() throws UnsatisfiedLinkError; + + /** + * Go to Previous Track. + * + */ + protected static native boolean previousTrack() throws UnsatisfiedLinkError; + + /** + * Go to Next Track. + * + */ + protected static native boolean nextTrack() throws UnsatisfiedLinkError; + + /** + * Fowards 5 seconds on the current song. + * + */ + protected static native boolean fwd5Secs() throws UnsatisfiedLinkError; + + /** + * Rewinds 5 seconds on the current song. + * + */ + protected static native boolean rew5Secs() throws UnsatisfiedLinkError; + + /** + * Increase Volume. + * + */ + protected static native boolean increaseVolume() throws UnsatisfiedLinkError; + + /** + * Decrease Volume. + * + */ + protected static native boolean decreaseVolume() throws UnsatisfiedLinkError; + + /** + * Increase Volume. + * @param percent Percent to Increase. + */ + protected static native boolean increaseVolumePercent(int percent) throws UnsatisfiedLinkError; + + /** + * Decrease Volume. + * @param percent Percent to Decrease. + */ + protected static native boolean decreaseVolumePercent(int percent) throws UnsatisfiedLinkError; + + /** + * Adjust Volume + * @param pos Position to Set Volume between 0 and 99. + */ + protected static native boolean setVolume(int pos) throws UnsatisfiedLinkError; + + /** + * Get Volume. + * @return volume. + */ + protected static native int getVolume() throws UnsatisfiedLinkError; + + /** + * Go to a Specified Position in the List. + * @param pos Position. + */ + protected static native boolean setPlaylistPosition(int pos) throws UnsatisfiedLinkError; + + /** + * Clear List. + * + */ + protected static native boolean clearPlayList() throws UnsatisfiedLinkError; + + /** + * Refresh List´s Cache. + * + */ + protected static native boolean refreshPlayListCache() throws UnsatisfiedLinkError; + + /** + * Return the PlayListLength. + * @return List Length. + */ + protected static native int getPlayListLength() throws UnsatisfiedLinkError; + + /** + * Write a Playlist in \\Winamp.m3u. + * @return List Position. + */ + protected static native int writePlayListToFile() throws UnsatisfiedLinkError; + + /** + * Verify if Shuffle is On. + * @return True - On throws UnsatisfiedLinkError; False - Off. + */ + protected static native int isShuffleStatusOn() throws UnsatisfiedLinkError; + + /** + * Verify if Repeat is On. + * @return True - On throws UnsatisfiedLinkError; False - Off. + */ + protected static native int isRepeatStatusOn() throws UnsatisfiedLinkError; + + /** + * Turn on Repeat. + * @param True - Turn on Repeat throws UnsatisfiedLinkError; False - Turn off Repeat. + */ + protected static native boolean setRepeatStatusOn(boolean mode) throws UnsatisfiedLinkError; + + /** + * Turn on Shuffle. + * @param True - Turn on Shuffle throws UnsatisfiedLinkError; False - Turn off Shuffle. + */ + protected static native boolean setShuffleStatusOn(boolean mode) throws UnsatisfiedLinkError; + + /** + * Append a File in the List + * @param filename FileName to Append. + */ + protected static native boolean appendToPlayList(String filename) throws UnsatisfiedLinkError; + + /** + * Get Winamp Status. + * @return STOPPED - Stop + * PLAYING - play + * PAUSED - Paused + */ + protected static native int getStatus() throws UnsatisfiedLinkError; + + /** + * Get Current List Pos. + * @return Current List Position. + */ + protected static native int getListPos() throws UnsatisfiedLinkError; + + /** + * Get Current Track Title + * @return Current Track Title + */ + protected static native String getTitle() throws UnsatisfiedLinkError; + + /** + * Get Track FileName in List´s index. + * @param index Track Index in the Current PlayList + * @return Current Track FileName + */ + protected static native String getFileNameInList(int index) throws UnsatisfiedLinkError; + + /** + * Get Song Time + * @param mode CURRENTTIME - Currently Time in Milliseconds + * TIMELENGHT - Song Time Length in seconds + * @return Song Time in Seconds + */ + protected static native int getTime(int mode) throws UnsatisfiedLinkError; + + /** + * Get File Name Playing In Winamp. + * + * @return Current File Name. + */ + protected static native String getFileNamePlaying() throws UnsatisfiedLinkError; + +} + diff --git a/vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/WinampController.java b/vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/WinampController.java new file mode 100644 index 0000000..159fd9c --- /dev/null +++ b/vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/WinampController.java @@ -0,0 +1,592 @@ +/* + * WinampController.java + * + * Created on 9 de Outubro de 2007, 14:06 + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +/** + * Package containing the Controller Class to communicate with Winamp. + * + * @author Francisco Guimarães + */ +package com.qotsa.jni.controller; + +import com.qotsa.exception.InvalidHandle; +import com.qotsa.exception.InvalidParameter; +import java.io.File; + +/** + * This class is a wrapper to call JNI functions + * to send Message to Winamp Window. + * + * @author Francisco Guimarães + * + * + */ +public class WinampController { + + /** + * Constant used as return in getTime() + * Value = -1 + */ + public static final int ISNOTPLAYING = -1; + + /** + * Constant used as parameter in getTime() method + * Value = 0 + */ + public static final int CURRENTTIME = 0; + + /** + * Constant used as parameter in getTime() method + * Value = 1 + */ + public static final int TIMELENGTH = 1; + + /** + * Constant used as return in getStatus() method + * Value = 0 + */ + public static final int STOPPED = 0; + + /** + * Constant used as return in getStatus() method + * Value = 1 + */ + public static final int PLAYING = 1; + + /** + * Constant used as return in getStatus() method + * Value = 3 + */ + public static final int PAUSED = 3; + + + /** + * Verify if Winamp is started + * and if not started, starts it. + * + * @throws java.lang.Exception When the key HKEY_LOCAL_MACHINE\Software\Clients\Media\Winamp\shell\open\command + * is not found in the register. This key is used to find Winamp Directory installation to execute it. + */ + + public static void run() throws Exception{ + + if (!JNIWinamp.run()) + throw new Exception("Unable to run Winamp. Verify if it is properly installed"); + + } + + /** + * Exit Winamp. + * + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void exit() throws InvalidHandle { + + if (!JNIWinamp.exit()) + throw new InvalidHandle(); + + + } + + /** + * Play current file in Winamp. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void play() throws InvalidHandle { + + if (!JNIWinamp.play()) + throw new InvalidHandle(); + + } + + /** + * Stop current file in Winamp. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void stop() throws InvalidHandle { + + if (!JNIWinamp.stop()) + throw new InvalidHandle(); + + } + + /** + * Resume current file in Winamp. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void resume() throws InvalidHandle { + + if (!JNIWinamp.resume()) + throw new InvalidHandle(); + + } + + /** + * Pause Winamp. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void pause() throws InvalidHandle { + + if (!JNIWinamp.pause()) + throw new InvalidHandle(); + + } + + /** + * + * Go to Previous Track in the play list. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void previousTrack() throws InvalidHandle { + + if (!JNIWinamp.previousTrack()) + throw new InvalidHandle(); + + } + + /** + * Go to Next Track in the play list. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void nextTrack() throws InvalidHandle { + + if (!JNIWinamp.nextTrack()) + throw new InvalidHandle(); + + } + + /** + * Fowards 5 seconds on the current song. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void fwd5Secs() throws InvalidHandle { + + if (!JNIWinamp.fwd5Secs()) + throw new InvalidHandle(); + + } + + /** + * Rewinds 5 seconds on the current song. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void rew5Secs() throws InvalidHandle { + + if (!JNIWinamp.rew5Secs()) + throw new InvalidHandle(); + + } + + /** + * Increase Volume a little bit. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void increaseVolume() throws InvalidHandle { + + if (!JNIWinamp.increaseVolume()) + throw new InvalidHandle(); + + } + + /** + * Decrease Volume a little bit. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void decreaseVolume() throws InvalidHandle { + + if (!JNIWinamp.decreaseVolume()) + throw new InvalidHandle(); + + } + + /** + * Increase Volume. + * + * @param percent Percent to Increase Volume. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + * @throws com.qotsa.exception.InvalidParameter If percent not between 0 and 100 + */ + public static void increaseVolumePercent (int percent) throws InvalidHandle, InvalidParameter { + + if ( (percent < 0) || (percent > 100) ) + throw new InvalidParameter("percent´s value must be between 0 and 100"); + + if (!JNIWinamp.increaseVolumePercent(percent)) + throw new InvalidHandle(); + + } + + /** + * Decrease Volume. + * + * @param percent Percent to Decrease Volume. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + * @throws com.qotsa.exception.InvalidParameter If percent not between 0 and 100 + */ + public static void decreaseVolumePercent(int percent) throws InvalidHandle, InvalidParameter { + + if ( (percent < 0) || (percent > 100) ) + throw new InvalidParameter("percent´s value must be between 0 and 100"); + if (!JNIWinamp.decreaseVolumePercent(percent)) + throw new InvalidHandle(); + + } + + /** + * Adjust Volume. + * Note that the pos must be between 0(0%) and 255 (100%). + * + * @param pos Position to Set Volume. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + * @throws com.qotsa.exception.InvalidParameter If pos not between 0 and 255 + */ + public static void setVolume(int pos) throws InvalidHandle, InvalidParameter { + + if ( (pos < 0) || (pos > 255) ) + throw new InvalidParameter("pos value must be between 0 and 255"); + if (!JNIWinamp.setVolume(pos)) + throw new InvalidHandle(); + + } + + /** + * Get Volume. + * @return The volume which is a number between 0 (0%) and 255(100%) + * @throws com.qotsa.exception.InvalidHandle + */ + public static int getVolume() throws InvalidHandle { + int volume = JNIWinamp.getVolume(); + if (volume == -1) + throw new InvalidHandle(); + return volume; + } + + /** + * Get Volume Percent. + * @return Volume percent. + * @throws com.qotsa.exception.InvalidHandle + */ + public static int getVolumePercent() throws InvalidHandle { + + int volume = getVolume(); + int percent = (volume * 100) / 255; + return percent; + } + + /** + * Restarts Winamp. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + * @throws java.lang.Exception When failed to restart Winamp. + */ + public static void restart() throws InvalidHandle, Exception { + + exit(); + run(); + + } + + /** + * Go to a Specified Position in the List. This method doesn´t play. + * Just set list position. If you wanna play call play() after set position. + * Parameter pos is Zero-based index. + * @param pos Position. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + * @throws com.qotsa.exception.InvalidParameter If pos is negative or greater than List Length. + */ + public static void setPlaylistPosition(int pos) throws InvalidHandle, InvalidParameter { + + int listLength = getPlayListLength(); + if ( (pos < 0) || ( (pos + 1) > listLength) ) + throw new InvalidParameter("Position is invalid in the list."); + if (!JNIWinamp.setPlaylistPosition(pos)) + throw new InvalidHandle(); + + } + + /** + * Clear Winamp's internal playlist. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void clearPlayList() throws InvalidHandle { + + if (!JNIWinamp.clearPlayList()) + throw new InvalidHandle(); + + } + + /** + * Flush the playlist cache buffer. + * Call this if you want it to go refetch titles for tracks in the list. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void refreshPlayListCache() throws InvalidHandle{ + + if (!JNIWinamp.refreshPlayListCache()) + throw new InvalidHandle(); + + } + + /** + * Return the PlayListLength. + * + * @return List Length. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static int getPlayListLength() throws InvalidHandle { + + int length = JNIWinamp.getPlayListLength(); + if (length == -1) + throw new InvalidHandle(); + return length; + + } + + /** + * Write a Playlist in winampDirInstallation\\Winamp.m3u. + * This is default Winamp IPC Default. If you wanna change this, + * just rename the file you´ve created. + * + * @return Current List Position. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static int writePlayListToFile() throws InvalidHandle { + + int playListPos = JNIWinamp.writePlayListToFile(); + if (playListPos == -1) + throw new InvalidHandle(); + return playListPos; + + } + + /** + * Verify if Shuffle is On. + * + * @return True - On ; False - Off. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static boolean isShuffleStatusOn() throws InvalidHandle { + + int status = JNIWinamp.isShuffleStatusOn(); + if (status == -1) + throw new InvalidHandle(); + return (status == 1 ? true : false); + + } + + /** + * Verify if Repeat is On. + * + * @return True - On ; False - Off. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static boolean isRepeatStatusOn() throws InvalidHandle { + + int status = JNIWinamp.isRepeatStatusOn(); + if (status == -1) + throw new InvalidHandle(); + return (status == 1 ? true : false); + + } + + /** + * Turn on Repeat. + * + * @param mode True - Turn on Repeat ; False - Turn off Repeat. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void setRepeatStatusOn(boolean mode) throws InvalidHandle { + + if (!JNIWinamp.setRepeatStatusOn(mode)) + throw new InvalidHandle(); + + } + + /** + * Turn on Shuffle. + * + * @param mode True - Turn on Shuffle ; False - Turn off Shuffle. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static void setShuffleStatusOn(boolean mode) throws InvalidHandle { + + if (!JNIWinamp.setShuffleStatusOn(mode)) + throw new InvalidHandle(); + + } + + /** + * Append a File into the List. + * + * @param filename FileName to Append in the list. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + * @throws com.qotsa.exception.InvalidParameter If the filename is an invalid path. + */ + public static void appendToPlayList(String filename) throws InvalidHandle, InvalidParameter { + + File file = new File(filename); + if (!file.exists()) + throw new InvalidParameter("File doesn´t exists."); + if (!JNIWinamp.appendToPlayList(filename)) + throw new InvalidHandle(); + + } + + /** + * Get Winamp Status. + * + * @return STOPPED - Stop + * PLAYING - play + * PAUSED - Paused + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static int getStatus() throws InvalidHandle { + + int status = JNIWinamp.getStatus(); + if (status == -1) + throw new InvalidHandle(); + return status; + + } + + /** + * Get Current List Pos. + * + * @return Current List Position. + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static int getListPos() throws InvalidHandle { + + int pos = JNIWinamp.getListPos(); + if (pos == -1) + throw new InvalidHandle(); + return pos; + + } + + /** + * Get Current Track Title. + * + * @return Current Track Title + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + */ + public static String getTitle() throws InvalidHandle { + + String title = JNIWinamp.getTitle(); + if (title == null) + throw new InvalidHandle(); + return title; + + } + + /** + * Get Current Track FileName. + * Parameter pos is Zero-based index. + * + * @return Current Track FileName + * @param pos Track Position in the Current PlayList + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + * @throws com.qotsa.exception.InvalidParameter If pos is negative or greater than List Length + */ + public static String getFileNameInList(int pos) throws InvalidHandle, InvalidParameter { + + int listLength = getPlayListLength(); + if ( (pos < 0) || (pos > listLength) ) + throw new InvalidParameter("Position is invalid in the list."); + String filename = JNIWinamp.getFileNameInList(pos); + if (filename == null) + throw new InvalidHandle(); + return filename; + + } + + /** + * Get Song Time. + * + * @return Time Song (depends on Param mode) or + * ISNOTPLAYING if there is no info about time because it not starts to play. + * @param mode CURRENTTIME - Currently Time in Milliseconds + * TIMELENGHT - Song Time Length in seconds + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + * @throws com.qotsa.exception.InvalidParameter if parameter is not CURRENTTIME or TIMELENGTH. + */ + public static int getTime(int mode) throws InvalidHandle, InvalidParameter { + + if (mode != CURRENTTIME && mode != TIMELENGTH) + throw new InvalidParameter(); + int time = JNIWinamp.getTime(mode); + if (time == -2) + throw new InvalidHandle(); + return time; + + } + + /** + * Fowards n Tracks in Play List. + * + * @param n Number of Tracks to Foward + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + * @throws com.qotsa.exception.InvalidParameter if n is negative or Zero. + */ + public static void fwdTracks(int n) throws InvalidParameter, InvalidHandle { + + if (n <= 0) + throw new InvalidParameter("Value must be Positive"); + int pos = getListPos(); + int lengthList = getPlayListLength(); + int newPos = pos + n; + if (newPos > lengthList ) { + setPlaylistPosition(lengthList); + play(); + } + else { + setPlaylistPosition(newPos); + play(); + } + + } + + /** + * Rewinds n Tracks in Play List. + * + * @param n Number of Tracks to Rewind + * @throws com.qotsa.exception.InvalidHandle When the Winamp Windows is not handle(in most case, it means that winamp is not running) + * @throws com.qotsa.exception.InvalidParameter if n is negative or Zero. + */ + public static void rewTracks(int n) throws InvalidParameter, InvalidHandle { + + if (n <= 0) + throw new InvalidParameter("Value must be Positive"); + int pos = getListPos(); + int lengthList = getPlayListLength(); + int newPos = pos - n; + if (newPos < 0 ) { + setPlaylistPosition(0); + play(); + } + else { + setPlaylistPosition(newPos); + play(); + } + + } + + /** + * Get File Name Playing In Winamp. + * + * @return Current File Name. + */ + public static String getFileNamePlaying() throws InvalidHandle { + + String fileName = JNIWinamp.getFileNamePlaying(); + if (fileName == null) + throw new InvalidHandle(); + return fileName; + + } + +} diff --git a/vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/package.html b/vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/package.html new file mode 100644 index 0000000..c78cf04 --- /dev/null +++ b/vendor/JavaWinampApi/1.1/java/com/qotsa/jni/controller/package.html @@ -0,0 +1,20 @@ + + + + + + + +Package containing the Controller Class to communicate with Winamp. + + +

Package Specification

+ + + + + diff --git a/vendor/commons-logging/1.1.1/commons-logging-1.1.1.jar b/vendor/commons-logging/1.1.1/commons-logging-1.1.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..8758a96b70cfba9466bacca19c0d99b87cf53734 GIT binary patch literal 60841 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
    {@^= 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 He!Ti0B=`{t literal 0 HcmV?d00001 diff --git a/vendor/commons-logging/1.1.1/commons-logging-api-1.1.1.jar b/vendor/commons-logging/1.1.1/commons-logging-api-1.1.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..bd4511684badd0cc710df5169b98e7b8f351858e GIT binary patch literal 52313 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 literal 0 HcmV?d00001 diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/Log.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/Log.java new file mode 100644 index 0000000..1fef2f0 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/Log.java @@ -0,0 +1,246 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging; + +/** + *

    A simple logging interface abstracting logging APIs. In order to be + * instantiated successfully by {@link LogFactory}, classes that implement + * this interface must have a constructor that takes a single String + * parameter representing the "name" of this Log.

    + * + *

    The six logging levels used by Log are (in order): + *

      + *
    1. trace (the least serious)
    2. + *
    3. debug
    4. + *
    5. info
    6. + *
    7. warn
    8. + *
    9. error
    10. + *
    11. fatal (the most serious)
    12. + *
    + * The mapping of these log levels to the concepts used by the underlying + * logging system is implementation dependent. + * The implemention should ensure, though, that this ordering behaves + * as expected.

    + * + *

    Performance is often a logging concern. + * By examining the appropriate property, + * a component can avoid expensive operations (producing information + * to be logged).

    + * + *

    For example, + *

    + *    if (log.isDebugEnabled()) {
    + *        ... do something expensive ...
    + *        log.debug(theResult);
    + *    }
    + * 
    + *

    + * + *

    Configuration of the underlying logging system will generally be done + * external to the Logging APIs, through whatever mechanism is supported by + * that system.

    + * + * @author Scott Sanders + * @author Rod Waldhoff + * @version $Id: Log.java 424107 2006-07-20 23:15:42Z skitching $ + */ +public interface Log { + + + // ----------------------------------------------------- Logging Properties + + + /** + *

    Is debug logging currently enabled?

    + * + *

    Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than debug.

    + * + * @return true if debug is enabled in the underlying logger. + */ + public boolean isDebugEnabled(); + + + /** + *

    Is error logging currently enabled?

    + * + *

    Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than error.

    + * + * @return true if error is enabled in the underlying logger. + */ + public boolean isErrorEnabled(); + + + /** + *

    Is fatal logging currently enabled?

    + * + *

    Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than fatal.

    + * + * @return true if fatal is enabled in the underlying logger. + */ + public boolean isFatalEnabled(); + + + /** + *

    Is info logging currently enabled?

    + * + *

    Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than info.

    + * + * @return true if info is enabled in the underlying logger. + */ + public boolean isInfoEnabled(); + + + /** + *

    Is trace logging currently enabled?

    + * + *

    Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than trace.

    + * + * @return true if trace is enabled in the underlying logger. + */ + public boolean isTraceEnabled(); + + + /** + *

    Is warn logging currently enabled?

    + * + *

    Call this method to prevent having to perform expensive operations + * (for example, String concatenation) + * when the log level is more than warn.

    + * + * @return true if warn is enabled in the underlying logger. + */ + public boolean isWarnEnabled(); + + + // -------------------------------------------------------- Logging Methods + + + /** + *

    Log a message with trace log level.

    + * + * @param message log this message + */ + public void trace(Object message); + + + /** + *

    Log an error with trace log level.

    + * + * @param message log this message + * @param t log this cause + */ + public void trace(Object message, Throwable t); + + + /** + *

    Log a message with debug log level.

    + * + * @param message log this message + */ + public void debug(Object message); + + + /** + *

    Log an error with debug log level.

    + * + * @param message log this message + * @param t log this cause + */ + public void debug(Object message, Throwable t); + + + /** + *

    Log a message with info log level.

    + * + * @param message log this message + */ + public void info(Object message); + + + /** + *

    Log an error with info log level.

    + * + * @param message log this message + * @param t log this cause + */ + public void info(Object message, Throwable t); + + + /** + *

    Log a message with warn log level.

    + * + * @param message log this message + */ + public void warn(Object message); + + + /** + *

    Log an error with warn log level.

    + * + * @param message log this message + * @param t log this cause + */ + public void warn(Object message, Throwable t); + + + /** + *

    Log a message with error log level.

    + * + * @param message log this message + */ + public void error(Object message); + + + /** + *

    Log an error with error log level.

    + * + * @param message log this message + * @param t log this cause + */ + public void error(Object message, Throwable t); + + + /** + *

    Log a message with fatal log level.

    + * + * @param message log this message + */ + public void fatal(Object message); + + + /** + *

    Log an error with fatal log level.

    + * + * @param message log this message + * @param t log this cause + */ + public void fatal(Object message, Throwable t); + + +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogConfigurationException.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogConfigurationException.java new file mode 100644 index 0000000..419725d --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogConfigurationException.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging; + + +/** + *

    An exception that is thrown only if a suitable LogFactory + * or Log instance cannot be created by the corresponding + * factory methods.

    + * + * @author Craig R. McClanahan + * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ + */ + +public class LogConfigurationException extends RuntimeException { + + + /** + * Construct a new exception with null as its detail message. + */ + public LogConfigurationException() { + + super(); + + } + + + /** + * Construct a new exception with the specified detail message. + * + * @param message The detail message + */ + public LogConfigurationException(String message) { + + super(message); + + } + + + /** + * Construct a new exception with the specified cause and a derived + * detail message. + * + * @param cause The underlying cause + */ + public LogConfigurationException(Throwable cause) { + + this((cause == null) ? null : cause.toString(), cause); + + } + + + /** + * Construct a new exception with the specified detail message and cause. + * + * @param message The detail message + * @param cause The underlying cause + */ + public LogConfigurationException(String message, Throwable cause) { + + super(message + " (Caused by " + cause + ")"); + this.cause = cause; // Two-argument version requires JDK 1.4 or later + + } + + + /** + * The underlying cause of this exception. + */ + protected Throwable cause = null; + + + /** + * Return the underlying cause of this exception (if any). + */ + public Throwable getCause() { + + return (this.cause); + + } + + +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogFactory.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogFactory.java new file mode 100644 index 0000000..60522af --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogFactory.java @@ -0,0 +1,1824 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging; + + +import java.io.BufferedReader; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Properties; + + +/** + *

    Factory for creating {@link Log} instances, with discovery and + * configuration features similar to that employed by standard Java APIs + * such as JAXP.

    + * + *

    IMPLEMENTATION NOTE - This implementation is heavily + * based on the SAXParserFactory and DocumentBuilderFactory implementations + * (corresponding to the JAXP pluggability APIs) found in Apache Xerces.

    + * + * @author Craig R. McClanahan + * @author Costin Manolache + * @author Richard A. Sitze + * @version $Revision: 593798 $ $Date: 2007-11-10 18:40:43 +0100 $ + */ + +public abstract class LogFactory { + // Implementation note re AccessController usage + // + // It is important to keep code invoked via an AccessController to small + // auditable blocks. Such code must carefully evaluate all user input + // (parameters, system properties, config file contents, etc). As an + // example, a Log implementation should not write to its logfile + // with an AccessController anywhere in the call stack, otherwise an + // insecure application could configure the log implementation to write + // to a protected file using the privileges granted to JCL rather than + // to the calling application. + // + // Under no circumstance should a non-private method return data that is + // retrieved via an AccessController. That would allow an insecure app + // to invoke that method and obtain data that it is not permitted to have. + // + // Invoking user-supplied code with an AccessController set is not a major + // issue (eg invoking the constructor of the class specified by + // HASHTABLE_IMPLEMENTATION_PROPERTY). That class will be in a different + // trust domain, and therefore must have permissions to do whatever it + // is trying to do regardless of the permissions granted to JCL. There is + // a slight issue in that untrusted code may point that environment var + // to another trusted library, in which case the code runs if both that + // lib and JCL have the necessary permissions even when the untrusted + // caller does not. That's a pretty hard route to exploit though. + + + // ----------------------------------------------------- Manifest Constants + + /** + * The name (priority) of the key in the config file used to + * specify the priority of that particular config file. The associated value + * is a floating-point number; higher values take priority over lower values. + */ + public static final String PRIORITY_KEY = "priority"; + + /** + * The name (use_tccl) of the key in the config file used + * to specify whether logging classes should be loaded via the thread + * context class loader (TCCL), or not. By default, the TCCL is used. + */ + public static final String TCCL_KEY = "use_tccl"; + + /** + * The name (org.apache.commons.logging.LogFactory) of the property + * used to identify the LogFactory implementation + * class name. This can be used as a system property, or as an entry in a + * configuration properties file. + */ + public static final String FACTORY_PROPERTY = + "org.apache.commons.logging.LogFactory"; + + /** + * The fully qualified class name of the fallback LogFactory + * implementation class to use, if no other can be found. + */ + public static final String FACTORY_DEFAULT = + "org.apache.commons.logging.impl.LogFactoryImpl"; + + /** + * The name (commons-logging.properties) of the properties file to search for. + */ + public static final String FACTORY_PROPERTIES = + "commons-logging.properties"; + + /** + * JDK1.3+ + * 'Service Provider' specification. + * + */ + protected static final String SERVICE_ID = + "META-INF/services/org.apache.commons.logging.LogFactory"; + + /** + * The name (org.apache.commons.logging.diagnostics.dest) + * of the property used to enable internal commons-logging + * diagnostic output, in order to get information on what logging + * implementations are being discovered, what classloaders they + * are loaded through, etc. + *

    + * If a system property of this name is set then the value is + * assumed to be the name of a file. The special strings + * STDOUT or STDERR (case-sensitive) indicate output to + * System.out and System.err respectively. + *

    + * Diagnostic logging should be used only to debug problematic + * configurations and should not be set in normal production use. + */ + public static final String DIAGNOSTICS_DEST_PROPERTY = + "org.apache.commons.logging.diagnostics.dest"; + + /** + * When null (the usual case), no diagnostic output will be + * generated by LogFactory or LogFactoryImpl. When non-null, + * interesting events will be written to the specified object. + */ + private static PrintStream diagnosticsStream = null; + + /** + * A string that gets prefixed to every message output by the + * logDiagnostic method, so that users can clearly see which + * LogFactory class is generating the output. + */ + private static String diagnosticPrefix; + + /** + *

    Setting this system property + * (org.apache.commons.logging.LogFactory.HashtableImpl) + * value allows the Hashtable used to store + * classloaders to be substituted by an alternative implementation. + *

    + *

    + * Note: LogFactory will print: + *

    +     * [ERROR] LogFactory: Load of custom hashtable failed
    +     * 
    + * to system error and then continue using a standard Hashtable. + *

    + *

    + * Usage: Set this property when Java is invoked + * and LogFactory will attempt to load a new instance + * of the given implementation class. + * For example, running the following ant scriplet: + *

    +     *  <java classname="${test.runner}" fork="yes" failonerror="${test.failonerror}">
    +     *     ...
    +     *     <sysproperty 
    +     *        key="org.apache.commons.logging.LogFactory.HashtableImpl"
    +     *        value="org.apache.commons.logging.AltHashtable"/>
    +     *  </java>
    +     * 
    + * will mean that LogFactory will load an instance of + * org.apache.commons.logging.AltHashtable. + *

    + *

    + * A typical use case is to allow a custom + * Hashtable implementation using weak references to be substituted. + * This will allow classloaders to be garbage collected without + * the need to release them (on 1.3+ JVMs only, of course ;) + *

    + */ + public static final String HASHTABLE_IMPLEMENTATION_PROPERTY = + "org.apache.commons.logging.LogFactory.HashtableImpl"; + /** Name used to load the weak hashtable implementation by names */ + private static final String WEAK_HASHTABLE_CLASSNAME = + "org.apache.commons.logging.impl.WeakHashtable"; + + /** + * A reference to the classloader that loaded this class. This is the + * same as LogFactory.class.getClassLoader(). However computing this + * value isn't quite as simple as that, as we potentially need to use + * AccessControllers etc. It's more efficient to compute it once and + * cache it here. + */ + private static ClassLoader thisClassLoader; + + // ----------------------------------------------------------- Constructors + + + /** + * Protected constructor that is not available for public use. + */ + protected LogFactory() { + } + + // --------------------------------------------------------- Public Methods + + + /** + * Return the configuration attribute with the specified name (if any), + * or null if there is no such attribute. + * + * @param name Name of the attribute to return + */ + public abstract Object getAttribute(String name); + + + /** + * Return an array containing the names of all currently defined + * configuration attributes. If there are no such attributes, a zero + * length array is returned. + */ + public abstract String[] getAttributeNames(); + + + /** + * Convenience method to derive a name from the specified class and + * call getInstance(String) with it. + * + * @param clazz Class for which a suitable Log name will be derived + * + * @exception LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public abstract Log getInstance(Class clazz) + throws LogConfigurationException; + + + /** + *

    Construct (if necessary) and return a Log instance, + * using the factory's current set of configuration attributes.

    + * + *

    NOTE - Depending upon the implementation of + * the LogFactory you are using, the Log + * instance you are returned may or may not be local to the current + * application, and may or may not be returned again on a subsequent + * call with the same name argument.

    + * + * @param name Logical name of the Log instance to be + * returned (the meaning of this name is only known to the underlying + * logging implementation that is being wrapped) + * + * @exception LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public abstract Log getInstance(String name) + throws LogConfigurationException; + + + /** + * Release any internal references to previously created {@link Log} + * instances returned by this factory. This is useful in environments + * like servlet containers, which implement application reloading by + * throwing away a ClassLoader. Dangling references to objects in that + * class loader would prevent garbage collection. + */ + public abstract void release(); + + + /** + * Remove any configuration attribute associated with the specified name. + * If there is no such attribute, no action is taken. + * + * @param name Name of the attribute to remove + */ + public abstract void removeAttribute(String name); + + + /** + * Set the configuration attribute with the specified name. Calling + * this with a null value is equivalent to calling + * removeAttribute(name). + * + * @param name Name of the attribute to set + * @param value Value of the attribute to set, or null + * to remove any setting for this attribute + */ + public abstract void setAttribute(String name, Object value); + + + // ------------------------------------------------------- Static Variables + + + /** + * The previously constructed LogFactory instances, keyed by + * the ClassLoader with which it was created. + */ + protected static Hashtable factories = null; + + /** + * Prevously constructed LogFactory instance as in the + * factories map, but for the case where + * getClassLoader returns null. + * This can happen when: + *
      + *
    • using JDK1.1 and the calling code is loaded via the system + * classloader (very common)
    • + *
    • using JDK1.2+ and the calling code is loaded via the boot + * classloader (only likely for embedded systems work).
    • + *
    + * Note that factories is a Hashtable (not a HashMap), + * and hashtables don't allow null as a key. + */ + protected static LogFactory nullClassLoaderFactory = null; + + /** + * Create the hashtable which will be used to store a map of + * (context-classloader -> logfactory-object). Version 1.2+ of Java + * supports "weak references", allowing a custom Hashtable class + * to be used which uses only weak references to its keys. Using weak + * references can fix memory leaks on webapp unload in some cases (though + * not all). Version 1.1 of Java does not support weak references, so we + * must dynamically determine which we are using. And just for fun, this + * code also supports the ability for a system property to specify an + * arbitrary Hashtable implementation name. + *

    + * Note that the correct way to ensure no memory leaks occur is to ensure + * that LogFactory.release(contextClassLoader) is called whenever a + * webapp is undeployed. + */ + private static final Hashtable createFactoryStore() { + Hashtable result = null; + String storeImplementationClass; + try { + storeImplementationClass = getSystemProperty(HASHTABLE_IMPLEMENTATION_PROPERTY, null); + } catch(SecurityException ex) { + // Permissions don't allow this to be accessed. Default to the "modern" + // weak hashtable implementation if it is available. + storeImplementationClass = null; + } + + if (storeImplementationClass == null) { + storeImplementationClass = WEAK_HASHTABLE_CLASSNAME; + } + try { + Class implementationClass = Class.forName(storeImplementationClass); + result = (Hashtable) implementationClass.newInstance(); + + } catch (Throwable t) { + // ignore + if (!WEAK_HASHTABLE_CLASSNAME.equals(storeImplementationClass)) { + // if the user's trying to set up a custom implementation, give a clue + if (isDiagnosticsEnabled()) { + // use internal logging to issue the warning + logDiagnostic("[ERROR] LogFactory: Load of custom hashtable failed"); + } else { + // we *really* want this output, even if diagnostics weren't + // explicitly enabled by the user. + System.err.println("[ERROR] LogFactory: Load of custom hashtable failed"); + } + } + } + if (result == null) { + result = new Hashtable(); + } + return result; + } + + + // --------------------------------------------------------- Static Methods + + /** Utility method to safely trim a string. */ + private static String trim(String src) { + if (src == null) { + return null; + } + return src.trim(); + } + + /** + *

    Construct (if necessary) and return a LogFactory + * instance, using the following ordered lookup procedure to determine + * the name of the implementation class to be loaded.

    + *
      + *
    • The org.apache.commons.logging.LogFactory system + * property.
    • + *
    • The JDK 1.3 Service Discovery mechanism
    • + *
    • Use the properties file commons-logging.properties + * file, if found in the class path of this class. The configuration + * file is in standard java.util.Properties format and + * contains the fully qualified name of the implementation class + * with the key being the system property defined above.
    • + *
    • Fall back to a default implementation class + * (org.apache.commons.logging.impl.LogFactoryImpl).
    • + *
    + * + *

    NOTE - If the properties file method of identifying the + * LogFactory implementation class is utilized, all of the + * properties defined in this file will be set as configuration attributes + * on the corresponding LogFactory instance.

    + * + *

    NOTE - In a multithreaded environment it is possible + * that two different instances will be returned for the same + * classloader environment. + *

    + * + * @exception LogConfigurationException if the implementation class is not + * available or cannot be instantiated. + */ + public static LogFactory getFactory() throws LogConfigurationException { + // Identify the class loader we will be using + ClassLoader contextClassLoader = getContextClassLoaderInternal(); + + if (contextClassLoader == null) { + // This is an odd enough situation to report about. This + // output will be a nuisance on JDK1.1, as the system + // classloader is null in that environment. + if (isDiagnosticsEnabled()) { + logDiagnostic("Context classloader is null."); + } + } + + // Return any previously registered factory for this class loader + LogFactory factory = getCachedFactory(contextClassLoader); + if (factory != null) { + return factory; + } + + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] LogFactory implementation requested for the first time for context classloader " + + objectId(contextClassLoader)); + logHierarchy("[LOOKUP] ", contextClassLoader); + } + + // Load properties file. + // + // If the properties file exists, then its contents are used as + // "attributes" on the LogFactory implementation class. One particular + // property may also control which LogFactory concrete subclass is + // used, but only if other discovery mechanisms fail.. + // + // As the properties file (if it exists) will be used one way or + // another in the end we may as well look for it first. + + Properties props = getConfigurationFile(contextClassLoader, FACTORY_PROPERTIES); + + // Determine whether we will be using the thread context class loader to + // load logging classes or not by checking the loaded properties file (if any). + ClassLoader baseClassLoader = contextClassLoader; + if (props != null) { + String useTCCLStr = props.getProperty(TCCL_KEY); + if (useTCCLStr != null) { + // The Boolean.valueOf(useTCCLStr).booleanValue() formulation + // is required for Java 1.2 compatability. + if (Boolean.valueOf(useTCCLStr).booleanValue() == false) { + // Don't use current context classloader when locating any + // LogFactory or Log classes, just use the class that loaded + // this abstract class. When this class is deployed in a shared + // classpath of a container, it means webapps cannot deploy their + // own logging implementations. It also means that it is up to the + // implementation whether to load library-specific config files + // from the TCCL or not. + baseClassLoader = thisClassLoader; + } + } + } + + // Determine which concrete LogFactory subclass to use. + // First, try a global system property + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Looking for system property [" + FACTORY_PROPERTY + + "] to define the LogFactory subclass to use..."); + } + + try { + String factoryClass = getSystemProperty(FACTORY_PROPERTY, null); + if (factoryClass != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Creating an instance of LogFactory class '" + factoryClass + + "' as specified by system property " + FACTORY_PROPERTY); + } + + factory = newFactory(factoryClass, baseClassLoader, contextClassLoader); + } else { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] No system property [" + FACTORY_PROPERTY + + "] defined."); + } + } + } catch (SecurityException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] A security exception occurred while trying to create an" + + " instance of the custom factory class" + + ": [" + trim(e.getMessage()) + + "]. Trying alternative implementations..."); + } + ; // ignore + } catch(RuntimeException e) { + // This is not consistent with the behaviour when a bad LogFactory class is + // specified in a services file. + // + // One possible exception that can occur here is a ClassCastException when + // the specified class wasn't castable to this LogFactory type. + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] An exception occurred while trying to create an" + + " instance of the custom factory class" + + ": [" + trim(e.getMessage()) + + "] as specified by a system property."); + } + throw e; + } + + + // Second, try to find a service by using the JDK1.3 class + // discovery mechanism, which involves putting a file with the name + // of an interface class in the META-INF/services directory, where the + // contents of the file is a single line specifying a concrete class + // that implements the desired interface. + + if (factory == null) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Looking for a resource file of name [" + SERVICE_ID + + "] to define the LogFactory subclass to use..."); + } + try { + InputStream is = getResourceAsStream(contextClassLoader, + SERVICE_ID); + + if( is != null ) { + // This code is needed by EBCDIC and other strange systems. + // It's a fix for bugs reported in xerces + BufferedReader rd; + try { + rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); + } catch (java.io.UnsupportedEncodingException e) { + rd = new BufferedReader(new InputStreamReader(is)); + } + + String factoryClassName = rd.readLine(); + rd.close(); + + if (factoryClassName != null && + ! "".equals(factoryClassName)) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Creating an instance of LogFactory class " + factoryClassName + + " as specified by file '" + SERVICE_ID + + "' which was present in the path of the context" + + " classloader."); + } + factory = newFactory(factoryClassName, baseClassLoader, contextClassLoader ); + } + } else { + // is == null + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] No resource file with name '" + SERVICE_ID + + "' found."); + } + } + } catch( Exception ex ) { + // note: if the specified LogFactory class wasn't compatible with LogFactory + // for some reason, a ClassCastException will be caught here, and attempts will + // continue to find a compatible class. + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] A security exception occurred while trying to create an" + + " instance of the custom factory class" + + ": [" + trim(ex.getMessage()) + + "]. Trying alternative implementations..."); + } + ; // ignore + } + } + + + // Third try looking into the properties file read earlier (if found) + + if (factory == null) { + if (props != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Looking in properties file for entry with key '" + + FACTORY_PROPERTY + + "' to define the LogFactory subclass to use..."); + } + String factoryClass = props.getProperty(FACTORY_PROPERTY); + if (factoryClass != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Properties file specifies LogFactory subclass '" + + factoryClass + "'"); + } + factory = newFactory(factoryClass, baseClassLoader, contextClassLoader); + + // TODO: think about whether we need to handle exceptions from newFactory + } else { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Properties file has no entry specifying LogFactory subclass."); + } + } + } else { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] No properties file available to determine" + + " LogFactory subclass from.."); + } + } + } + + + // Fourth, try the fallback implementation class + + if (factory == null) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Loading the default LogFactory implementation '" + FACTORY_DEFAULT + + "' via the same classloader that loaded this LogFactory" + + " class (ie not looking in the context classloader)."); + } + + // Note: unlike the above code which can try to load custom LogFactory + // implementations via the TCCL, we don't try to load the default LogFactory + // implementation via the context classloader because: + // * that can cause problems (see comments in newFactory method) + // * no-one should be customising the code of the default class + // Yes, we do give up the ability for the child to ship a newer + // version of the LogFactoryImpl class and have it used dynamically + // by an old LogFactory class in the parent, but that isn't + // necessarily a good idea anyway. + factory = newFactory(FACTORY_DEFAULT, thisClassLoader, contextClassLoader); + } + + if (factory != null) { + /** + * Always cache using context class loader. + */ + cacheFactory(contextClassLoader, factory); + + if( props!=null ) { + Enumeration names = props.propertyNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + String value = props.getProperty(name); + factory.setAttribute(name, value); + } + } + } + + return factory; + } + + + /** + * Convenience method to return a named logger, without the application + * having to care about factories. + * + * @param clazz Class from which a log name will be derived + * + * @exception LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public static Log getLog(Class clazz) + throws LogConfigurationException { + + return (getFactory().getInstance(clazz)); + + } + + + /** + * Convenience method to return a named logger, without the application + * having to care about factories. + * + * @param name Logical name of the Log instance to be + * returned (the meaning of this name is only known to the underlying + * logging implementation that is being wrapped) + * + * @exception LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public static Log getLog(String name) + throws LogConfigurationException { + + return (getFactory().getInstance(name)); + + } + + + /** + * Release any internal references to previously created {@link LogFactory} + * instances that have been associated with the specified class loader + * (if any), after calling the instance method release() on + * each of them. + * + * @param classLoader ClassLoader for which to release the LogFactory + */ + public static void release(ClassLoader classLoader) { + + if (isDiagnosticsEnabled()) { + logDiagnostic("Releasing factory for classloader " + objectId(classLoader)); + } + synchronized (factories) { + if (classLoader == null) { + if (nullClassLoaderFactory != null) { + nullClassLoaderFactory.release(); + nullClassLoaderFactory = null; + } + } else { + LogFactory factory = (LogFactory) factories.get(classLoader); + if (factory != null) { + factory.release(); + factories.remove(classLoader); + } + } + } + + } + + + /** + * Release any internal references to previously created {@link LogFactory} + * instances, after calling the instance method release() on + * each of them. This is useful in environments like servlet containers, + * which implement application reloading by throwing away a ClassLoader. + * Dangling references to objects in that class loader would prevent + * garbage collection. + */ + public static void releaseAll() { + + if (isDiagnosticsEnabled()) { + logDiagnostic("Releasing factory for all classloaders."); + } + synchronized (factories) { + Enumeration elements = factories.elements(); + while (elements.hasMoreElements()) { + LogFactory element = (LogFactory) elements.nextElement(); + element.release(); + } + factories.clear(); + + if (nullClassLoaderFactory != null) { + nullClassLoaderFactory.release(); + nullClassLoaderFactory = null; + } + } + + } + + + // ------------------------------------------------------ Protected Methods + + /** + * Safely get access to the classloader for the specified class. + *

    + * Theoretically, calling getClassLoader can throw a security exception, + * and so should be done under an AccessController in order to provide + * maximum flexibility. However in practice people don't appear to use + * security policies that forbid getClassLoader calls. So for the moment + * all code is written to call this method rather than Class.getClassLoader, + * so that we could put AccessController stuff in this method without any + * disruption later if we need to. + *

    + * Even when using an AccessController, however, this method can still + * throw SecurityException. Commons-logging basically relies on the + * ability to access classloaders, ie a policy that forbids all + * classloader access will also prevent commons-logging from working: + * currently this method will throw an exception preventing the entire app + * from starting up. Maybe it would be good to detect this situation and + * just disable all commons-logging? Not high priority though - as stated + * above, security policies that prevent classloader access aren't common. + *

    + * Note that returning an object fetched via an AccessController would + * technically be a security flaw anyway; untrusted code that has access + * to a trusted JCL library could use it to fetch the classloader for + * a class even when forbidden to do so directly. + * + * @since 1.1 + */ + protected static ClassLoader getClassLoader(Class clazz) { + try { + return clazz.getClassLoader(); + } catch(SecurityException ex) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "Unable to get classloader for class '" + clazz + + "' due to security restrictions - " + ex.getMessage()); + } + throw ex; + } + } + + /** + * Returns the current context classloader. + *

    + * In versions prior to 1.1, this method did not use an AccessController. + * In version 1.1, an AccessController wrapper was incorrectly added to + * this method, causing a minor security flaw. + *

    + * In version 1.1.1 this change was reverted; this method no longer uses + * an AccessController. User code wishing to obtain the context classloader + * must invoke this method via AccessController.doPrivileged if it needs + * support for that. + * + * @return the context classloader associated with the current thread, + * or null if security doesn't allow it. + * + * @throws LogConfigurationException if there was some weird error while + * attempting to get the context classloader. + * + * @throws SecurityException if the current java security policy doesn't + * allow this class to access the context classloader. + */ + protected static ClassLoader getContextClassLoader() + throws LogConfigurationException { + + return directGetContextClassLoader(); + } + + /** + * Calls LogFactory.directGetContextClassLoader under the control of an + * AccessController class. This means that java code running under a + * security manager that forbids access to ClassLoaders will still work + * if this class is given appropriate privileges, even when the caller + * doesn't have such privileges. Without using an AccessController, the + * the entire call stack must have the privilege before the call is + * allowed. + * + * @return the context classloader associated with the current thread, + * or null if security doesn't allow it. + * + * @throws LogConfigurationException if there was some weird error while + * attempting to get the context classloader. + * + * @throws SecurityException if the current java security policy doesn't + * allow this class to access the context classloader. + */ + private static ClassLoader getContextClassLoaderInternal() + throws LogConfigurationException { + return (ClassLoader)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return directGetContextClassLoader(); + } + }); + } + + /** + * Return the thread context class loader if available; otherwise return + * null. + *

    + * Most/all code should call getContextClassLoaderInternal rather than + * calling this method directly. + *

    + * The thread context class loader is available for JDK 1.2 + * or later, if certain security conditions are met. + *

    + * Note that no internal logging is done within this method because + * this method is called every time LogFactory.getLogger() is called, + * and we don't want too much output generated here. + * + * @exception LogConfigurationException if a suitable class loader + * cannot be identified. + * + * @exception SecurityException if the java security policy forbids + * access to the context classloader from one of the classes in the + * current call stack. + * @since 1.1 + */ + protected static ClassLoader directGetContextClassLoader() + throws LogConfigurationException + { + ClassLoader classLoader = null; + + try { + // Are we running on a JDK 1.2 or later system? + Method method = Thread.class.getMethod("getContextClassLoader", + (Class[]) null); + + // Get the thread context class loader (if there is one) + try { + classLoader = (ClassLoader)method.invoke(Thread.currentThread(), + (Object[]) null); + } catch (IllegalAccessException e) { + throw new LogConfigurationException + ("Unexpected IllegalAccessException", e); + } catch (InvocationTargetException e) { + /** + * InvocationTargetException is thrown by 'invoke' when + * the method being invoked (getContextClassLoader) throws + * an exception. + * + * getContextClassLoader() throws SecurityException when + * the context class loader isn't an ancestor of the + * calling class's class loader, or if security + * permissions are restricted. + * + * In the first case (not related), we want to ignore and + * keep going. We cannot help but also ignore the second + * with the logic below, but other calls elsewhere (to + * obtain a class loader) will trigger this exception where + * we can make a distinction. + */ + if (e.getTargetException() instanceof SecurityException) { + ; // ignore + } else { + // Capture 'e.getTargetException()' exception for details + // alternate: log 'e.getTargetException()', and pass back 'e'. + throw new LogConfigurationException + ("Unexpected InvocationTargetException", e.getTargetException()); + } + } + } catch (NoSuchMethodException e) { + // Assume we are running on JDK 1.1 + classLoader = getClassLoader(LogFactory.class); + + // We deliberately don't log a message here to outputStream; + // this message would be output for every call to LogFactory.getLog() + // when running on JDK1.1 + // + // if (outputStream != null) { + // outputStream.println( + // "Method Thread.getContextClassLoader does not exist;" + // + " assuming this is JDK 1.1, and that the context" + // + " classloader is the same as the class that loaded" + // + " the concrete LogFactory class."); + // } + + } + + // Return the selected class loader + return classLoader; + } + + /** + * Check cached factories (keyed by contextClassLoader) + * + * @param contextClassLoader is the context classloader associated + * with the current thread. This allows separate LogFactory objects + * per component within a container, provided each component has + * a distinct context classloader set. This parameter may be null + * in JDK1.1, and in embedded systems where jcl-using code is + * placed in the bootclasspath. + * + * @return the factory associated with the specified classloader if + * one has previously been created, or null if this is the first time + * we have seen this particular classloader. + */ + private static LogFactory getCachedFactory(ClassLoader contextClassLoader) + { + LogFactory factory = null; + + if (contextClassLoader == null) { + // We have to handle this specially, as factories is a Hashtable + // and those don't accept null as a key value. + // + // nb: nullClassLoaderFactory might be null. That's ok. + factory = nullClassLoaderFactory; + } else { + factory = (LogFactory) factories.get(contextClassLoader); + } + + return factory; + } + + /** + * Remember this factory, so later calls to LogFactory.getCachedFactory + * can return the previously created object (together with all its + * cached Log objects). + * + * @param classLoader should be the current context classloader. Note that + * this can be null under some circumstances; this is ok. + * + * @param factory should be the factory to cache. This should never be null. + */ + private static void cacheFactory(ClassLoader classLoader, LogFactory factory) + { + // Ideally we would assert(factory != null) here. However reporting + // errors from within a logging implementation is a little tricky! + + if (factory != null) { + if (classLoader == null) { + nullClassLoaderFactory = factory; + } else { + factories.put(classLoader, factory); + } + } + } + + /** + * Return a new instance of the specified LogFactory + * implementation class, loaded by the specified class loader. + * If that fails, try the class loader used to load this + * (abstract) LogFactory. + *

    + *

    ClassLoader conflicts

    + * Note that there can be problems if the specified ClassLoader is not the + * same as the classloader that loaded this class, ie when loading a + * concrete LogFactory subclass via a context classloader. + *

    + * The problem is the same one that can occur when loading a concrete Log + * subclass via a context classloader. + *

    + * The problem occurs when code running in the context classloader calls + * class X which was loaded via a parent classloader, and class X then calls + * LogFactory.getFactory (either directly or via LogFactory.getLog). Because + * class X was loaded via the parent, it binds to LogFactory loaded via + * the parent. When the code in this method finds some LogFactoryYYYY + * class in the child (context) classloader, and there also happens to be a + * LogFactory class defined in the child classloader, then LogFactoryYYYY + * will be bound to LogFactory@childloader. It cannot be cast to + * LogFactory@parentloader, ie this method cannot return the object as + * the desired type. Note that it doesn't matter if the LogFactory class + * in the child classloader is identical to the LogFactory class in the + * parent classloader, they are not compatible. + *

    + * The solution taken here is to simply print out an error message when + * this occurs then throw an exception. The deployer of the application + * must ensure they remove all occurrences of the LogFactory class from + * the child classloader in order to resolve the issue. Note that they + * do not have to move the custom LogFactory subclass; that is ok as + * long as the only LogFactory class it can find to bind to is in the + * parent classloader. + *

    + * @param factoryClass Fully qualified name of the LogFactory + * implementation class + * @param classLoader ClassLoader from which to load this class + * @param contextClassLoader is the context that this new factory will + * manage logging for. + * + * @exception LogConfigurationException if a suitable instance + * cannot be created + * @since 1.1 + */ + protected static LogFactory newFactory(final String factoryClass, + final ClassLoader classLoader, + final ClassLoader contextClassLoader) + throws LogConfigurationException + { + // Note that any unchecked exceptions thrown by the createFactory + // method will propagate out of this method; in particular a + // ClassCastException can be thrown. + Object result = AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return createFactory(factoryClass, classLoader); + } + }); + + if (result instanceof LogConfigurationException) { + LogConfigurationException ex = (LogConfigurationException) result; + if (isDiagnosticsEnabled()) { + logDiagnostic( + "An error occurred while loading the factory class:" + + ex.getMessage()); + } + throw ex; + } + if (isDiagnosticsEnabled()) { + logDiagnostic( + "Created object " + objectId(result) + + " to manage classloader " + objectId(contextClassLoader)); + } + return (LogFactory)result; + } + + /** + * Method provided for backwards compatibility; see newFactory version that + * takes 3 parameters. + *

    + * This method would only ever be called in some rather odd situation. + * Note that this method is static, so overriding in a subclass doesn't + * have any effect unless this method is called from a method in that + * subclass. However this method only makes sense to use from the + * getFactory method, and as that is almost always invoked via + * LogFactory.getFactory, any custom definition in a subclass would be + * pointless. Only a class with a custom getFactory method, then invoked + * directly via CustomFactoryImpl.getFactory or similar would ever call + * this. Anyway, it's here just in case, though the "managed class loader" + * value output to the diagnostics will not report the correct value. + */ + protected static LogFactory newFactory(final String factoryClass, + final ClassLoader classLoader) { + return newFactory(factoryClass, classLoader, null); + } + + /** + * Implements the operations described in the javadoc for newFactory. + * + * @param factoryClass + * + * @param classLoader used to load the specified factory class. This is + * expected to be either the TCCL or the classloader which loaded this + * class. Note that the classloader which loaded this class might be + * "null" (ie the bootloader) for embedded systems. + * + * @return either a LogFactory object or a LogConfigurationException object. + * @since 1.1 + */ + protected static Object createFactory(String factoryClass, ClassLoader classLoader) { + + // This will be used to diagnose bad configurations + // and allow a useful message to be sent to the user + Class logFactoryClass = null; + try { + if (classLoader != null) { + try { + // First the given class loader param (thread class loader) + + // Warning: must typecast here & allow exception + // to be generated/caught & recast properly. + logFactoryClass = classLoader.loadClass(factoryClass); + if (LogFactory.class.isAssignableFrom(logFactoryClass)) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "Loaded class " + logFactoryClass.getName() + + " from classloader " + objectId(classLoader)); + } + } else { + // + // This indicates a problem with the ClassLoader tree. + // An incompatible ClassLoader was used to load the + // implementation. + // As the same classes + // must be available in multiple class loaders, + // it is very likely that multiple JCL jars are present. + // The most likely fix for this + // problem is to remove the extra JCL jars from the + // ClassLoader hierarchy. + // + if (isDiagnosticsEnabled()) { + logDiagnostic( + "Factory class " + logFactoryClass.getName() + + " loaded from classloader " + objectId(logFactoryClass.getClassLoader()) + + " does not extend '" + LogFactory.class.getName() + + "' as loaded by this classloader."); + logHierarchy("[BAD CL TREE] ", classLoader); + } + } + + return (LogFactory) logFactoryClass.newInstance(); + + } catch (ClassNotFoundException ex) { + if (classLoader == thisClassLoader) { + // Nothing more to try, onwards. + if (isDiagnosticsEnabled()) { + logDiagnostic( + "Unable to locate any class called '" + factoryClass + + "' via classloader " + objectId(classLoader)); + } + throw ex; + } + // ignore exception, continue + } catch (NoClassDefFoundError e) { + if (classLoader == thisClassLoader) { + // Nothing more to try, onwards. + if (isDiagnosticsEnabled()) { + logDiagnostic( + "Class '" + factoryClass + "' cannot be loaded" + + " via classloader " + objectId(classLoader) + + " - it depends on some other class that cannot" + + " be found."); + } + throw e; + } + // ignore exception, continue + } catch(ClassCastException e) { + if (classLoader == thisClassLoader) { + // There's no point in falling through to the code below that + // tries again with thisClassLoader, because we've just tried + // loading with that loader (not the TCCL). Just throw an + // appropriate exception here. + + final boolean implementsLogFactory = implementsLogFactory(logFactoryClass); + + // + // Construct a good message: users may not actual expect that a custom implementation + // has been specified. Several well known containers use this mechanism to adapt JCL + // to their native logging system. + // + String msg = + "The application has specified that a custom LogFactory implementation should be used but " + + "Class '" + factoryClass + "' cannot be converted to '" + + LogFactory.class.getName() + "'. "; + if (implementsLogFactory) { + msg = msg + "The conflict is caused by the presence of multiple LogFactory classes in incompatible classloaders. " + + "Background can be found in http://commons.apache.org/logging/tech.html. " + + "If you have not explicitly specified a custom LogFactory then it is likely that " + + "the container has set one without your knowledge. " + + "In this case, consider using the commons-logging-adapters.jar file or " + + "specifying the standard LogFactory from the command line. "; + } else { + msg = msg + "Please check the custom implementation. "; + } + msg = msg + "Help can be found @http://commons.apache.org/logging/troubleshooting.html."; + + if (isDiagnosticsEnabled()) { + logDiagnostic(msg); + } + + ClassCastException ex = new ClassCastException(msg); + throw ex; + } + + // Ignore exception, continue. Presumably the classloader was the + // TCCL; the code below will try to load the class via thisClassLoader. + // This will handle the case where the original calling class is in + // a shared classpath but the TCCL has a copy of LogFactory and the + // specified LogFactory implementation; we will fall back to using the + // LogFactory implementation from the same classloader as this class. + // + // Issue: this doesn't handle the reverse case, where this LogFactory + // is in the webapp, and the specified LogFactory implementation is + // in a shared classpath. In that case: + // (a) the class really does implement LogFactory (bad log msg above) + // (b) the fallback code will result in exactly the same problem. + } + } + + /* At this point, either classLoader == null, OR + * classLoader was unable to load factoryClass. + * + * In either case, we call Class.forName, which is equivalent + * to LogFactory.class.getClassLoader().load(name), ie we ignore + * the classloader parameter the caller passed, and fall back + * to trying the classloader associated with this class. See the + * javadoc for the newFactory method for more info on the + * consequences of this. + * + * Notes: + * * LogFactory.class.getClassLoader() may return 'null' + * if LogFactory is loaded by the bootstrap classloader. + */ + // Warning: must typecast here & allow exception + // to be generated/caught & recast properly. + if (isDiagnosticsEnabled()) { + logDiagnostic( + "Unable to load factory class via classloader " + + objectId(classLoader) + + " - trying the classloader associated with this LogFactory."); + } + logFactoryClass = Class.forName(factoryClass); + return (LogFactory) logFactoryClass.newInstance(); + } catch (Exception e) { + // Check to see if we've got a bad configuration + if (isDiagnosticsEnabled()) { + logDiagnostic("Unable to create LogFactory instance."); + } + if (logFactoryClass != null + && !LogFactory.class.isAssignableFrom(logFactoryClass)) { + + return new LogConfigurationException( + "The chosen LogFactory implementation does not extend LogFactory." + + " Please check your configuration.", + e); + } + return new LogConfigurationException(e); + } + } + + /** + * Determines whether the given class actually implements LogFactory. + * Diagnostic information is also logged. + *

    + * Usage: to diagnose whether a classloader conflict is the cause + * of incompatibility. The test used is whether the class is assignable from + * the LogFactory class loaded by the class's classloader. + * @param logFactoryClass Class which may implement LogFactory + * @return true if the logFactoryClass does extend + * LogFactory when that class is loaded via the same + * classloader that loaded the logFactoryClass. + */ + private static boolean implementsLogFactory(Class logFactoryClass) { + boolean implementsLogFactory = false; + if (logFactoryClass != null) { + try { + ClassLoader logFactoryClassLoader = logFactoryClass.getClassLoader(); + if (logFactoryClassLoader == null) { + logDiagnostic("[CUSTOM LOG FACTORY] was loaded by the boot classloader"); + } else { + logHierarchy("[CUSTOM LOG FACTORY] ", logFactoryClassLoader); + Class factoryFromCustomLoader + = Class.forName("org.apache.commons.logging.LogFactory", false, logFactoryClassLoader); + implementsLogFactory = factoryFromCustomLoader.isAssignableFrom(logFactoryClass); + if (implementsLogFactory) { + logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClass.getName() + + " implements LogFactory but was loaded by an incompatible classloader."); + } else { + logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClass.getName() + + " does not implement LogFactory."); + } + } + } catch (SecurityException e) { + // + // The application is running within a hostile security environment. + // This will make it very hard to diagnose issues with JCL. + // Consider running less securely whilst debugging this issue. + // + logDiagnostic("[CUSTOM LOG FACTORY] SecurityException thrown whilst trying to determine whether " + + "the compatibility was caused by a classloader conflict: " + + e.getMessage()); + } catch (LinkageError e) { + // + // This should be an unusual circumstance. + // LinkageError's usually indicate that a dependent class has incompatibly changed. + // Another possibility may be an exception thrown by an initializer. + // Time for a clean rebuild? + // + logDiagnostic("[CUSTOM LOG FACTORY] LinkageError thrown whilst trying to determine whether " + + "the compatibility was caused by a classloader conflict: " + + e.getMessage()); + } catch (ClassNotFoundException e) { + // + // LogFactory cannot be loaded by the classloader which loaded the custom factory implementation. + // The custom implementation is not viable until this is corrected. + // Ensure that the JCL jar and the custom class are available from the same classloader. + // Running with diagnostics on should give information about the classloaders used + // to load the custom factory. + // + logDiagnostic("[CUSTOM LOG FACTORY] LogFactory class cannot be loaded by classloader which loaded the " + + "custom LogFactory implementation. Is the custom factory in the right classloader?"); + } + } + return implementsLogFactory; + } + + /** + * Applets may run in an environment where accessing resources of a loader is + * a secure operation, but where the commons-logging library has explicitly + * been granted permission for that operation. In this case, we need to + * run the operation using an AccessController. + */ + private static InputStream getResourceAsStream(final ClassLoader loader, + final String name) + { + return (InputStream)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + if (loader != null) { + return loader.getResourceAsStream(name); + } else { + return ClassLoader.getSystemResourceAsStream(name); + } + } + }); + } + + /** + * Given a filename, return an enumeration of URLs pointing to + * all the occurrences of that filename in the classpath. + *

    + * This is just like ClassLoader.getResources except that the + * operation is done under an AccessController so that this method will + * succeed when this jarfile is privileged but the caller is not. + * This method must therefore remain private to avoid security issues. + *

    + * If no instances are found, an Enumeration is returned whose + * hasMoreElements method returns false (ie an "empty" enumeration). + * If resources could not be listed for some reason, null is returned. + */ + private static Enumeration getResources(final ClassLoader loader, + final String name) + { + PrivilegedAction action = + new PrivilegedAction() { + public Object run() { + try { + if (loader != null) { + return loader.getResources(name); + } else { + return ClassLoader.getSystemResources(name); + } + } catch(IOException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "Exception while trying to find configuration file " + + name + ":" + e.getMessage()); + } + return null; + } catch(NoSuchMethodError e) { + // we must be running on a 1.1 JVM which doesn't support + // ClassLoader.getSystemResources; just return null in + // this case. + return null; + } + } + }; + Object result = AccessController.doPrivileged(action); + return (Enumeration) result; + } + + /** + * Given a URL that refers to a .properties file, load that file. + * This is done under an AccessController so that this method will + * succeed when this jarfile is privileged but the caller is not. + * This method must therefore remain private to avoid security issues. + *

    + * Null is returned if the URL cannot be opened. + */ + private static Properties getProperties(final URL url) { + PrivilegedAction action = + new PrivilegedAction() { + public Object run() { + try { + InputStream stream = url.openStream(); + if (stream != null) { + Properties props = new Properties(); + props.load(stream); + stream.close(); + return props; + } + } catch(IOException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Unable to read URL " + url); + } + } + + return null; + } + }; + return (Properties) AccessController.doPrivileged(action); + } + + /** + * Locate a user-provided configuration file. + *

    + * The classpath of the specified classLoader (usually the context classloader) + * is searched for properties files of the specified name. If none is found, + * null is returned. If more than one is found, then the file with the greatest + * value for its PRIORITY property is returned. If multiple files have the + * same PRIORITY value then the first in the classpath is returned. + *

    + * This differs from the 1.0.x releases; those always use the first one found. + * However as the priority is a new field, this change is backwards compatible. + *

    + * The purpose of the priority field is to allow a webserver administrator to + * override logging settings in all webapps by placing a commons-logging.properties + * file in a shared classpath location with a priority > 0; this overrides any + * commons-logging.properties files without priorities which are in the + * webapps. Webapps can also use explicit priorities to override a configuration + * file in the shared classpath if needed. + */ + private static final Properties getConfigurationFile( + ClassLoader classLoader, String fileName) { + + Properties props = null; + double priority = 0.0; + URL propsUrl = null; + try { + Enumeration urls = getResources(classLoader, fileName); + + if (urls == null) { + return null; + } + + while (urls.hasMoreElements()) { + URL url = (URL) urls.nextElement(); + + Properties newProps = getProperties(url); + if (newProps != null) { + if (props == null) { + propsUrl = url; + props = newProps; + String priorityStr = props.getProperty(PRIORITY_KEY); + priority = 0.0; + if (priorityStr != null) { + priority = Double.parseDouble(priorityStr); + } + + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Properties file found at '" + url + "'" + + " with priority " + priority); + } + } else { + String newPriorityStr = newProps.getProperty(PRIORITY_KEY); + double newPriority = 0.0; + if (newPriorityStr != null) { + newPriority = Double.parseDouble(newPriorityStr); + } + + if (newPriority > priority) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Properties file at '" + url + "'" + + " with priority " + newPriority + + " overrides file at '" + propsUrl + "'" + + " with priority " + priority); + } + + propsUrl = url; + props = newProps; + priority = newPriority; + } else { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[LOOKUP] Properties file at '" + url + "'" + + " with priority " + newPriority + + " does not override file at '" + propsUrl + "'" + + " with priority " + priority); + } + } + } + + } + } + } catch (SecurityException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("SecurityException thrown while trying to find/read config files."); + } + } + + if (isDiagnosticsEnabled()) { + if (props == null) { + logDiagnostic( + "[LOOKUP] No properties file of name '" + fileName + + "' found."); + } else { + logDiagnostic( + "[LOOKUP] Properties file of name '" + fileName + + "' found at '" + propsUrl + '"'); + } + } + + return props; + } + + /** + * Read the specified system property, using an AccessController so that + * the property can be read if JCL has been granted the appropriate + * security rights even if the calling code has not. + *

    + * Take care not to expose the value returned by this method to the + * calling application in any way; otherwise the calling app can use that + * info to access data that should not be available to it. + */ + private static String getSystemProperty(final String key, final String def) + throws SecurityException { + return (String) AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return System.getProperty(key, def); + } + }); + } + + /** + * Determines whether the user wants internal diagnostic output. If so, + * returns an appropriate writer object. Users can enable diagnostic + * output by setting the system property named {@link #DIAGNOSTICS_DEST_PROPERTY} to + * a filename, or the special values STDOUT or STDERR. + */ + private static void initDiagnostics() { + String dest; + try { + dest = getSystemProperty(DIAGNOSTICS_DEST_PROPERTY, null); + if (dest == null) { + return; + } + } catch(SecurityException ex) { + // We must be running in some very secure environment. + // We just have to assume output is not wanted.. + return; + } + + if (dest.equals("STDOUT")) { + diagnosticsStream = System.out; + } else if (dest.equals("STDERR")) { + diagnosticsStream = System.err; + } else { + try { + // open the file in append mode + FileOutputStream fos = new FileOutputStream(dest, true); + diagnosticsStream = new PrintStream(fos); + } catch(IOException ex) { + // We should report this to the user - but how? + return; + } + } + + // In order to avoid confusion where multiple instances of JCL are + // being used via different classloaders within the same app, we + // ensure each logged message has a prefix of form + // [LogFactory from classloader OID] + // + // Note that this prefix should be kept consistent with that + // in LogFactoryImpl. However here we don't need to output info + // about the actual *instance* of LogFactory, as all methods that + // output diagnostics from this class are static. + String classLoaderName; + try { + ClassLoader classLoader = thisClassLoader; + if (thisClassLoader == null) { + classLoaderName = "BOOTLOADER"; + } else { + classLoaderName = objectId(classLoader); + } + } catch(SecurityException e) { + classLoaderName = "UNKNOWN"; + } + diagnosticPrefix = "[LogFactory from " + classLoaderName + "] "; + } + + /** + * Indicates true if the user has enabled internal logging. + *

    + * By the way, sorry for the incorrect grammar, but calling this method + * areDiagnosticsEnabled just isn't java beans style. + * + * @return true if calls to logDiagnostic will have any effect. + * @since 1.1 + */ + protected static boolean isDiagnosticsEnabled() { + return diagnosticsStream != null; + } + + /** + * Write the specified message to the internal logging destination. + *

    + * Note that this method is private; concrete subclasses of this class + * should not call it because the diagnosticPrefix string this + * method puts in front of all its messages is LogFactory@...., + * while subclasses should put SomeSubClass@... + *

    + * Subclasses should instead compute their own prefix, then call + * logRawDiagnostic. Note that calling isDiagnosticsEnabled is + * fine for subclasses. + *

    + * Note that it is safe to call this method before initDiagnostics + * is called; any output will just be ignored (as isDiagnosticsEnabled + * will return false). + * + * @param msg is the diagnostic message to be output. + */ + private static final void logDiagnostic(String msg) { + if (diagnosticsStream != null) { + diagnosticsStream.print(diagnosticPrefix); + diagnosticsStream.println(msg); + diagnosticsStream.flush(); + } + } + + /** + * Write the specified message to the internal logging destination. + * + * @param msg is the diagnostic message to be output. + * @since 1.1 + */ + protected static final void logRawDiagnostic(String msg) { + if (diagnosticsStream != null) { + diagnosticsStream.println(msg); + diagnosticsStream.flush(); + } + } + + /** + * Generate useful diagnostics regarding the classloader tree for + * the specified class. + *

    + * As an example, if the specified class was loaded via a webapp's + * classloader, then you may get the following output: + *

    +     * Class com.acme.Foo was loaded via classloader 11111
    +     * ClassLoader tree: 11111 -> 22222 (SYSTEM) -> 33333 -> BOOT 
    +     * 
    + *

    + * This method returns immediately if isDiagnosticsEnabled() + * returns false. + * + * @param clazz is the class whose classloader + tree are to be + * output. + */ + private static void logClassLoaderEnvironment(Class clazz) { + if (!isDiagnosticsEnabled()) { + return; + } + + try { + // Deliberately use System.getProperty here instead of getSystemProperty; if + // the overall security policy for the calling application forbids access to + // these variables then we do not want to output them to the diagnostic stream. + logDiagnostic("[ENV] Extension directories (java.ext.dir): " + System.getProperty("java.ext.dir")); + logDiagnostic("[ENV] Application classpath (java.class.path): " + System.getProperty("java.class.path")); + } catch(SecurityException ex) { + logDiagnostic("[ENV] Security setting prevent interrogation of system classpaths."); + } + + String className = clazz.getName(); + ClassLoader classLoader; + + try { + classLoader = getClassLoader(clazz); + } catch(SecurityException ex) { + // not much useful diagnostics we can print here! + logDiagnostic( + "[ENV] Security forbids determining the classloader for " + className); + return; + } + + logDiagnostic( + "[ENV] Class " + className + " was loaded via classloader " + + objectId(classLoader)); + logHierarchy("[ENV] Ancestry of classloader which loaded " + className + " is ", classLoader); + } + + /** + * Logs diagnostic messages about the given classloader + * and it's hierarchy. The prefix is prepended to the message + * and is intended to make it easier to understand the logs. + * @param prefix + * @param classLoader + */ + private static void logHierarchy(String prefix, ClassLoader classLoader) { + if (!isDiagnosticsEnabled()) { + return; + } + ClassLoader systemClassLoader; + if (classLoader != null) { + final String classLoaderString = classLoader.toString(); + logDiagnostic(prefix + objectId(classLoader) + " == '" + classLoaderString + "'"); + } + + try { + systemClassLoader = ClassLoader.getSystemClassLoader(); + } catch(SecurityException ex) { + logDiagnostic( + prefix + "Security forbids determining the system classloader."); + return; + } + if (classLoader != null) { + StringBuffer buf = new StringBuffer(prefix + "ClassLoader tree:"); + for(;;) { + buf.append(objectId(classLoader)); + if (classLoader == systemClassLoader) { + buf.append(" (SYSTEM) "); + } + + try { + classLoader = classLoader.getParent(); + } catch(SecurityException ex) { + buf.append(" --> SECRET"); + break; + } + + buf.append(" --> "); + if (classLoader == null) { + buf.append("BOOT"); + break; + } + } + logDiagnostic(buf.toString()); + } + } + + /** + * Returns a string that uniquely identifies the specified object, including + * its class. + *

    + * The returned string is of form "classname@hashcode", ie is the same as + * the return value of the Object.toString() method, but works even when + * the specified object's class has overidden the toString method. + * + * @param o may be null. + * @return a string of form classname@hashcode, or "null" if param o is null. + * @since 1.1 + */ + public static String objectId(Object o) { + if (o == null) { + return "null"; + } else { + return o.getClass().getName() + "@" + System.identityHashCode(o); + } + } + + // ---------------------------------------------------------------------- + // Static initialiser block to perform initialisation at class load time. + // + // We can't do this in the class constructor, as there are many + // static methods on this class that can be called before any + // LogFactory instances are created, and they depend upon this + // stuff having been set up. + // + // Note that this block must come after any variable declarations used + // by any methods called from this block, as we want any static initialiser + // associated with the variable to run first. If static initialisers for + // variables run after this code, then (a) their value might be needed + // by methods called from here, and (b) they might *override* any value + // computed here! + // + // So the wisest thing to do is just to place this code at the very end + // of the class file. + // ---------------------------------------------------------------------- + + static { + // note: it's safe to call methods before initDiagnostics (though + // diagnostic output gets discarded). + thisClassLoader = getClassLoader(LogFactory.class); + initDiagnostics(); + logClassLoaderEnvironment(LogFactory.class); + factories = createFactoryStore(); + if (isDiagnosticsEnabled()) { + logDiagnostic("BOOTSTRAP COMPLETED"); + } + } +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogSource.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogSource.java new file mode 100644 index 0000000..50b3e4b --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/LogSource.java @@ -0,0 +1,262 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging; + + +import java.lang.reflect.Constructor; +import java.util.Hashtable; + +import org.apache.commons.logging.impl.NoOpLog; + + +/** + *

    Factory for creating {@link Log} instances. Applications should call + * the makeNewLogInstance() method to instantiate new instances + * of the configured {@link Log} implementation class.

    + * + *

    By default, calling getInstance() will use the following + * algorithm:

    + *
      + *
    • If Log4J is available, return an instance of + * org.apache.commons.logging.impl.Log4JLogger.
    • + *
    • If JDK 1.4 or later is available, return an instance of + * org.apache.commons.logging.impl.Jdk14Logger.
    • + *
    • Otherwise, return an instance of + * org.apache.commons.logging.impl.NoOpLog.
    • + *
    + * + *

    You can change the default behavior in one of two ways:

    + *
      + *
    • On the startup command line, set the system property + * org.apache.commons.logging.log to the name of the + * org.apache.commons.logging.Log implementation class + * you want to use.
    • + *
    • At runtime, call LogSource.setLogImplementation().
    • + *
    + * + * @deprecated Use {@link LogFactory} instead - The default factory + * implementation performs exactly the same algorithm as this class did + * + * @author Rod Waldhoff + * @version $Id: LogSource.java 424107 2006-07-20 23:15:42Z skitching $ + */ +public class LogSource { + + // ------------------------------------------------------- Class Attributes + + static protected Hashtable logs = new Hashtable(); + + /** Is log4j available (in the current classpath) */ + static protected boolean log4jIsAvailable = false; + + /** Is JDK 1.4 logging available */ + static protected boolean jdk14IsAvailable = false; + + /** Constructor for current log class */ + static protected Constructor logImplctor = null; + + + // ----------------------------------------------------- Class Initializers + + static { + + // Is Log4J Available? + try { + if (null != Class.forName("org.apache.log4j.Logger")) { + log4jIsAvailable = true; + } else { + log4jIsAvailable = false; + } + } catch (Throwable t) { + log4jIsAvailable = false; + } + + // Is JDK 1.4 Logging Available? + try { + if ((null != Class.forName("java.util.logging.Logger")) && + (null != Class.forName("org.apache.commons.logging.impl.Jdk14Logger"))) { + jdk14IsAvailable = true; + } else { + jdk14IsAvailable = false; + } + } catch (Throwable t) { + jdk14IsAvailable = false; + } + + // Set the default Log implementation + String name = null; + try { + name = System.getProperty("org.apache.commons.logging.log"); + if (name == null) { + name = System.getProperty("org.apache.commons.logging.Log"); + } + } catch (Throwable t) { + } + if (name != null) { + try { + setLogImplementation(name); + } catch (Throwable t) { + try { + setLogImplementation + ("org.apache.commons.logging.impl.NoOpLog"); + } catch (Throwable u) { + ; + } + } + } else { + try { + if (log4jIsAvailable) { + setLogImplementation + ("org.apache.commons.logging.impl.Log4JLogger"); + } else if (jdk14IsAvailable) { + setLogImplementation + ("org.apache.commons.logging.impl.Jdk14Logger"); + } else { + setLogImplementation + ("org.apache.commons.logging.impl.NoOpLog"); + } + } catch (Throwable t) { + try { + setLogImplementation + ("org.apache.commons.logging.impl.NoOpLog"); + } catch (Throwable u) { + ; + } + } + } + + } + + + // ------------------------------------------------------------ Constructor + + + /** Don't allow others to create instances */ + private LogSource() { + } + + + // ---------------------------------------------------------- Class Methods + + + /** + * Set the log implementation/log implementation factory + * by the name of the class. The given class + * must implement {@link Log}, and provide a constructor that + * takes a single {@link String} argument (containing the name + * of the log). + */ + static public void setLogImplementation(String classname) throws + LinkageError, ExceptionInInitializerError, + NoSuchMethodException, SecurityException, + ClassNotFoundException { + try { + Class logclass = Class.forName(classname); + Class[] argtypes = new Class[1]; + argtypes[0] = "".getClass(); + logImplctor = logclass.getConstructor(argtypes); + } catch (Throwable t) { + logImplctor = null; + } + } + + + /** + * Set the log implementation/log implementation factory + * by class. The given class must implement {@link Log}, + * and provide a constructor that takes a single {@link String} + * argument (containing the name of the log). + */ + static public void setLogImplementation(Class logclass) throws + LinkageError, ExceptionInInitializerError, + NoSuchMethodException, SecurityException { + Class[] argtypes = new Class[1]; + argtypes[0] = "".getClass(); + logImplctor = logclass.getConstructor(argtypes); + } + + + /** Get a Log instance by class name */ + static public Log getInstance(String name) { + Log log = (Log) (logs.get(name)); + if (null == log) { + log = makeNewLogInstance(name); + logs.put(name, log); + } + return log; + } + + + /** Get a Log instance by class */ + static public Log getInstance(Class clazz) { + return getInstance(clazz.getName()); + } + + + /** + * Create a new {@link Log} implementation, based + * on the given name. + *

    + * The specific {@link Log} implementation returned + * is determined by the value of the + * org.apache.commons.logging.log property. + * The value of org.apache.commons.logging.log may be set to + * the fully specified name of a class that implements + * the {@link Log} interface. This class must also + * have a public constructor that takes a single + * {@link String} argument (containing the name + * of the {@link Log} to be constructed. + *

    + * When org.apache.commons.logging.log is not set, + * or when no corresponding class can be found, + * this method will return a Log4JLogger + * if the log4j Logger class is + * available in the {@link LogSource}'s classpath, or a + * Jdk14Logger if we are on a JDK 1.4 or later system, or + * NoOpLog if neither of the above conditions is true. + * + * @param name the log name (or category) + */ + static public Log makeNewLogInstance(String name) { + + Log log = null; + try { + Object[] args = new Object[1]; + args[0] = name; + log = (Log) (logImplctor.newInstance(args)); + } catch (Throwable t) { + log = null; + } + if (null == log) { + log = new NoOpLog(name); + } + return log; + + } + + + /** + * Returns a {@link String} array containing the names of + * all logs known to me. + */ + static public String[] getLogNames() { + return (String[]) (logs.keySet().toArray(new String[logs.size()])); + } + + +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/AvalonLogger.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/AvalonLogger.java new file mode 100644 index 0000000..2500172 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/AvalonLogger.java @@ -0,0 +1,292 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + +import org.apache.avalon.framework.logger.Logger; +import org.apache.commons.logging.Log; + +/** + *

    Implementation of commons-logging Log interface that delegates all + * logging calls to the Avalon logging abstraction: the Logger interface. + *

    + *

    + * There are two ways in which this class can be used: + *

    + *
      + *
    • the instance can be constructed with an Avalon logger + * (by calling {@link #AvalonLogger(Logger)}). In this case, it acts + * as a simple thin wrapping implementation over the logger. This is + * particularly useful when using a property setter. + *
    • + *
    • the {@link #setDefaultLogger} class property can be called which + * sets the ancesteral Avalon logger for this class. Any AvalonLogger + * instances created through the LogFactory mechanisms will output + * to child loggers of this Logger. + *
    • + *
    + *

    + * Note: AvalonLogger does not implement Serializable + * because the constructors available for it make this impossible to achieve in all + * circumstances; there is no way to "reconnect" to an underlying Logger object on + * deserialization if one was just passed in to the constructor of the original + * object. This class was marked Serializable in the 1.0.4 release of + * commons-logging, but this never actually worked (a NullPointerException would + * be thrown as soon as the deserialized object was used), so removing this marker + * is not considered to be an incompatible change. + *

    + * @author Neeme Praks + * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ + */ +public class AvalonLogger implements Log { + + /** Ancesteral avalon logger */ + private static Logger defaultLogger = null; + /** Avalon logger used to perform log */ + private transient Logger logger = null; + + /** + * Constructs an AvalonLogger that outputs to the given + * Logger instance. + * @param logger the avalon logger implementation to delegate to + */ + public AvalonLogger(Logger logger) { + this.logger = logger; + } + + /** + * Constructs an AvalonLogger that will log to a child + * of the Logger set by calling {@link #setDefaultLogger}. + * @param name the name of the avalon logger implementation to delegate to + */ + public AvalonLogger(String name) { + if (defaultLogger == null) + throw new NullPointerException("default logger has to be specified if this constructor is used!"); + this.logger = defaultLogger.getChildLogger(name); + } + + /** + * Gets the Avalon logger implementation used to perform logging. + * @return avalon logger implementation + */ + public Logger getLogger() { + return logger; + } + + /** + * Sets the ancesteral Avalon logger from which the delegating loggers + * will descend. + * @param logger the default avalon logger, + * in case there is no logger instance supplied in constructor + */ + public static void setDefaultLogger(Logger logger) { + defaultLogger = logger; + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.debug. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public void debug(Object message, Throwable t) { + if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message), t); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.debug. + * + * @param message to log. + * @see org.apache.commons.logging.Log#debug(Object) + */ + public void debug(Object message) { + if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message)); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.error. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public void error(Object message, Throwable t) { + if (getLogger().isErrorEnabled()) getLogger().error(String.valueOf(message), t); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.error. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public void error(Object message) { + if (getLogger().isErrorEnabled()) getLogger().error(String.valueOf(message)); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.fatalError. + * + * @param message to log. + * @param t log this cause. + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public void fatal(Object message, Throwable t) { + if (getLogger().isFatalErrorEnabled()) getLogger().fatalError(String.valueOf(message), t); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.fatalError. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public void fatal(Object message) { + if (getLogger().isFatalErrorEnabled()) getLogger().fatalError(String.valueOf(message)); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.info. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public void info(Object message, Throwable t) { + if (getLogger().isInfoEnabled()) getLogger().info(String.valueOf(message), t); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.info. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public void info(Object message) { + if (getLogger().isInfoEnabled()) getLogger().info(String.valueOf(message)); + } + + /** + * Is logging to + * org.apache.avalon.framework.logger.Logger.debug enabled? + * @see org.apache.commons.logging.Log#isDebugEnabled() + */ + public boolean isDebugEnabled() { + return getLogger().isDebugEnabled(); + } + + /** + * Is logging to + * org.apache.avalon.framework.logger.Logger.error enabled? + * @see org.apache.commons.logging.Log#isErrorEnabled() + */ + public boolean isErrorEnabled() { + return getLogger().isErrorEnabled(); + } + + /** + * Is logging to + * org.apache.avalon.framework.logger.Logger.fatalError enabled? + * @see org.apache.commons.logging.Log#isFatalEnabled() + */ + public boolean isFatalEnabled() { + return getLogger().isFatalErrorEnabled(); + } + + /** + * Is logging to + * org.apache.avalon.framework.logger.Logger.info enabled? + * @see org.apache.commons.logging.Log#isInfoEnabled() + */ + public boolean isInfoEnabled() { + return getLogger().isInfoEnabled(); + } + + /** + * Is logging to + * org.apache.avalon.framework.logger.Logger.debug enabled? + * @see org.apache.commons.logging.Log#isTraceEnabled() + */ + public boolean isTraceEnabled() { + return getLogger().isDebugEnabled(); + } + + /** + * Is logging to + * org.apache.avalon.framework.logger.Logger.warn enabled? + * @see org.apache.commons.logging.Log#isWarnEnabled() + */ + public boolean isWarnEnabled() { + return getLogger().isWarnEnabled(); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.debug. + * + * @param message to log. + * @param t log this cause. + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public void trace(Object message, Throwable t) { + if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message), t); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.debug. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public void trace(Object message) { + if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message)); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.warn. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public void warn(Object message, Throwable t) { + if (getLogger().isWarnEnabled()) getLogger().warn(String.valueOf(message), t); + } + + /** + * Logs a message with + * org.apache.avalon.framework.logger.Logger.warn. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public void warn(Object message) { + if (getLogger().isWarnEnabled()) getLogger().warn(String.valueOf(message)); + } + +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java new file mode 100644 index 0000000..fb17d26 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java @@ -0,0 +1,335 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging.impl; + + +import java.io.Serializable; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.LogRecord; +import java.util.StringTokenizer; +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.commons.logging.Log; + + +/** + *

    Implementation of the org.apache.commons.logging.Log + * interface that wraps the standard JDK logging mechanisms that are + * available in SourceForge's Lumberjack for JDKs prior to 1.4.

    + * + * @author Scott Sanders + * @author Berin Loritsch + * @author Peter Donald + * @author Vince Eagen + * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ + * @since 1.1 + */ + +public class Jdk13LumberjackLogger implements Log, Serializable { + + + // ----------------------------------------------------- Instance Variables + + + /** + * The underlying Logger implementation we are using. + */ + protected transient Logger logger = null; + protected String name = null; + private String sourceClassName = "unknown"; + private String sourceMethodName = "unknown"; + private boolean classAndMethodFound = false; + + + /** + * This member variable simply ensures that any attempt to initialise + * this class in a pre-1.4 JVM will result in an ExceptionInInitializerError. + * It must not be private, as an optimising compiler could detect that it + * is not used and optimise it away. + */ + protected static final Level dummyLevel = Level.FINE; + + // ----------------------------------------------------------- Constructors + + + /** + * Construct a named instance of this Logger. + * + * @param name Name of the logger to be constructed + */ + public Jdk13LumberjackLogger(String name) { + + this.name = name; + logger = getLogger(); + + } + + + // --------------------------------------------------------- Public Methods + + + private void log( Level level, String msg, Throwable ex ) { + if( getLogger().isLoggable(level) ) { + LogRecord record = new LogRecord(level, msg); + if( !classAndMethodFound ) { + getClassAndMethod(); + } + record.setSourceClassName(sourceClassName); + record.setSourceMethodName(sourceMethodName); + if( ex != null ) { + record.setThrown(ex); + } + getLogger().log(record); + } + } + + /** + *

    Gets the class and method by looking at the stack trace for the + * first entry that is not this class.

    + */ + private void getClassAndMethod() { + try { + Throwable throwable = new Throwable(); + throwable.fillInStackTrace(); + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter( stringWriter ); + throwable.printStackTrace( printWriter ); + String traceString = stringWriter.getBuffer().toString(); + StringTokenizer tokenizer = + new StringTokenizer( traceString, "\n" ); + tokenizer.nextToken(); + String line = tokenizer.nextToken(); + while ( line.indexOf( this.getClass().getName() ) == -1 ) { + line = tokenizer.nextToken(); + } + while ( line.indexOf( this.getClass().getName() ) >= 0 ) { + line = tokenizer.nextToken(); + } + int start = line.indexOf( "at " ) + 3; + int end = line.indexOf( '(' ); + String temp = line.substring( start, end ); + int lastPeriod = temp.lastIndexOf( '.' ); + sourceClassName = temp.substring( 0, lastPeriod ); + sourceMethodName = temp.substring( lastPeriod + 1 ); + } catch ( Exception ex ) { + // ignore - leave class and methodname unknown + } + classAndMethodFound = true; + } + + /** + * Logs a message with java.util.logging.Level.FINE. + * + * @param message to log + * @see org.apache.commons.logging.Log#debug(Object) + */ + public void debug(Object message) { + log(Level.FINE, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.FINE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public void debug(Object message, Throwable exception) { + log(Level.FINE, String.valueOf(message), exception); + } + + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public void error(Object message) { + log(Level.SEVERE, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public void error(Object message, Throwable exception) { + log(Level.SEVERE, String.valueOf(message), exception); + } + + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public void fatal(Object message) { + log(Level.SEVERE, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public void fatal(Object message, Throwable exception) { + log(Level.SEVERE, String.valueOf(message), exception); + } + + + /** + * Return the native Logger instance we are using. + */ + public Logger getLogger() { + if (logger == null) { + logger = Logger.getLogger(name); + } + return (logger); + } + + + /** + * Logs a message with java.util.logging.Level.INFO. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public void info(Object message) { + log(Level.INFO, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.INFO. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public void info(Object message, Throwable exception) { + log(Level.INFO, String.valueOf(message), exception); + } + + + /** + * Is debug logging currently enabled? + */ + public boolean isDebugEnabled() { + return (getLogger().isLoggable(Level.FINE)); + } + + + /** + * Is error logging currently enabled? + */ + public boolean isErrorEnabled() { + return (getLogger().isLoggable(Level.SEVERE)); + } + + + /** + * Is fatal logging currently enabled? + */ + public boolean isFatalEnabled() { + return (getLogger().isLoggable(Level.SEVERE)); + } + + + /** + * Is info logging currently enabled? + */ + public boolean isInfoEnabled() { + return (getLogger().isLoggable(Level.INFO)); + } + + + /** + * Is trace logging currently enabled? + */ + public boolean isTraceEnabled() { + return (getLogger().isLoggable(Level.FINEST)); + } + + + /** + * Is warn logging currently enabled? + */ + public boolean isWarnEnabled() { + return (getLogger().isLoggable(Level.WARNING)); + } + + + /** + * Logs a message with java.util.logging.Level.FINEST. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public void trace(Object message) { + log(Level.FINEST, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.FINEST. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public void trace(Object message, Throwable exception) { + log(Level.FINEST, String.valueOf(message), exception); + } + + + /** + * Logs a message with java.util.logging.Level.WARNING. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public void warn(Object message) { + log(Level.WARNING, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.WARNING. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public void warn(Object message, Throwable exception) { + log(Level.WARNING, String.valueOf(message), exception); + } + + +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Jdk14Logger.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Jdk14Logger.java new file mode 100644 index 0000000..9fafefd --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Jdk14Logger.java @@ -0,0 +1,304 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging.impl; + + +import java.io.Serializable; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.commons.logging.Log; + + +/** + *

    Implementation of the org.apache.commons.logging.Log + * interface that wraps the standard JDK logging mechanisms that were + * introduced in the Merlin release (JDK 1.4).

    + * + * @author Scott Sanders + * @author Berin Loritsch + * @author Peter Donald + * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ + */ + +public class Jdk14Logger implements Log, Serializable { + + /** + * This member variable simply ensures that any attempt to initialise + * this class in a pre-1.4 JVM will result in an ExceptionInInitializerError. + * It must not be private, as an optimising compiler could detect that it + * is not used and optimise it away. + */ + protected static final Level dummyLevel = Level.FINE; + + // ----------------------------------------------------------- Constructors + + + /** + * Construct a named instance of this Logger. + * + * @param name Name of the logger to be constructed + */ + public Jdk14Logger(String name) { + + this.name = name; + logger = getLogger(); + + } + + + // ----------------------------------------------------- Instance Variables + + + /** + * The underlying Logger implementation we are using. + */ + protected transient Logger logger = null; + + + /** + * The name of the logger we are wrapping. + */ + protected String name = null; + + + // --------------------------------------------------------- Public Methods + + private void log( Level level, String msg, Throwable ex ) { + + Logger logger = getLogger(); + if (logger.isLoggable(level)) { + // Hack (?) to get the stack trace. + Throwable dummyException=new Throwable(); + StackTraceElement locations[]=dummyException.getStackTrace(); + // Caller will be the third element + String cname="unknown"; + String method="unknown"; + if( locations!=null && locations.length >2 ) { + StackTraceElement caller=locations[2]; + cname=caller.getClassName(); + method=caller.getMethodName(); + } + if( ex==null ) { + logger.logp( level, cname, method, msg ); + } else { + logger.logp( level, cname, method, msg, ex ); + } + } + + } + + /** + * Logs a message with java.util.logging.Level.FINE. + * + * @param message to log + * @see org.apache.commons.logging.Log#debug(Object) + */ + public void debug(Object message) { + log(Level.FINE, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.FINE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public void debug(Object message, Throwable exception) { + log(Level.FINE, String.valueOf(message), exception); + } + + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public void error(Object message) { + log(Level.SEVERE, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public void error(Object message, Throwable exception) { + log(Level.SEVERE, String.valueOf(message), exception); + } + + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public void fatal(Object message) { + log(Level.SEVERE, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.SEVERE. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public void fatal(Object message, Throwable exception) { + log(Level.SEVERE, String.valueOf(message), exception); + } + + + /** + * Return the native Logger instance we are using. + */ + public Logger getLogger() { + if (logger == null) { + logger = Logger.getLogger(name); + } + return (logger); + } + + + /** + * Logs a message with java.util.logging.Level.INFO. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public void info(Object message) { + log(Level.INFO, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.INFO. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public void info(Object message, Throwable exception) { + log(Level.INFO, String.valueOf(message), exception); + } + + + /** + * Is debug logging currently enabled? + */ + public boolean isDebugEnabled() { + return (getLogger().isLoggable(Level.FINE)); + } + + + /** + * Is error logging currently enabled? + */ + public boolean isErrorEnabled() { + return (getLogger().isLoggable(Level.SEVERE)); + } + + + /** + * Is fatal logging currently enabled? + */ + public boolean isFatalEnabled() { + return (getLogger().isLoggable(Level.SEVERE)); + } + + + /** + * Is info logging currently enabled? + */ + public boolean isInfoEnabled() { + return (getLogger().isLoggable(Level.INFO)); + } + + + /** + * Is trace logging currently enabled? + */ + public boolean isTraceEnabled() { + return (getLogger().isLoggable(Level.FINEST)); + } + + + /** + * Is warn logging currently enabled? + */ + public boolean isWarnEnabled() { + return (getLogger().isLoggable(Level.WARNING)); + } + + + /** + * Logs a message with java.util.logging.Level.FINEST. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public void trace(Object message) { + log(Level.FINEST, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.FINEST. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public void trace(Object message, Throwable exception) { + log(Level.FINEST, String.valueOf(message), exception); + } + + + /** + * Logs a message with java.util.logging.Level.WARNING. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public void warn(Object message) { + log(Level.WARNING, String.valueOf(message), null); + } + + + /** + * Logs a message with java.util.logging.Level.WARNING. + * + * @param message to log + * @param exception log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public void warn(Object message, Throwable exception) { + log(Level.WARNING, String.valueOf(message), exception); + } + + +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Log4JLogger.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Log4JLogger.java new file mode 100644 index 0000000..68877b9 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/Log4JLogger.java @@ -0,0 +1,342 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging.impl; + +import java.io.Serializable; +import org.apache.commons.logging.Log; +import org.apache.log4j.Logger; +import org.apache.log4j.Priority; +import org.apache.log4j.Level; + +/** + * Implementation of {@link Log} that maps directly to a + * Logger for log4J version 1.2. + *

    + * Initial configuration of the corresponding Logger instances should be done + * in the usual manner, as outlined in the Log4J documentation. + *

    + * The reason this logger is distinct from the 1.3 logger is that in version 1.2 + * of Log4J: + *

      + *
    • class Logger takes Priority parameters not Level parameters. + *
    • class Level extends Priority + *
    + * Log4J1.3 is expected to change Level so it no longer extends Priority, which is + * a non-binary-compatible change. The class generated by compiling this code against + * log4j 1.2 will therefore not run against log4j 1.3. + * + * @author Scott Sanders + * @author Rod Waldhoff + * @author Robert Burrell Donkin + * @version $Id: Log4JLogger.java 479747 2006-11-27 20:15:01Z dennisl $ + */ + +public class Log4JLogger implements Log, Serializable { + + // ------------------------------------------------------------- Attributes + + /** The fully qualified name of the Log4JLogger class. */ + private static final String FQCN = Log4JLogger.class.getName(); + + /** Log to this logger */ + private transient Logger logger = null; + + /** Logger name */ + private String name = null; + + private static Priority traceLevel; + + // ------------------------------------------------------------ + // Static Initializer. + // + // Note that this must come after the static variable declarations + // otherwise initialiser expressions associated with those variables + // will override any settings done here. + // + // Verify that log4j is available, and that it is version 1.2. + // If an ExceptionInInitializerError is generated, then LogFactoryImpl + // will treat that as meaning that the appropriate underlying logging + // library is just not present - if discovery is in progress then + // discovery will continue. + // ------------------------------------------------------------ + + static { + if (!Priority.class.isAssignableFrom(Level.class)) { + // nope, this is log4j 1.3, so force an ExceptionInInitializerError + throw new InstantiationError("Log4J 1.2 not available"); + } + + // Releases of log4j1.2 >= 1.2.12 have Priority.TRACE available, earlier + // versions do not. If TRACE is not available, then we have to map + // calls to Log.trace(...) onto the DEBUG level. + + try { + traceLevel = (Priority) Level.class.getDeclaredField("TRACE").get(null); + } catch(Exception ex) { + // ok, trace not available + traceLevel = Priority.DEBUG; + } + } + + + // ------------------------------------------------------------ Constructor + + public Log4JLogger() { + } + + + /** + * Base constructor. + */ + public Log4JLogger(String name) { + this.name = name; + this.logger = getLogger(); + } + + /** + * For use with a log4j factory. + */ + public Log4JLogger(Logger logger ) { + if (logger == null) { + throw new IllegalArgumentException( + "Warning - null logger in constructor; possible log4j misconfiguration."); + } + this.name = logger.getName(); + this.logger=logger; + } + + + // --------------------------------------------------------- + // Implementation + // + // Note that in the methods below the Priority class is used to define + // levels even though the Level class is supported in 1.2. This is done + // so that at compile time the call definitely resolves to a call to + // a method that takes a Priority rather than one that takes a Level. + // + // The Category class (and hence its subclass Logger) in version 1.2 only + // has methods that take Priority objects. The Category class (and hence + // Logger class) in version 1.3 has methods that take both Priority and + // Level objects. This means that if we use Level here, and compile + // against log4j 1.3 then calls would be bound to the versions of + // methods taking Level objects and then would fail to run against + // version 1.2 of log4j. + // --------------------------------------------------------- + + + /** + * Logs a message with org.apache.log4j.Priority.TRACE. + * When using a log4j version that does not support the TRACE + * level, the message will be logged at the DEBUG level. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public void trace(Object message) { + getLogger().log(FQCN, traceLevel, message, null ); + } + + + /** + * Logs a message with org.apache.log4j.Priority.TRACE. + * When using a log4j version that does not support the TRACE + * level, the message will be logged at the DEBUG level. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public void trace(Object message, Throwable t) { + getLogger().log(FQCN, traceLevel, message, t ); + } + + + /** + * Logs a message with org.apache.log4j.Priority.DEBUG. + * + * @param message to log + * @see org.apache.commons.logging.Log#debug(Object) + */ + public void debug(Object message) { + getLogger().log(FQCN, Priority.DEBUG, message, null ); + } + + /** + * Logs a message with org.apache.log4j.Priority.DEBUG. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public void debug(Object message, Throwable t) { + getLogger().log(FQCN, Priority.DEBUG, message, t ); + } + + + /** + * Logs a message with org.apache.log4j.Priority.INFO. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public void info(Object message) { + getLogger().log(FQCN, Priority.INFO, message, null ); + } + + + /** + * Logs a message with org.apache.log4j.Priority.INFO. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public void info(Object message, Throwable t) { + getLogger().log(FQCN, Priority.INFO, message, t ); + } + + + /** + * Logs a message with org.apache.log4j.Priority.WARN. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public void warn(Object message) { + getLogger().log(FQCN, Priority.WARN, message, null ); + } + + + /** + * Logs a message with org.apache.log4j.Priority.WARN. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public void warn(Object message, Throwable t) { + getLogger().log(FQCN, Priority.WARN, message, t ); + } + + + /** + * Logs a message with org.apache.log4j.Priority.ERROR. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public void error(Object message) { + getLogger().log(FQCN, Priority.ERROR, message, null ); + } + + + /** + * Logs a message with org.apache.log4j.Priority.ERROR. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public void error(Object message, Throwable t) { + getLogger().log(FQCN, Priority.ERROR, message, t ); + } + + + /** + * Logs a message with org.apache.log4j.Priority.FATAL. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public void fatal(Object message) { + getLogger().log(FQCN, Priority.FATAL, message, null ); + } + + + /** + * Logs a message with org.apache.log4j.Priority.FATAL. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public void fatal(Object message, Throwable t) { + getLogger().log(FQCN, Priority.FATAL, message, t ); + } + + + /** + * Return the native Logger instance we are using. + */ + public Logger getLogger() { + if (logger == null) { + logger = Logger.getLogger(name); + } + return (this.logger); + } + + + /** + * Check whether the Log4j Logger used is enabled for DEBUG priority. + */ + public boolean isDebugEnabled() { + return getLogger().isDebugEnabled(); + } + + + /** + * Check whether the Log4j Logger used is enabled for ERROR priority. + */ + public boolean isErrorEnabled() { + return getLogger().isEnabledFor(Priority.ERROR); + } + + + /** + * Check whether the Log4j Logger used is enabled for FATAL priority. + */ + public boolean isFatalEnabled() { + return getLogger().isEnabledFor(Priority.FATAL); + } + + + /** + * Check whether the Log4j Logger used is enabled for INFO priority. + */ + public boolean isInfoEnabled() { + return getLogger().isInfoEnabled(); + } + + + /** + * Check whether the Log4j Logger used is enabled for TRACE priority. + * When using a log4j version that does not support the TRACE level, this call + * will report whether DEBUG is enabled or not. + */ + public boolean isTraceEnabled() { + return getLogger().isEnabledFor(traceLevel); + } + + /** + * Check whether the Log4j Logger used is enabled for WARN priority. + */ + public boolean isWarnEnabled() { + return getLogger().isEnabledFor(Priority.WARN); + } +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/LogFactoryImpl.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/LogFactoryImpl.java new file mode 100644 index 0000000..97a9ac0 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/LogFactoryImpl.java @@ -0,0 +1,1500 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.logging.impl; + + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogConfigurationException; +import org.apache.commons.logging.LogFactory; + + +/** + *

    Concrete subclass of {@link LogFactory} that implements the + * following algorithm to dynamically select a logging implementation + * class to instantiate a wrapper for.

    + *
      + *
    • Use a factory configuration attribute named + * org.apache.commons.logging.Log to identify the + * requested implementation class.
    • + *
    • Use the org.apache.commons.logging.Log system property + * to identify the requested implementation class.
    • + *
    • If Log4J is available, return an instance of + * org.apache.commons.logging.impl.Log4JLogger.
    • + *
    • If JDK 1.4 or later is available, return an instance of + * org.apache.commons.logging.impl.Jdk14Logger.
    • + *
    • Otherwise, return an instance of + * org.apache.commons.logging.impl.SimpleLog.
    • + *
    + * + *

    If the selected {@link Log} implementation class has a + * setLogFactory() method that accepts a {@link LogFactory} + * parameter, this method will be called on each newly created instance + * to identify the associated factory. This makes factory configuration + * attributes available to the Log instance, if it so desires.

    + * + *

    This factory will remember previously created Log instances + * for the same name, and will return them on repeated requests to the + * getInstance() method.

    + * + * @author Rod Waldhoff + * @author Craig R. McClanahan + * @author Richard A. Sitze + * @author Brian Stansberry + * @version $Revision: 581090 $ $Date: 2007-10-02 00:01:06 +0200 (ti, 02 okt 2007) $ + */ + +public class LogFactoryImpl extends LogFactory { + + + /** Log4JLogger class name */ + private static final String LOGGING_IMPL_LOG4J_LOGGER = "org.apache.commons.logging.impl.Log4JLogger"; + /** Jdk14Logger class name */ + private static final String LOGGING_IMPL_JDK14_LOGGER = "org.apache.commons.logging.impl.Jdk14Logger"; + /** Jdk13LumberjackLogger class name */ + private static final String LOGGING_IMPL_LUMBERJACK_LOGGER = "org.apache.commons.logging.impl.Jdk13LumberjackLogger"; + /** SimpleLog class name */ + private static final String LOGGING_IMPL_SIMPLE_LOGGER = "org.apache.commons.logging.impl.SimpleLog"; + + private static final String PKG_IMPL="org.apache.commons.logging.impl."; + private static final int PKG_LEN = PKG_IMPL.length(); + + // ----------------------------------------------------------- Constructors + + + + /** + * Public no-arguments constructor required by the lookup mechanism. + */ + public LogFactoryImpl() { + super(); + initDiagnostics(); // method on this object + if (isDiagnosticsEnabled()) { + logDiagnostic("Instance created."); + } + } + + + // ----------------------------------------------------- Manifest Constants + + + /** + * The name (org.apache.commons.logging.Log) of the system + * property identifying our {@link Log} implementation class. + */ + public static final String LOG_PROPERTY = + "org.apache.commons.logging.Log"; + + + /** + * The deprecated system property used for backwards compatibility with + * old versions of JCL. + */ + protected static final String LOG_PROPERTY_OLD = + "org.apache.commons.logging.log"; + + /** + * The name (org.apache.commons.logging.Log.allowFlawedContext) + * of the system property which can be set true/false to + * determine system behaviour when a bad context-classloader is encountered. + * When set to false, a LogConfigurationException is thrown if + * LogFactoryImpl is loaded via a child classloader of the TCCL (this + * should never happen in sane systems). + * + * Default behaviour: true (tolerates bad context classloaders) + * + * See also method setAttribute. + */ + public static final String ALLOW_FLAWED_CONTEXT_PROPERTY = + "org.apache.commons.logging.Log.allowFlawedContext"; + + /** + * The name (org.apache.commons.logging.Log.allowFlawedDiscovery) + * of the system property which can be set true/false to + * determine system behaviour when a bad logging adapter class is + * encountered during logging discovery. When set to false, an + * exception will be thrown and the app will fail to start. When set + * to true, discovery will continue (though the user might end up + * with a different logging implementation than they expected). + * + * Default behaviour: true (tolerates bad logging adapters) + * + * See also method setAttribute. + */ + public static final String ALLOW_FLAWED_DISCOVERY_PROPERTY = + "org.apache.commons.logging.Log.allowFlawedDiscovery"; + + /** + * The name (org.apache.commons.logging.Log.allowFlawedHierarchy) + * of the system property which can be set true/false to + * determine system behaviour when a logging adapter class is + * encountered which has bound to the wrong Log class implementation. + * When set to false, an exception will be thrown and the app will fail + * to start. When set to true, discovery will continue (though the user + * might end up with a different logging implementation than they expected). + * + * Default behaviour: true (tolerates bad Log class hierarchy) + * + * See also method setAttribute. + */ + public static final String ALLOW_FLAWED_HIERARCHY_PROPERTY = + "org.apache.commons.logging.Log.allowFlawedHierarchy"; + + + /** + * The names of classes that will be tried (in order) as logging + * adapters. Each class is expected to implement the Log interface, + * and to throw NoClassDefFound or ExceptionInInitializerError when + * loaded if the underlying logging library is not available. Any + * other error indicates that the underlying logging library is available + * but broken/unusable for some reason. + */ + private static final String[] classesToDiscover = { + LOGGING_IMPL_LOG4J_LOGGER, + "org.apache.commons.logging.impl.Jdk14Logger", + "org.apache.commons.logging.impl.Jdk13LumberjackLogger", + "org.apache.commons.logging.impl.SimpleLog" + }; + + + // ----------------------------------------------------- Instance Variables + + /** + * Determines whether logging classes should be loaded using the thread-context + * classloader, or via the classloader that loaded this LogFactoryImpl class. + */ + private boolean useTCCL = true; + + /** + * The string prefixed to every message output by the logDiagnostic method. + */ + private String diagnosticPrefix; + + + /** + * Configuration attributes. + */ + protected Hashtable attributes = new Hashtable(); + + + /** + * The {@link org.apache.commons.logging.Log} instances that have + * already been created, keyed by logger name. + */ + protected Hashtable instances = new Hashtable(); + + + /** + * Name of the class implementing the Log interface. + */ + private String logClassName; + + + /** + * The one-argument constructor of the + * {@link org.apache.commons.logging.Log} + * implementation class that will be used to create new instances. + * This value is initialized by getLogConstructor(), + * and then returned repeatedly. + */ + protected Constructor logConstructor = null; + + + /** + * The signature of the Constructor to be used. + */ + protected Class logConstructorSignature[] = + { java.lang.String.class }; + + + /** + * The one-argument setLogFactory method of the selected + * {@link org.apache.commons.logging.Log} method, if it exists. + */ + protected Method logMethod = null; + + + /** + * The signature of the setLogFactory method to be used. + */ + protected Class logMethodSignature[] = + { LogFactory.class }; + + /** + * See getBaseClassLoader and initConfiguration. + */ + private boolean allowFlawedContext; + + /** + * See handleFlawedDiscovery and initConfiguration. + */ + private boolean allowFlawedDiscovery; + + /** + * See handleFlawedHierarchy and initConfiguration. + */ + private boolean allowFlawedHierarchy; + + // --------------------------------------------------------- Public Methods + + + /** + * Return the configuration attribute with the specified name (if any), + * or null if there is no such attribute. + * + * @param name Name of the attribute to return + */ + public Object getAttribute(String name) { + + return (attributes.get(name)); + + } + + + /** + * Return an array containing the names of all currently defined + * configuration attributes. If there are no such attributes, a zero + * length array is returned. + */ + public String[] getAttributeNames() { + + Vector names = new Vector(); + Enumeration keys = attributes.keys(); + while (keys.hasMoreElements()) { + names.addElement((String) keys.nextElement()); + } + String results[] = new String[names.size()]; + for (int i = 0; i < results.length; i++) { + results[i] = (String) names.elementAt(i); + } + return (results); + + } + + + /** + * Convenience method to derive a name from the specified class and + * call getInstance(String) with it. + * + * @param clazz Class for which a suitable Log name will be derived + * + * @exception LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public Log getInstance(Class clazz) throws LogConfigurationException { + + return (getInstance(clazz.getName())); + + } + + + /** + *

    Construct (if necessary) and return a Log instance, + * using the factory's current set of configuration attributes.

    + * + *

    NOTE - Depending upon the implementation of + * the LogFactory you are using, the Log + * instance you are returned may or may not be local to the current + * application, and may or may not be returned again on a subsequent + * call with the same name argument.

    + * + * @param name Logical name of the Log instance to be + * returned (the meaning of this name is only known to the underlying + * logging implementation that is being wrapped) + * + * @exception LogConfigurationException if a suitable Log + * instance cannot be returned + */ + public Log getInstance(String name) throws LogConfigurationException { + + Log instance = (Log) instances.get(name); + if (instance == null) { + instance = newInstance(name); + instances.put(name, instance); + } + return (instance); + + } + + + /** + * Release any internal references to previously created + * {@link org.apache.commons.logging.Log} + * instances returned by this factory. This is useful in environments + * like servlet containers, which implement application reloading by + * throwing away a ClassLoader. Dangling references to objects in that + * class loader would prevent garbage collection. + */ + public void release() { + + logDiagnostic("Releasing all known loggers"); + instances.clear(); + } + + + /** + * Remove any configuration attribute associated with the specified name. + * If there is no such attribute, no action is taken. + * + * @param name Name of the attribute to remove + */ + public void removeAttribute(String name) { + + attributes.remove(name); + + } + + + /** + * Set the configuration attribute with the specified name. Calling + * this with a null value is equivalent to calling + * removeAttribute(name). + *

    + * This method can be used to set logging configuration programmatically + * rather than via system properties. It can also be used in code running + * within a container (such as a webapp) to configure behaviour on a + * per-component level instead of globally as system properties would do. + * To use this method instead of a system property, call + *

    +     * LogFactory.getFactory().setAttribute(...)
    +     * 
    + * This must be done before the first Log object is created; configuration + * changes after that point will be ignored. + *

    + * This method is also called automatically if LogFactory detects a + * commons-logging.properties file; every entry in that file is set + * automatically as an attribute here. + * + * @param name Name of the attribute to set + * @param value Value of the attribute to set, or null + * to remove any setting for this attribute + */ + public void setAttribute(String name, Object value) { + + if (logConstructor != null) { + logDiagnostic("setAttribute: call too late; configuration already performed."); + } + + if (value == null) { + attributes.remove(name); + } else { + attributes.put(name, value); + } + + if (name.equals(TCCL_KEY)) { + useTCCL = Boolean.valueOf(value.toString()).booleanValue(); + } + + } + + + // ------------------------------------------------------ + // Static Methods + // + // These methods only defined as workarounds for a java 1.2 bug; + // theoretically none of these are needed. + // ------------------------------------------------------ + + /** + * Gets the context classloader. + * This method is a workaround for a java 1.2 compiler bug. + * @since 1.1 + */ + protected static ClassLoader getContextClassLoader() throws LogConfigurationException { + return LogFactory.getContextClassLoader(); + } + + + /** + * Workaround for bug in Java1.2; in theory this method is not needed. + * See LogFactory.isDiagnosticsEnabled. + */ + protected static boolean isDiagnosticsEnabled() { + return LogFactory.isDiagnosticsEnabled(); + } + + + /** + * Workaround for bug in Java1.2; in theory this method is not needed. + * See LogFactory.getClassLoader. + * @since 1.1 + */ + protected static ClassLoader getClassLoader(Class clazz) { + return LogFactory.getClassLoader(clazz); + } + + + // ------------------------------------------------------ Protected Methods + + /** + * Calculate and cache a string that uniquely identifies this instance, + * including which classloader the object was loaded from. + *

    + * This string will later be prefixed to each "internal logging" message + * emitted, so that users can clearly see any unexpected behaviour. + *

    + * Note that this method does not detect whether internal logging is + * enabled or not, nor where to output stuff if it is; that is all + * handled by the parent LogFactory class. This method just computes + * its own unique prefix for log messages. + */ + private void initDiagnostics() { + // It would be nice to include an identifier of the context classloader + // that this LogFactoryImpl object is responsible for. However that + // isn't possible as that information isn't available. It is possible + // to figure this out by looking at the logging from LogFactory to + // see the context & impl ids from when this object was instantiated, + // in order to link the impl id output as this object's prefix back to + // the context it is intended to manage. + // Note that this prefix should be kept consistent with that + // in LogFactory. + Class clazz = this.getClass(); + ClassLoader classLoader = getClassLoader(clazz); + String classLoaderName; + try { + if (classLoader == null) { + classLoaderName = "BOOTLOADER"; + } else { + classLoaderName = objectId(classLoader); + } + } catch(SecurityException e) { + classLoaderName = "UNKNOWN"; + } + diagnosticPrefix = "[LogFactoryImpl@" + System.identityHashCode(this) + " from " + classLoaderName + "] "; + } + + + /** + * Output a diagnostic message to a user-specified destination (if the + * user has enabled diagnostic logging). + * + * @param msg diagnostic message + * @since 1.1 + */ + protected void logDiagnostic(String msg) { + if (isDiagnosticsEnabled()) { + logRawDiagnostic(diagnosticPrefix + msg); + } + } + + /** + * Return the fully qualified Java classname of the {@link Log} + * implementation we will be using. + * + * @deprecated Never invoked by this class; subclasses should not assume + * it will be. + */ + protected String getLogClassName() { + + if (logClassName == null) { + discoverLogImplementation(getClass().getName()); + } + + return logClassName; + } + + + /** + *

    Return the Constructor that can be called to instantiate + * new {@link org.apache.commons.logging.Log} instances.

    + * + *

    IMPLEMENTATION NOTE - Race conditions caused by + * calling this method from more than one thread are ignored, because + * the same Constructor instance will ultimately be derived + * in all circumstances.

    + * + * @exception LogConfigurationException if a suitable constructor + * cannot be returned + * + * @deprecated Never invoked by this class; subclasses should not assume + * it will be. + */ + protected Constructor getLogConstructor() + throws LogConfigurationException { + + // Return the previously identified Constructor (if any) + if (logConstructor == null) { + discoverLogImplementation(getClass().getName()); + } + + return logConstructor; + } + + + /** + * Is JDK 1.3 with Lumberjack logging available? + * + * @deprecated Never invoked by this class; subclasses should not assume + * it will be. + */ + protected boolean isJdk13LumberjackAvailable() { + return isLogLibraryAvailable( + "Jdk13Lumberjack", + "org.apache.commons.logging.impl.Jdk13LumberjackLogger"); + } + + + /** + *

    Return true if JDK 1.4 or later logging + * is available. Also checks that the Throwable class + * supports getStackTrace(), which is required by + * Jdk14Logger.

    + * + * @deprecated Never invoked by this class; subclasses should not assume + * it will be. + */ + protected boolean isJdk14Available() { + return isLogLibraryAvailable( + "Jdk14", + "org.apache.commons.logging.impl.Jdk14Logger"); + } + + + /** + * Is a Log4J implementation available? + * + * @deprecated Never invoked by this class; subclasses should not assume + * it will be. + */ + protected boolean isLog4JAvailable() { + return isLogLibraryAvailable( + "Log4J", + LOGGING_IMPL_LOG4J_LOGGER); + } + + + /** + * Create and return a new {@link org.apache.commons.logging.Log} + * instance for the specified name. + * + * @param name Name of the new logger + * + * @exception LogConfigurationException if a new instance cannot + * be created + */ + protected Log newInstance(String name) throws LogConfigurationException { + + Log instance = null; + try { + if (logConstructor == null) { + instance = discoverLogImplementation(name); + } + else { + Object params[] = { name }; + instance = (Log) logConstructor.newInstance(params); + } + + if (logMethod != null) { + Object params[] = { this }; + logMethod.invoke(instance, params); + } + + return (instance); + + } catch (LogConfigurationException lce) { + + // this type of exception means there was a problem in discovery + // and we've already output diagnostics about the issue, etc.; + // just pass it on + throw (LogConfigurationException) lce; + + } catch (InvocationTargetException e) { + // A problem occurred invoking the Constructor or Method + // previously discovered + Throwable c = e.getTargetException(); + if (c != null) { + throw new LogConfigurationException(c); + } else { + throw new LogConfigurationException(e); + } + } catch (Throwable t) { + // A problem occurred invoking the Constructor or Method + // previously discovered + throw new LogConfigurationException(t); + } + } + + + // ------------------------------------------------------ Private Methods + + /** + * Calls LogFactory.directGetContextClassLoader under the control of an + * AccessController class. This means that java code running under a + * security manager that forbids access to ClassLoaders will still work + * if this class is given appropriate privileges, even when the caller + * doesn't have such privileges. Without using an AccessController, the + * the entire call stack must have the privilege before the call is + * allowed. + * + * @return the context classloader associated with the current thread, + * or null if security doesn't allow it. + * + * @throws LogConfigurationException if there was some weird error while + * attempting to get the context classloader. + * + * @throws SecurityException if the current java security policy doesn't + * allow this class to access the context classloader. + */ + private static ClassLoader getContextClassLoaderInternal() + throws LogConfigurationException { + return (ClassLoader)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return LogFactory.directGetContextClassLoader(); + } + }); + } + + /** + * Read the specified system property, using an AccessController so that + * the property can be read if JCL has been granted the appropriate + * security rights even if the calling code has not. + *

    + * Take care not to expose the value returned by this method to the + * calling application in any way; otherwise the calling app can use that + * info to access data that should not be available to it. + */ + private static String getSystemProperty(final String key, final String def) + throws SecurityException { + return (String) AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return System.getProperty(key, def); + } + }); + } + + /** + * Fetch the parent classloader of a specified classloader. + *

    + * If a SecurityException occurs, null is returned. + *

    + * Note that this method is non-static merely so logDiagnostic is available. + */ + private ClassLoader getParentClassLoader(final ClassLoader cl) { + try { + return (ClassLoader)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return cl.getParent(); + } + }); + } catch(SecurityException ex) { + logDiagnostic("[SECURITY] Unable to obtain parent classloader"); + return null; + } + + } + + /** + * Utility method to check whether a particular logging library is + * present and available for use. Note that this does not + * affect the future behaviour of this class. + */ + private boolean isLogLibraryAvailable(String name, String classname) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Checking for '" + name + "'."); + } + try { + Log log = createLogFromClass( + classname, + this.getClass().getName(), // dummy category + false); + + if (log == null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Did not find '" + name + "'."); + } + return false; + } else { + if (isDiagnosticsEnabled()) { + logDiagnostic("Found '" + name + "'."); + } + return true; + } + } catch(LogConfigurationException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Logging system '" + name + "' is available but not useable."); + } + return false; + } + } + + /** + * Attempt to find an attribute (see method setAttribute) or a + * system property with the provided name and return its value. + *

    + * The attributes associated with this object are checked before + * system properties in case someone has explicitly called setAttribute, + * or a configuration property has been set in a commons-logging.properties + * file. + * + * @return the value associated with the property, or null. + */ + private String getConfigurationValue(String property) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] Trying to get configuration for item " + property); + } + + Object valueObj = getAttribute(property); + if (valueObj != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] Found LogFactory attribute [" + valueObj + "] for " + property); + } + return valueObj.toString(); + } + + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] No LogFactory attribute found for " + property); + } + + try { + // warning: minor security hole here, in that we potentially read a system + // property that the caller cannot, then output it in readable form as a + // diagnostic message. However it's only ever JCL-specific properties + // involved here, so the harm is truly trivial. + String value = getSystemProperty(property, null); + if (value != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] Found system property [" + value + "] for " + property); + } + return value; + } + + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] No system property found for property " + property); + } + } catch (SecurityException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] Security prevented reading system property " + property); + } + } + + if (isDiagnosticsEnabled()) { + logDiagnostic("[ENV] No configuration defined for item " + property); + } + + return null; + } + + /** + * Get the setting for the user-configurable behaviour specified by key. + * If nothing has explicitly been set, then return dflt. + */ + private boolean getBooleanConfiguration(String key, boolean dflt) { + String val = getConfigurationValue(key); + if (val == null) + return dflt; + return Boolean.valueOf(val).booleanValue(); + } + + /** + * Initialize a number of variables that control the behaviour of this + * class and that can be tweaked by the user. This is done when the first + * logger is created, not in the constructor of this class, because we + * need to give the user a chance to call method setAttribute in order to + * configure this object. + */ + private void initConfiguration() { + allowFlawedContext = getBooleanConfiguration(ALLOW_FLAWED_CONTEXT_PROPERTY, true); + allowFlawedDiscovery = getBooleanConfiguration(ALLOW_FLAWED_DISCOVERY_PROPERTY, true); + allowFlawedHierarchy = getBooleanConfiguration(ALLOW_FLAWED_HIERARCHY_PROPERTY, true); + } + + + /** + * Attempts to create a Log instance for the given category name. + * Follows the discovery process described in the class javadoc. + * + * @param logCategory the name of the log category + * + * @throws LogConfigurationException if an error in discovery occurs, + * or if no adapter at all can be instantiated + */ + private Log discoverLogImplementation(String logCategory) + throws LogConfigurationException + { + if (isDiagnosticsEnabled()) { + logDiagnostic("Discovering a Log implementation..."); + } + + initConfiguration(); + + Log result = null; + + // See if the user specified the Log implementation to use + String specifiedLogClassName = findUserSpecifiedLogClassName(); + + if (specifiedLogClassName != null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Attempting to load user-specified log class '" + + specifiedLogClassName + "'..."); + } + + result = createLogFromClass(specifiedLogClassName, + logCategory, + true); + if (result == null) { + StringBuffer messageBuffer = new StringBuffer("User-specified log class '"); + messageBuffer.append(specifiedLogClassName); + messageBuffer.append("' cannot be found or is not useable."); + + // Mistyping or misspelling names is a common fault. + // Construct a good error message, if we can + if (specifiedLogClassName != null) { + informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LOG4J_LOGGER); + informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_JDK14_LOGGER); + informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LUMBERJACK_LOGGER); + informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_SIMPLE_LOGGER); + } + throw new LogConfigurationException(messageBuffer.toString()); + } + + return result; + } + + // No user specified log; try to discover what's on the classpath + // + // Note that we deliberately loop here over classesToDiscover and + // expect method createLogFromClass to loop over the possible source + // classloaders. The effect is: + // for each discoverable log adapter + // for each possible classloader + // see if it works + // + // It appears reasonable at first glance to do the opposite: + // for each possible classloader + // for each discoverable log adapter + // see if it works + // + // The latter certainly has advantages for user-installable logging + // libraries such as log4j; in a webapp for example this code should + // first check whether the user has provided any of the possible + // logging libraries before looking in the parent classloader. + // Unfortunately, however, Jdk14Logger will always work in jvm>=1.4, + // and SimpleLog will always work in any JVM. So the loop would never + // ever look for logging libraries in the parent classpath. Yet many + // users would expect that putting log4j there would cause it to be + // detected (and this is the historical JCL behaviour). So we go with + // the first approach. A user that has bundled a specific logging lib + // in a webapp should use a commons-logging.properties file or a + // service file in META-INF to force use of that logging lib anyway, + // rather than relying on discovery. + + if (isDiagnosticsEnabled()) { + logDiagnostic( + "No user-specified Log implementation; performing discovery" + + " using the standard supported logging implementations..."); + } + for(int i=0; (iStringBuffer the message should be appended to, + * not null + * @param name the (trimmed) name to be test against the candidate, not null + * @param candidate the candidate name (not null) + */ + private void informUponSimilarName(final StringBuffer messageBuffer, final String name, + final String candidate) { + if (name.equals(candidate)) { + // Don't suggest a name that is exactly the same as the one the + // user tried... + return; + } + + // If the user provides a name that is in the right package, and gets + // the first 5 characters of the adapter class right (ignoring case), + // then suggest the candidate adapter class name. + if (name.regionMatches(true, 0, candidate, 0, PKG_LEN + 5)) { + messageBuffer.append(" Did you mean '"); + messageBuffer.append(candidate); + messageBuffer.append("'?"); + } + } + + + /** + * Checks system properties and the attribute map for + * a Log implementation specified by the user under the + * property names {@link #LOG_PROPERTY} or {@link #LOG_PROPERTY_OLD}. + * + * @return classname specified by the user, or null + */ + private String findUserSpecifiedLogClassName() + { + if (isDiagnosticsEnabled()) { + logDiagnostic("Trying to get log class from attribute '" + LOG_PROPERTY + "'"); + } + String specifiedClass = (String) getAttribute(LOG_PROPERTY); + + if (specifiedClass == null) { // @deprecated + if (isDiagnosticsEnabled()) { + logDiagnostic("Trying to get log class from attribute '" + + LOG_PROPERTY_OLD + "'"); + } + specifiedClass = (String) getAttribute(LOG_PROPERTY_OLD); + } + + if (specifiedClass == null) { + if (isDiagnosticsEnabled()) { + logDiagnostic("Trying to get log class from system property '" + + LOG_PROPERTY + "'"); + } + try { + specifiedClass = getSystemProperty(LOG_PROPERTY, null); + } catch (SecurityException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("No access allowed to system property '" + + LOG_PROPERTY + "' - " + e.getMessage()); + } + } + } + + if (specifiedClass == null) { // @deprecated + if (isDiagnosticsEnabled()) { + logDiagnostic("Trying to get log class from system property '" + + LOG_PROPERTY_OLD + "'"); + } + try { + specifiedClass = getSystemProperty(LOG_PROPERTY_OLD, null); + } catch (SecurityException e) { + if (isDiagnosticsEnabled()) { + logDiagnostic("No access allowed to system property '" + + LOG_PROPERTY_OLD + "' - " + e.getMessage()); + } + } + } + + // Remove any whitespace; it's never valid in a classname so its + // presence just means a user mistake. As we know what they meant, + // we may as well strip the spaces. + if (specifiedClass != null) { + specifiedClass = specifiedClass.trim(); + } + + return specifiedClass; + } + + + /** + * Attempts to load the given class, find a suitable constructor, + * and instantiate an instance of Log. + * + * @param logAdapterClassName classname of the Log implementation + * + * @param logCategory argument to pass to the Log implementation's + * constructor + * + * @param affectState true if this object's state should + * be affected by this method call, false otherwise. + * + * @return an instance of the given class, or null if the logging + * library associated with the specified adapter is not available. + * + * @throws LogConfigurationException if there was a serious error with + * configuration and the handleFlawedDiscovery method decided this + * problem was fatal. + */ + private Log createLogFromClass(String logAdapterClassName, + String logCategory, + boolean affectState) + throws LogConfigurationException { + + if (isDiagnosticsEnabled()) { + logDiagnostic("Attempting to instantiate '" + logAdapterClassName + "'"); + } + + Object[] params = { logCategory }; + Log logAdapter = null; + Constructor constructor = null; + + Class logAdapterClass = null; + ClassLoader currentCL = getBaseClassLoader(); + + for(;;) { + // Loop through the classloader hierarchy trying to find + // a viable classloader. + logDiagnostic( + "Trying to load '" + + logAdapterClassName + + "' from classloader " + + objectId(currentCL)); + try { + if (isDiagnosticsEnabled()) { + // Show the location of the first occurrence of the .class file + // in the classpath. This is the location that ClassLoader.loadClass + // will load the class from -- unless the classloader is doing + // something weird. + URL url; + String resourceName = logAdapterClassName.replace('.', '/') + ".class"; + if (currentCL != null) { + url = currentCL.getResource(resourceName ); + } else { + url = ClassLoader.getSystemResource(resourceName + ".class"); + } + + if (url == null) { + logDiagnostic("Class '" + logAdapterClassName + "' [" + resourceName + "] cannot be found."); + } else { + logDiagnostic("Class '" + logAdapterClassName + "' was found at '" + url + "'"); + } + } + + Class c = null; + try { + c = Class.forName(logAdapterClassName, true, currentCL); + } catch (ClassNotFoundException originalClassNotFoundException) { + // The current classloader was unable to find the log adapter + // in this or any ancestor classloader. There's no point in + // trying higher up in the hierarchy in this case.. + String msg = "" + originalClassNotFoundException.getMessage(); + logDiagnostic( + "The log adapter '" + + logAdapterClassName + + "' is not available via classloader " + + objectId(currentCL) + + ": " + + msg.trim()); + try { + // Try the class classloader. + // This may work in cases where the TCCL + // does not contain the code executed or JCL. + // This behaviour indicates that the application + // classloading strategy is not consistent with the + // Java 1.2 classloading guidelines but JCL can + // and so should handle this case. + c = Class.forName(logAdapterClassName); + } catch (ClassNotFoundException secondaryClassNotFoundException) { + // no point continuing: this adapter isn't available + msg = "" + secondaryClassNotFoundException.getMessage(); + logDiagnostic( + "The log adapter '" + + logAdapterClassName + + "' is not available via the LogFactoryImpl class classloader: " + + msg.trim()); + break; + } + } + + constructor = c.getConstructor(logConstructorSignature); + Object o = constructor.newInstance(params); + + // Note that we do this test after trying to create an instance + // [rather than testing Log.class.isAssignableFrom(c)] so that + // we don't complain about Log hierarchy problems when the + // adapter couldn't be instantiated anyway. + if (o instanceof Log) { + logAdapterClass = c; + logAdapter = (Log) o; + break; + } + + // Oops, we have a potential problem here. An adapter class + // has been found and its underlying lib is present too, but + // there are multiple Log interface classes available making it + // impossible to cast to the type the caller wanted. We + // certainly can't use this logger, but we need to know whether + // to keep on discovering or terminate now. + // + // The handleFlawedHierarchy method will throw + // LogConfigurationException if it regards this problem as + // fatal, and just return if not. + handleFlawedHierarchy(currentCL, c); + } catch (NoClassDefFoundError e) { + // We were able to load the adapter but it had references to + // other classes that could not be found. This simply means that + // the underlying logger library is not present in this or any + // ancestor classloader. There's no point in trying higher up + // in the hierarchy in this case.. + String msg = "" + e.getMessage(); + logDiagnostic( + "The log adapter '" + + logAdapterClassName + + "' is missing dependencies when loaded via classloader " + + objectId(currentCL) + + ": " + + msg.trim()); + break; + } catch (ExceptionInInitializerError e) { + // A static initializer block or the initializer code associated + // with a static variable on the log adapter class has thrown + // an exception. + // + // We treat this as meaning the adapter's underlying logging + // library could not be found. + String msg = "" + e.getMessage(); + logDiagnostic( + "The log adapter '" + + logAdapterClassName + + "' is unable to initialize itself when loaded via classloader " + + objectId(currentCL) + + ": " + + msg.trim()); + break; + } catch(LogConfigurationException e) { + // call to handleFlawedHierarchy above must have thrown + // a LogConfigurationException, so just throw it on + throw e; + } catch(Throwable t) { + // handleFlawedDiscovery will determine whether this is a fatal + // problem or not. If it is fatal, then a LogConfigurationException + // will be thrown. + handleFlawedDiscovery(logAdapterClassName, currentCL, t); + } + + if (currentCL == null) { + break; + } + + // try the parent classloader + // currentCL = currentCL.getParent(); + currentCL = getParentClassLoader(currentCL); + } + + if ((logAdapter != null) && affectState) { + // We've succeeded, so set instance fields + this.logClassName = logAdapterClassName; + this.logConstructor = constructor; + + // Identify the setLogFactory method (if there is one) + try { + this.logMethod = logAdapterClass.getMethod("setLogFactory", + logMethodSignature); + logDiagnostic("Found method setLogFactory(LogFactory) in '" + + logAdapterClassName + "'"); + } catch (Throwable t) { + this.logMethod = null; + logDiagnostic( + "[INFO] '" + logAdapterClassName + + "' from classloader " + objectId(currentCL) + + " does not declare optional method " + + "setLogFactory(LogFactory)"); + } + + logDiagnostic( + "Log adapter '" + logAdapterClassName + + "' from classloader " + objectId(logAdapterClass.getClassLoader()) + + " has been selected for use."); + } + + return logAdapter; + } + + + /** + * Return the classloader from which we should try to load the logging + * adapter classes. + *

    + * This method usually returns the context classloader. However if it + * is discovered that the classloader which loaded this class is a child + * of the context classloader and the allowFlawedContext option + * has been set then the classloader which loaded this class is returned + * instead. + *

    + * The only time when the classloader which loaded this class is a + * descendant (rather than the same as or an ancestor of the context + * classloader) is when an app has created custom classloaders but + * failed to correctly set the context classloader. This is a bug in + * the calling application; however we provide the option for JCL to + * simply generate a warning rather than fail outright. + * + */ + private ClassLoader getBaseClassLoader() throws LogConfigurationException { + ClassLoader thisClassLoader = getClassLoader(LogFactoryImpl.class); + + if (useTCCL == false) { + return thisClassLoader; + } + + ClassLoader contextClassLoader = getContextClassLoaderInternal(); + + ClassLoader baseClassLoader = getLowestClassLoader( + contextClassLoader, thisClassLoader); + + if (baseClassLoader == null) { + // The two classloaders are not part of a parent child relationship. + // In some classloading setups (e.g. JBoss with its + // UnifiedLoaderRepository) this can still work, so if user hasn't + // forbidden it, just return the contextClassLoader. + if (allowFlawedContext) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "[WARNING] the context classloader is not part of a" + + " parent-child relationship with the classloader that" + + " loaded LogFactoryImpl."); + } + // If contextClassLoader were null, getLowestClassLoader() would + // have returned thisClassLoader. The fact we are here means + // contextClassLoader is not null, so we can just return it. + return contextClassLoader; + } + else { + throw new LogConfigurationException( + "Bad classloader hierarchy; LogFactoryImpl was loaded via" + + " a classloader that is not related to the current context" + + " classloader."); + } + } + + if (baseClassLoader != contextClassLoader) { + // We really should just use the contextClassLoader as the starting + // point for scanning for log adapter classes. However it is expected + // that there are a number of broken systems out there which create + // custom classloaders but fail to set the context classloader so + // we handle those flawed systems anyway. + if (allowFlawedContext) { + if (isDiagnosticsEnabled()) { + logDiagnostic( + "Warning: the context classloader is an ancestor of the" + + " classloader that loaded LogFactoryImpl; it should be" + + " the same or a descendant. The application using" + + " commons-logging should ensure the context classloader" + + " is used correctly."); + } + } else { + throw new LogConfigurationException( + "Bad classloader hierarchy; LogFactoryImpl was loaded via" + + " a classloader that is not related to the current context" + + " classloader."); + } + } + + return baseClassLoader; + } + + /** + * Given two related classloaders, return the one which is a child of + * the other. + *

    + * @param c1 is a classloader (including the null classloader) + * @param c2 is a classloader (including the null classloader) + * + * @return c1 if it has c2 as an ancestor, c2 if it has c1 as an ancestor, + * and null if neither is an ancestor of the other. + */ + private ClassLoader getLowestClassLoader(ClassLoader c1, ClassLoader c2) { + // TODO: use AccessController when dealing with classloaders here + + if (c1 == null) + return c2; + + if (c2 == null) + return c1; + + ClassLoader current; + + // scan c1's ancestors to find c2 + current = c1; + while (current != null) { + if (current == c2) + return c1; + current = current.getParent(); + } + + // scan c2's ancestors to find c1 + current = c2; + while (current != null) { + if (current == c1) + return c2; + current = current.getParent(); + } + + return null; + } + + /** + * Generates an internal diagnostic logging of the discovery failure and + * then throws a LogConfigurationException that wraps + * the passed Throwable. + * + * @param logAdapterClassName is the class name of the Log implementation + * that could not be instantiated. Cannot be null. + * + * @param classLoader is the classloader that we were trying to load the + * logAdapterClassName from when the exception occurred. + * + * @param discoveryFlaw is the Throwable created by the classloader + * + * @throws LogConfigurationException ALWAYS + */ + private void handleFlawedDiscovery(String logAdapterClassName, + ClassLoader classLoader, + Throwable discoveryFlaw) { + + if (isDiagnosticsEnabled()) { + logDiagnostic("Could not instantiate Log '" + + logAdapterClassName + "' -- " + + discoveryFlaw.getClass().getName() + ": " + + discoveryFlaw.getLocalizedMessage()); + + if (discoveryFlaw instanceof InvocationTargetException ) { + // Ok, the lib is there but while trying to create a real underlying + // logger something failed in the underlying lib; display info about + // that if possible. + InvocationTargetException ite = (InvocationTargetException)discoveryFlaw; + Throwable cause = ite.getTargetException(); + if (cause != null) { + logDiagnostic("... InvocationTargetException: " + + cause.getClass().getName() + ": " + + cause.getLocalizedMessage()); + + if (cause instanceof ExceptionInInitializerError) { + ExceptionInInitializerError eiie = (ExceptionInInitializerError)cause; + Throwable cause2 = eiie.getException(); + if (cause2 != null) { + logDiagnostic("... ExceptionInInitializerError: " + + cause2.getClass().getName() + ": " + + cause2.getLocalizedMessage()); + } + } + } + } + } + + if (!allowFlawedDiscovery) { + throw new LogConfigurationException(discoveryFlaw); + } + } + + + /** + * Report a problem loading the log adapter, then either return + * (if the situation is considered recoverable) or throw a + * LogConfigurationException. + *

    + * There are two possible reasons why we successfully loaded the + * specified log adapter class then failed to cast it to a Log object: + *

      + *
    1. the specific class just doesn't implement the Log interface + * (user screwed up), or + *
    2. the specified class has bound to a Log class loaded by some other + * classloader; Log@classloaderX cannot be cast to Log@classloaderY. + *
    + *

    + * Here we try to figure out which case has occurred so we can give the + * user some reasonable feedback. + * + * @param badClassLoader is the classloader we loaded the problem class from, + * ie it is equivalent to badClass.getClassLoader(). + * + * @param badClass is a Class object with the desired name, but which + * does not implement Log correctly. + * + * @throws LogConfigurationException when the situation + * should not be recovered from. + */ + private void handleFlawedHierarchy(ClassLoader badClassLoader, Class badClass) + throws LogConfigurationException { + + boolean implementsLog = false; + String logInterfaceName = Log.class.getName(); + Class interfaces[] = badClass.getInterfaces(); + for (int i = 0; i < interfaces.length; i++) { + if (logInterfaceName.equals(interfaces[i].getName())) { + implementsLog = true; + break; + } + } + + if (implementsLog) { + // the class does implement an interface called Log, but + // it is in the wrong classloader + if (isDiagnosticsEnabled()) { + try { + ClassLoader logInterfaceClassLoader = getClassLoader(Log.class); + logDiagnostic( + "Class '" + badClass.getName() + + "' was found in classloader " + + objectId(badClassLoader) + + ". It is bound to a Log interface which is not" + + " the one loaded from classloader " + + objectId(logInterfaceClassLoader)); + } catch (Throwable t) { + logDiagnostic( + "Error while trying to output diagnostics about" + + " bad class '" + badClass + "'"); + } + } + + if (!allowFlawedHierarchy) { + StringBuffer msg = new StringBuffer(); + msg.append("Terminating logging for this context "); + msg.append("due to bad log hierarchy. "); + msg.append("You have more than one version of '"); + msg.append(Log.class.getName()); + msg.append("' visible."); + if (isDiagnosticsEnabled()) { + logDiagnostic(msg.toString()); + } + throw new LogConfigurationException(msg.toString()); + } + + if (isDiagnosticsEnabled()) { + StringBuffer msg = new StringBuffer(); + msg.append("Warning: bad log hierarchy. "); + msg.append("You have more than one version of '"); + msg.append(Log.class.getName()); + msg.append("' visible."); + logDiagnostic(msg.toString()); + } + } else { + // this is just a bad adapter class + if (!allowFlawedDiscovery) { + StringBuffer msg = new StringBuffer(); + msg.append("Terminating logging for this context. "); + msg.append("Log class '"); + msg.append(badClass.getName()); + msg.append("' does not implement the Log interface."); + if (isDiagnosticsEnabled()) { + logDiagnostic(msg.toString()); + } + + throw new LogConfigurationException(msg.toString()); + } + + if (isDiagnosticsEnabled()) { + StringBuffer msg = new StringBuffer(); + msg.append("[WARNING] Log class '"); + msg.append(badClass.getName()); + msg.append("' does not implement the Log interface."); + logDiagnostic(msg.toString()); + } + } + } +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/LogKitLogger.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/LogKitLogger.java new file mode 100644 index 0000000..2587e81 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/LogKitLogger.java @@ -0,0 +1,294 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging.impl; + +import java.io.Serializable; +import org.apache.log.Logger; +import org.apache.log.Hierarchy; +import org.apache.commons.logging.Log; + +/** + *

    Implementation of org.apache.commons.logging.Log + * that wraps the avalon-logkit + * logging system. Configuration of LogKit is left to the user. + *

    + * + *

    LogKit accepts only String messages. + * Therefore, this implementation converts object messages into strings + * by called their toString() method before logging them.

    + * + * @author Scott Sanders + * @author Robert Burrell Donkin + * @version $Id: LogKitLogger.java 424107 2006-07-20 23:15:42Z skitching $ + */ + +public class LogKitLogger implements Log, Serializable { + + + // ------------------------------------------------------------- Attributes + + + /** Logging goes to this LogKit logger */ + protected transient Logger logger = null; + + /** Name of this logger */ + protected String name = null; + + + // ------------------------------------------------------------ Constructor + + + /** + * Construct LogKitLogger which wraps the LogKit + * logger with given name. + * + * @param name log name + */ + public LogKitLogger(String name) { + this.name = name; + this.logger = getLogger(); + } + + + // --------------------------------------------------------- Public Methods + + + /** + *

    Return the underlying Logger we are using.

    + */ + public Logger getLogger() { + + if (logger == null) { + logger = Hierarchy.getDefaultHierarchy().getLoggerFor(name); + } + return (logger); + + } + + + // ----------------------------------------------------- Log Implementation + + + /** + * Logs a message with org.apache.log.Priority.DEBUG. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public void trace(Object message) { + debug(message); + } + + + /** + * Logs a message with org.apache.log.Priority.DEBUG. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public void trace(Object message, Throwable t) { + debug(message, t); + } + + + /** + * Logs a message with org.apache.log.Priority.DEBUG. + * + * @param message to log + * @see org.apache.commons.logging.Log#debug(Object) + */ + public void debug(Object message) { + if (message != null) { + getLogger().debug(String.valueOf(message)); + } + } + + + /** + * Logs a message with org.apache.log.Priority.DEBUG. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public void debug(Object message, Throwable t) { + if (message != null) { + getLogger().debug(String.valueOf(message), t); + } + } + + + /** + * Logs a message with org.apache.log.Priority.INFO. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public void info(Object message) { + if (message != null) { + getLogger().info(String.valueOf(message)); + } + } + + + /** + * Logs a message with org.apache.log.Priority.INFO. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public void info(Object message, Throwable t) { + if (message != null) { + getLogger().info(String.valueOf(message), t); + } + } + + + /** + * Logs a message with org.apache.log.Priority.WARN. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public void warn(Object message) { + if (message != null) { + getLogger().warn(String.valueOf(message)); + } + } + + + /** + * Logs a message with org.apache.log.Priority.WARN. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public void warn(Object message, Throwable t) { + if (message != null) { + getLogger().warn(String.valueOf(message), t); + } + } + + + /** + * Logs a message with org.apache.log.Priority.ERROR. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public void error(Object message) { + if (message != null) { + getLogger().error(String.valueOf(message)); + } + } + + + /** + * Logs a message with org.apache.log.Priority.ERROR. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public void error(Object message, Throwable t) { + if (message != null) { + getLogger().error(String.valueOf(message), t); + } + } + + + /** + * Logs a message with org.apache.log.Priority.FATAL_ERROR. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public void fatal(Object message) { + if (message != null) { + getLogger().fatalError(String.valueOf(message)); + } + } + + + /** + * Logs a message with org.apache.log.Priority.FATAL_ERROR. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public void fatal(Object message, Throwable t) { + if (message != null) { + getLogger().fatalError(String.valueOf(message), t); + } + } + + + /** + * Checks whether the LogKit logger will log messages of priority DEBUG. + */ + public boolean isDebugEnabled() { + return getLogger().isDebugEnabled(); + } + + + /** + * Checks whether the LogKit logger will log messages of priority ERROR. + */ + public boolean isErrorEnabled() { + return getLogger().isErrorEnabled(); + } + + + /** + * Checks whether the LogKit logger will log messages of priority FATAL_ERROR. + */ + public boolean isFatalEnabled() { + return getLogger().isFatalErrorEnabled(); + } + + + /** + * Checks whether the LogKit logger will log messages of priority INFO. + */ + public boolean isInfoEnabled() { + return getLogger().isInfoEnabled(); + } + + + /** + * Checks whether the LogKit logger will log messages of priority DEBUG. + */ + public boolean isTraceEnabled() { + return getLogger().isDebugEnabled(); + } + + + /** + * Checks whether the LogKit logger will log messages of priority WARN. + */ + public boolean isWarnEnabled() { + return getLogger().isWarnEnabled(); + } + + +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/NoOpLog.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/NoOpLog.java new file mode 100644 index 0000000..229cdff --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/NoOpLog.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging.impl; + + +import java.io.Serializable; +import org.apache.commons.logging.Log; + + +/** + *

    Trivial implementation of Log that throws away all messages. No + * configurable system properties are supported.

    + * + * @author Scott Sanders + * @author Rod Waldhoff + * @version $Id: NoOpLog.java 424107 2006-07-20 23:15:42Z skitching $ + */ +public class NoOpLog implements Log, Serializable { + + /** Convenience constructor */ + public NoOpLog() { } + /** Base constructor */ + public NoOpLog(String name) { } + /** Do nothing */ + public void trace(Object message) { } + /** Do nothing */ + public void trace(Object message, Throwable t) { } + /** Do nothing */ + public void debug(Object message) { } + /** Do nothing */ + public void debug(Object message, Throwable t) { } + /** Do nothing */ + public void info(Object message) { } + /** Do nothing */ + public void info(Object message, Throwable t) { } + /** Do nothing */ + public void warn(Object message) { } + /** Do nothing */ + public void warn(Object message, Throwable t) { } + /** Do nothing */ + public void error(Object message) { } + /** Do nothing */ + public void error(Object message, Throwable t) { } + /** Do nothing */ + public void fatal(Object message) { } + /** Do nothing */ + public void fatal(Object message, Throwable t) { } + + /** + * Debug is never enabled. + * + * @return false + */ + public final boolean isDebugEnabled() { return false; } + + /** + * Error is never enabled. + * + * @return false + */ + public final boolean isErrorEnabled() { return false; } + + /** + * Fatal is never enabled. + * + * @return false + */ + public final boolean isFatalEnabled() { return false; } + + /** + * Info is never enabled. + * + * @return false + */ + public final boolean isInfoEnabled() { return false; } + + /** + * Trace is never enabled. + * + * @return false + */ + public final boolean isTraceEnabled() { return false; } + + /** + * Warn is never enabled. + * + * @return false + */ + public final boolean isWarnEnabled() { return false; } + +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/ServletContextCleaner.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/ServletContextCleaner.java new file mode 100644 index 0000000..6061171 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/ServletContextCleaner.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging.impl; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.apache.commons.logging.LogFactory; + + +/** + * This class is capable of receiving notifications about the undeployment of + * a webapp, and responds by ensuring that commons-logging releases all + * memory associated with the undeployed webapp. + *

    + * In general, the WeakHashtable support added in commons-logging release 1.1 + * ensures that logging classes do not hold references that prevent an + * undeployed webapp's memory from being garbage-collected even when multiple + * copies of commons-logging are deployed via multiple classloaders (a + * situation that earlier versions had problems with). However there are + * some rare cases where the WeakHashtable approach does not work; in these + * situations specifying this class as a listener for the web application will + * ensure that all references held by commons-logging are fully released. + *

    + * To use this class, configure the webapp deployment descriptor to call + * this class on webapp undeploy; the contextDestroyed method will tell + * every accessable LogFactory class that the entry in its map for the + * current webapp's context classloader should be cleared. + * + * @since 1.1 + */ + +public class ServletContextCleaner implements ServletContextListener { + + private Class[] RELEASE_SIGNATURE = {ClassLoader.class}; + + /** + * Invoked when a webapp is undeployed, this tells the LogFactory + * class to release any logging information related to the current + * contextClassloader. + */ + public void contextDestroyed(ServletContextEvent sce) { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + + Object[] params = new Object[1]; + params[0] = tccl; + + // Walk up the tree of classloaders, finding all the available + // LogFactory classes and releasing any objects associated with + // the tccl (ie the webapp). + // + // When there is only one LogFactory in the classpath, and it + // is within the webapp being undeployed then there is no problem; + // garbage collection works fine. + // + // When there are multiple LogFactory classes in the classpath but + // parent-first classloading is used everywhere, this loop is really + // short. The first instance of LogFactory found will + // be the highest in the classpath, and then no more will be found. + // This is ok, as with this setup this will be the only LogFactory + // holding any data associated with the tccl being released. + // + // When there are multiple LogFactory classes in the classpath and + // child-first classloading is used in any classloader, then multiple + // LogFactory instances may hold info about this TCCL; whenever the + // webapp makes a call into a class loaded via an ancestor classloader + // and that class calls LogFactory the tccl gets registered in + // the LogFactory instance that is visible from the ancestor + // classloader. However the concrete logging library it points + // to is expected to have been loaded via the TCCL, so the + // underlying logging lib is only initialised/configured once. + // These references from ancestor LogFactory classes down to + // TCCL classloaders are held via weak references and so should + // be released but there are circumstances where they may not. + // Walking up the classloader ancestry ladder releasing + // the current tccl at each level tree, though, will definitely + // clear any problem references. + ClassLoader loader = tccl; + while (loader != null) { + // Load via the current loader. Note that if the class is not accessable + // via this loader, but is accessable via some ancestor then that class + // will be returned. + try { + Class logFactoryClass = loader.loadClass("org.apache.commons.logging.LogFactory"); + Method releaseMethod = logFactoryClass.getMethod("release", RELEASE_SIGNATURE); + releaseMethod.invoke(null, params); + loader = logFactoryClass.getClassLoader().getParent(); + } catch(ClassNotFoundException ex) { + // Neither the current classloader nor any of its ancestors could find + // the LogFactory class, so we can stop now. + loader = null; + } catch(NoSuchMethodException ex) { + // This is not expected; every version of JCL has this method + System.err.println("LogFactory instance found which does not support release method!"); + loader = null; + } catch(IllegalAccessException ex) { + // This is not expected; every ancestor class should be accessable + System.err.println("LogFactory instance found which is not accessable!"); + loader = null; + } catch(InvocationTargetException ex) { + // This is not expected + System.err.println("LogFactory instance release method failed!"); + loader = null; + } + } + + // Just to be sure, invoke release on the LogFactory that is visible from + // this ServletContextCleaner class too. This should already have been caught + // by the above loop but just in case... + LogFactory.release(tccl); + } + + /** + * Invoked when a webapp is deployed. Nothing needs to be done here. + */ + public void contextInitialized(ServletContextEvent sce) { + // do nothing + } +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/SimpleLog.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/SimpleLog.java new file mode 100644 index 0000000..d966722 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/SimpleLog.java @@ -0,0 +1,721 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging.impl; + +import java.io.InputStream; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogConfigurationException; + +/** + *

    Simple implementation of Log that sends all enabled log messages, + * for all defined loggers, to System.err. The following system properties + * are supported to configure the behavior of this logger:

    + *
      + *
    • org.apache.commons.logging.simplelog.defaultlog - + * Default logging detail level for all instances of SimpleLog. + * Must be one of ("trace", "debug", "info", "warn", "error", or "fatal"). + * If not specified, defaults to "info".
    • + *
    • org.apache.commons.logging.simplelog.log.xxxxx - + * Logging detail level for a SimpleLog instance named "xxxxx". + * Must be one of ("trace", "debug", "info", "warn", "error", or "fatal"). + * If not specified, the default logging detail level is used.
    • + *
    • org.apache.commons.logging.simplelog.showlogname - + * Set to true if you want the Log instance name to be + * included in output messages. Defaults to false.
    • + *
    • org.apache.commons.logging.simplelog.showShortLogname - + * Set to true if you want the last component of the name to be + * included in output messages. Defaults to true.
    • + *
    • org.apache.commons.logging.simplelog.showdatetime - + * Set to true if you want the current date and time + * to be included in output messages. Default is false.
    • + *
    • org.apache.commons.logging.simplelog.dateTimeFormat - + * The date and time format to be used in the output messages. + * The pattern describing the date and time format is the same that is + * used in java.text.SimpleDateFormat. If the format is not + * specified or is invalid, the default format is used. + * The default format is yyyy/MM/dd HH:mm:ss:SSS zzz.
    • + *
    + * + *

    In addition to looking for system properties with the names specified + * above, this implementation also checks for a class loader resource named + * "simplelog.properties", and includes any matching definitions + * from this resource (if it exists).

    + * + * @author Scott Sanders + * @author Rod Waldhoff + * @author Robert Burrell Donkin + * + * @version $Id: SimpleLog.java 581090 2007-10-01 22:01:06Z dennisl $ + */ +public class SimpleLog implements Log, Serializable { + + + // ------------------------------------------------------- Class Attributes + + /** All system properties used by SimpleLog start with this */ + static protected final String systemPrefix = + "org.apache.commons.logging.simplelog."; + + /** Properties loaded from simplelog.properties */ + static protected final Properties simpleLogProps = new Properties(); + + /** The default format to use when formating dates */ + static protected final String DEFAULT_DATE_TIME_FORMAT = + "yyyy/MM/dd HH:mm:ss:SSS zzz"; + + /** Include the instance name in the log message? */ + static protected boolean showLogName = false; + /** Include the short name ( last component ) of the logger in the log + * message. Defaults to true - otherwise we'll be lost in a flood of + * messages without knowing who sends them. + */ + static protected boolean showShortName = true; + /** Include the current time in the log message */ + static protected boolean showDateTime = false; + /** The date and time format to use in the log message */ + static protected String dateTimeFormat = DEFAULT_DATE_TIME_FORMAT; + + /** + * Used to format times. + *

    + * Any code that accesses this object should first obtain a lock on it, + * ie use synchronized(dateFormatter); this requirement was introduced + * in 1.1.1 to fix an existing thread safety bug (SimpleDateFormat.format + * is not thread-safe). + */ + static protected DateFormat dateFormatter = null; + + // ---------------------------------------------------- Log Level Constants + + + /** "Trace" level logging. */ + public static final int LOG_LEVEL_TRACE = 1; + /** "Debug" level logging. */ + public static final int LOG_LEVEL_DEBUG = 2; + /** "Info" level logging. */ + public static final int LOG_LEVEL_INFO = 3; + /** "Warn" level logging. */ + public static final int LOG_LEVEL_WARN = 4; + /** "Error" level logging. */ + public static final int LOG_LEVEL_ERROR = 5; + /** "Fatal" level logging. */ + public static final int LOG_LEVEL_FATAL = 6; + + /** Enable all logging levels */ + public static final int LOG_LEVEL_ALL = (LOG_LEVEL_TRACE - 1); + + /** Enable no logging levels */ + public static final int LOG_LEVEL_OFF = (LOG_LEVEL_FATAL + 1); + + // ------------------------------------------------------------ Initializer + + private static String getStringProperty(String name) { + String prop = null; + try { + prop = System.getProperty(name); + } catch (SecurityException e) { + ; // Ignore + } + return (prop == null) ? simpleLogProps.getProperty(name) : prop; + } + + private static String getStringProperty(String name, String dephault) { + String prop = getStringProperty(name); + return (prop == null) ? dephault : prop; + } + + private static boolean getBooleanProperty(String name, boolean dephault) { + String prop = getStringProperty(name); + return (prop == null) ? dephault : "true".equalsIgnoreCase(prop); + } + + // Initialize class attributes. + // Load properties file, if found. + // Override with system properties. + static { + // Add props from the resource simplelog.properties + InputStream in = getResourceAsStream("simplelog.properties"); + if(null != in) { + try { + simpleLogProps.load(in); + in.close(); + } catch(java.io.IOException e) { + // ignored + } + } + + showLogName = getBooleanProperty( systemPrefix + "showlogname", showLogName); + showShortName = getBooleanProperty( systemPrefix + "showShortLogname", showShortName); + showDateTime = getBooleanProperty( systemPrefix + "showdatetime", showDateTime); + + if(showDateTime) { + dateTimeFormat = getStringProperty(systemPrefix + "dateTimeFormat", + dateTimeFormat); + try { + dateFormatter = new SimpleDateFormat(dateTimeFormat); + } catch(IllegalArgumentException e) { + // If the format pattern is invalid - use the default format + dateTimeFormat = DEFAULT_DATE_TIME_FORMAT; + dateFormatter = new SimpleDateFormat(dateTimeFormat); + } + } + } + + // ------------------------------------------------------------- Attributes + + /** The name of this simple log instance */ + protected String logName = null; + /** The current log level */ + protected int currentLogLevel; + /** The short name of this simple log instance */ + private String shortLogName = null; + + + // ------------------------------------------------------------ Constructor + + /** + * Construct a simple log with given name. + * + * @param name log name + */ + public SimpleLog(String name) { + + logName = name; + + // Set initial log level + // Used to be: set default log level to ERROR + // IMHO it should be lower, but at least info ( costin ). + setLevel(SimpleLog.LOG_LEVEL_INFO); + + // Set log level from properties + String lvl = getStringProperty(systemPrefix + "log." + logName); + int i = String.valueOf(name).lastIndexOf("."); + while(null == lvl && i > -1) { + name = name.substring(0,i); + lvl = getStringProperty(systemPrefix + "log." + name); + i = String.valueOf(name).lastIndexOf("."); + } + + if(null == lvl) { + lvl = getStringProperty(systemPrefix + "defaultlog"); + } + + if("all".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_ALL); + } else if("trace".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_TRACE); + } else if("debug".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_DEBUG); + } else if("info".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_INFO); + } else if("warn".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_WARN); + } else if("error".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_ERROR); + } else if("fatal".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_FATAL); + } else if("off".equalsIgnoreCase(lvl)) { + setLevel(SimpleLog.LOG_LEVEL_OFF); + } + + } + + + // -------------------------------------------------------- Properties + + /** + *

    Set logging level.

    + * + * @param currentLogLevel new logging level + */ + public void setLevel(int currentLogLevel) { + + this.currentLogLevel = currentLogLevel; + + } + + + /** + *

    Get logging level.

    + */ + public int getLevel() { + + return currentLogLevel; + } + + + // -------------------------------------------------------- Logging Methods + + + /** + *

    Do the actual logging. + * This method assembles the message + * and then calls write() to cause it to be written.

    + * + * @param type One of the LOG_LEVEL_XXX constants defining the log level + * @param message The message itself (typically a String) + * @param t The exception whose stack trace should be logged + */ + protected void log(int type, Object message, Throwable t) { + // Use a string buffer for better performance + StringBuffer buf = new StringBuffer(); + + // Append date-time if so configured + if(showDateTime) { + Date now = new Date(); + String dateText; + synchronized(dateFormatter) { + dateText = dateFormatter.format(now); + } + buf.append(dateText); + buf.append(" "); + } + + // Append a readable representation of the log level + switch(type) { + case SimpleLog.LOG_LEVEL_TRACE: buf.append("[TRACE] "); break; + case SimpleLog.LOG_LEVEL_DEBUG: buf.append("[DEBUG] "); break; + case SimpleLog.LOG_LEVEL_INFO: buf.append("[INFO] "); break; + case SimpleLog.LOG_LEVEL_WARN: buf.append("[WARN] "); break; + case SimpleLog.LOG_LEVEL_ERROR: buf.append("[ERROR] "); break; + case SimpleLog.LOG_LEVEL_FATAL: buf.append("[FATAL] "); break; + } + + // Append the name of the log instance if so configured + if( showShortName) { + if( shortLogName==null ) { + // Cut all but the last component of the name for both styles + shortLogName = logName.substring(logName.lastIndexOf(".") + 1); + shortLogName = + shortLogName.substring(shortLogName.lastIndexOf("/") + 1); + } + buf.append(String.valueOf(shortLogName)).append(" - "); + } else if(showLogName) { + buf.append(String.valueOf(logName)).append(" - "); + } + + // Append the message + buf.append(String.valueOf(message)); + + // Append stack trace if not null + if(t != null) { + buf.append(" <"); + buf.append(t.toString()); + buf.append(">"); + + java.io.StringWriter sw= new java.io.StringWriter(1024); + java.io.PrintWriter pw= new java.io.PrintWriter(sw); + t.printStackTrace(pw); + pw.close(); + buf.append(sw.toString()); + } + + // Print to the appropriate destination + write(buf); + + } + + + /** + *

    Write the content of the message accumulated in the specified + * StringBuffer to the appropriate output destination. The + * default implementation writes to System.err.

    + * + * @param buffer A StringBuffer containing the accumulated + * text to be logged + */ + protected void write(StringBuffer buffer) { + + System.err.println(buffer.toString()); + + } + + + /** + * Is the given log level currently enabled? + * + * @param logLevel is this level enabled? + */ + protected boolean isLevelEnabled(int logLevel) { + // log level are numerically ordered so can use simple numeric + // comparison + return (logLevel >= currentLogLevel); + } + + + // -------------------------------------------------------- Log Implementation + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG. + * + * @param message to log + * @see org.apache.commons.logging.Log#debug(Object) + */ + public final void debug(Object message) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) { + log(SimpleLog.LOG_LEVEL_DEBUG, message, null); + } + } + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#debug(Object, Throwable) + */ + public final void debug(Object message, Throwable t) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) { + log(SimpleLog.LOG_LEVEL_DEBUG, message, t); + } + } + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE. + * + * @param message to log + * @see org.apache.commons.logging.Log#trace(Object) + */ + public final void trace(Object message) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) { + log(SimpleLog.LOG_LEVEL_TRACE, message, null); + } + } + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#trace(Object, Throwable) + */ + public final void trace(Object message, Throwable t) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) { + log(SimpleLog.LOG_LEVEL_TRACE, message, t); + } + } + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO. + * + * @param message to log + * @see org.apache.commons.logging.Log#info(Object) + */ + public final void info(Object message) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) { + log(SimpleLog.LOG_LEVEL_INFO,message,null); + } + } + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#info(Object, Throwable) + */ + public final void info(Object message, Throwable t) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) { + log(SimpleLog.LOG_LEVEL_INFO, message, t); + } + } + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN. + * + * @param message to log + * @see org.apache.commons.logging.Log#warn(Object) + */ + public final void warn(Object message) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) { + log(SimpleLog.LOG_LEVEL_WARN, message, null); + } + } + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#warn(Object, Throwable) + */ + public final void warn(Object message, Throwable t) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) { + log(SimpleLog.LOG_LEVEL_WARN, message, t); + } + } + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR. + * + * @param message to log + * @see org.apache.commons.logging.Log#error(Object) + */ + public final void error(Object message) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) { + log(SimpleLog.LOG_LEVEL_ERROR, message, null); + } + } + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#error(Object, Throwable) + */ + public final void error(Object message, Throwable t) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) { + log(SimpleLog.LOG_LEVEL_ERROR, message, t); + } + } + + + /** + * Log a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL. + * + * @param message to log + * @see org.apache.commons.logging.Log#fatal(Object) + */ + public final void fatal(Object message) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) { + log(SimpleLog.LOG_LEVEL_FATAL, message, null); + } + } + + + /** + * Logs a message with + * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL. + * + * @param message to log + * @param t log this cause + * @see org.apache.commons.logging.Log#fatal(Object, Throwable) + */ + public final void fatal(Object message, Throwable t) { + + if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) { + log(SimpleLog.LOG_LEVEL_FATAL, message, t); + } + } + + + /** + *

    Are debug messages currently enabled?

    + * + *

    This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger.

    + */ + public final boolean isDebugEnabled() { + + return isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG); + } + + + /** + *

    Are error messages currently enabled?

    + * + *

    This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger.

    + */ + public final boolean isErrorEnabled() { + + return isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR); + } + + + /** + *

    Are fatal messages currently enabled?

    + * + *

    This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger.

    + */ + public final boolean isFatalEnabled() { + + return isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL); + } + + + /** + *

    Are info messages currently enabled?

    + * + *

    This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger.

    + */ + public final boolean isInfoEnabled() { + + return isLevelEnabled(SimpleLog.LOG_LEVEL_INFO); + } + + + /** + *

    Are trace messages currently enabled?

    + * + *

    This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger.

    + */ + public final boolean isTraceEnabled() { + + return isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE); + } + + + /** + *

    Are warn messages currently enabled?

    + * + *

    This allows expensive operations such as String + * concatenation to be avoided when the message will be ignored by the + * logger.

    + */ + public final boolean isWarnEnabled() { + + return isLevelEnabled(SimpleLog.LOG_LEVEL_WARN); + } + + + /** + * Return the thread context class loader if available. + * Otherwise return null. + * + * The thread context class loader is available for JDK 1.2 + * or later, if certain security conditions are met. + * + * @exception LogConfigurationException if a suitable class loader + * cannot be identified. + */ + private static ClassLoader getContextClassLoader() + { + ClassLoader classLoader = null; + + if (classLoader == null) { + try { + // Are we running on a JDK 1.2 or later system? + Method method = Thread.class.getMethod("getContextClassLoader", + (Class[]) null); + + // Get the thread context class loader (if there is one) + try { + classLoader = (ClassLoader)method.invoke(Thread.currentThread(), + (Class[]) null); + } catch (IllegalAccessException e) { + ; // ignore + } catch (InvocationTargetException e) { + /** + * InvocationTargetException is thrown by 'invoke' when + * the method being invoked (getContextClassLoader) throws + * an exception. + * + * getContextClassLoader() throws SecurityException when + * the context class loader isn't an ancestor of the + * calling class's class loader, or if security + * permissions are restricted. + * + * In the first case (not related), we want to ignore and + * keep going. We cannot help but also ignore the second + * with the logic below, but other calls elsewhere (to + * obtain a class loader) will trigger this exception where + * we can make a distinction. + */ + if (e.getTargetException() instanceof SecurityException) { + ; // ignore + } else { + // Capture 'e.getTargetException()' exception for details + // alternate: log 'e.getTargetException()', and pass back 'e'. + throw new LogConfigurationException + ("Unexpected InvocationTargetException", e.getTargetException()); + } + } + } catch (NoSuchMethodException e) { + // Assume we are running on JDK 1.1 + ; // ignore + } + } + + if (classLoader == null) { + classLoader = SimpleLog.class.getClassLoader(); + } + + // Return the selected class loader + return classLoader; + } + + private static InputStream getResourceAsStream(final String name) + { + return (InputStream)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + ClassLoader threadCL = getContextClassLoader(); + + if (threadCL != null) { + return threadCL.getResourceAsStream(name); + } else { + return ClassLoader.getSystemResourceAsStream(name); + } + } + }); + } +} + diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/WeakHashtable.java b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/WeakHashtable.java new file mode 100644 index 0000000..e2d4100 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/WeakHashtable.java @@ -0,0 +1,478 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.apache.commons.logging.impl; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.*; + +/** + *

    Implementation of Hashtable that uses WeakReference's + * to hold its keys thus allowing them to be reclaimed by the garbage collector. + * The associated values are retained using strong references.

    + * + *

    This class follows the symantics of Hashtable as closely as + * possible. It therefore does not accept null values or keys.

    + * + *

    Note: + * This is not intended to be a general purpose hash table replacement. + * This implementation is also tuned towards a particular purpose: for use as a replacement + * for Hashtable in LogFactory. This application requires + * good liveliness for get and put. Various tradeoffs + * have been made with this in mind. + *

    + *

    + * Usage: typical use case is as a drop-in replacement + * for the Hashtable used in LogFactory for J2EE enviroments + * running 1.3+ JVMs. Use of this class in most cases (see below) will + * allow classloaders to be collected by the garbage collector without the need + * to call {@link org.apache.commons.logging.LogFactory#release(ClassLoader) LogFactory.release(ClassLoader)}. + *

    + * + *

    org.apache.commons.logging.LogFactory checks whether this class + * can be supported by the current JVM, and if so then uses it to store + * references to the LogFactory implementationd it loads + * (rather than using a standard Hashtable instance). + * Having this class used instead of Hashtable solves + * certain issues related to dynamic reloading of applications in J2EE-style + * environments. However this class requires java 1.3 or later (due to its use + * of java.lang.ref.WeakReference and associates). + * And by the way, this extends Hashtable rather than HashMap + * for backwards compatibility reasons. See the documentation + * for method LogFactory.createFactoryStore for more details.

    + * + *

    The reason all this is necessary is due to a issue which + * arises during hot deploy in a J2EE-like containers. + * Each component running in the container owns one or more classloaders; when + * the component loads a LogFactory instance via the component classloader + * a reference to it gets stored in the static LogFactory.factories member, + * keyed by the component's classloader so different components don't + * stomp on each other. When the component is later unloaded, the container + * sets the component's classloader to null with the intent that all the + * component's classes get garbage-collected. However there's still a + * reference to the component's classloader from a key in the "global" + * LogFactory's factories member! If LogFactory.release() + * is called whenever component is unloaded, the classloaders will be correctly + * garbage collected; this should be done by any container that + * bundles commons-logging by default. However, holding the classloader + * references weakly ensures that the classloader will be garbage collected + * without the container performing this step.

    + * + *

    + * Limitations: + * There is still one (unusual) scenario in which a component will not + * be correctly unloaded without an explicit release. Though weak references + * are used for its keys, it is necessary to use strong references for its values. + *

    + * + *

    If the abstract class LogFactory is + * loaded by the container classloader but a subclass of + * LogFactory [LogFactory1] is loaded by the component's + * classloader and an instance stored in the static map associated with the + * base LogFactory class, then there is a strong reference from the LogFactory + * class to the LogFactory1 instance (as normal) and a strong reference from + * the LogFactory1 instance to the component classloader via + * getClass().getClassLoader(). This chain of references will prevent + * collection of the child classloader.

    + * + *

    + * Such a situation occurs when the commons-logging.jar is + * loaded by a parent classloader (e.g. a server level classloader in a + * servlet container) and a custom LogFactory implementation is + * loaded by a child classloader (e.g. a web app classloader).

    + * + *

    To avoid this scenario, ensure + * that any custom LogFactory subclass is loaded by the same classloader as + * the base LogFactory. Creating custom LogFactory subclasses is, + * however, rare. The standard LogFactoryImpl class should be sufficient + * for most or all users.

    + * + * + * @author Brian Stansberry + * + * @since 1.1 + */ +public final class WeakHashtable extends Hashtable { + + /** + * The maximum number of times put() or remove() can be called before + * the map will be purged of all cleared entries. + */ + private static final int MAX_CHANGES_BEFORE_PURGE = 100; + + /** + * The maximum number of times put() or remove() can be called before + * the map will be purged of one cleared entry. + */ + private static final int PARTIAL_PURGE_COUNT = 10; + + /* ReferenceQueue we check for gc'd keys */ + private ReferenceQueue queue = new ReferenceQueue(); + /* Counter used to control how often we purge gc'd entries */ + private int changeCount = 0; + + /** + * Constructs a WeakHashtable with the Hashtable default + * capacity and load factor. + */ + public WeakHashtable() {} + + + /** + *@see Hashtable + */ + public boolean containsKey(Object key) { + // purge should not be required + Referenced referenced = new Referenced(key); + return super.containsKey(referenced); + } + + /** + *@see Hashtable + */ + public Enumeration elements() { + purge(); + return super.elements(); + } + + /** + *@see Hashtable + */ + public Set entrySet() { + purge(); + Set referencedEntries = super.entrySet(); + Set unreferencedEntries = new HashSet(); + for (Iterator it=referencedEntries.iterator(); it.hasNext();) { + Map.Entry entry = (Map.Entry) it.next(); + Referenced referencedKey = (Referenced) entry.getKey(); + Object key = referencedKey.getValue(); + Object value = entry.getValue(); + if (key != null) { + Entry dereferencedEntry = new Entry(key, value); + unreferencedEntries.add(dereferencedEntry); + } + } + return unreferencedEntries; + } + + /** + *@see Hashtable + */ + public Object get(Object key) { + // for performance reasons, no purge + Referenced referenceKey = new Referenced(key); + return super.get(referenceKey); + } + + /** + *@see Hashtable + */ + public Enumeration keys() { + purge(); + final Enumeration enumer = super.keys(); + return new Enumeration() { + public boolean hasMoreElements() { + return enumer.hasMoreElements(); + } + public Object nextElement() { + Referenced nextReference = (Referenced) enumer.nextElement(); + return nextReference.getValue(); + } + }; + } + + + /** + *@see Hashtable + */ + public Set keySet() { + purge(); + Set referencedKeys = super.keySet(); + Set unreferencedKeys = new HashSet(); + for (Iterator it=referencedKeys.iterator(); it.hasNext();) { + Referenced referenceKey = (Referenced) it.next(); + Object keyValue = referenceKey.getValue(); + if (keyValue != null) { + unreferencedKeys.add(keyValue); + } + } + return unreferencedKeys; + } + + /** + *@see Hashtable + */ + public Object put(Object key, Object value) { + // check for nulls, ensuring symantics match superclass + if (key == null) { + throw new NullPointerException("Null keys are not allowed"); + } + if (value == null) { + throw new NullPointerException("Null values are not allowed"); + } + + // for performance reasons, only purge every + // MAX_CHANGES_BEFORE_PURGE times + if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) { + purge(); + changeCount = 0; + } + // do a partial purge more often + else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) { + purgeOne(); + } + + Referenced keyRef = new Referenced(key, queue); + return super.put(keyRef, value); + } + + /** + *@see Hashtable + */ + public void putAll(Map t) { + if (t != null) { + Set entrySet = t.entrySet(); + for (Iterator it=entrySet.iterator(); it.hasNext();) { + Map.Entry entry = (Map.Entry) it.next(); + put(entry.getKey(), entry.getValue()); + } + } + } + + /** + *@see Hashtable + */ + public Collection values() { + purge(); + return super.values(); + } + + /** + *@see Hashtable + */ + public Object remove(Object key) { + // for performance reasons, only purge every + // MAX_CHANGES_BEFORE_PURGE times + if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) { + purge(); + changeCount = 0; + } + // do a partial purge more often + else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) { + purgeOne(); + } + return super.remove(new Referenced(key)); + } + + /** + *@see Hashtable + */ + public boolean isEmpty() { + purge(); + return super.isEmpty(); + } + + /** + *@see Hashtable + */ + public int size() { + purge(); + return super.size(); + } + + /** + *@see Hashtable + */ + public String toString() { + purge(); + return super.toString(); + } + + /** + * @see Hashtable + */ + protected void rehash() { + // purge here to save the effort of rehashing dead entries + purge(); + super.rehash(); + } + + /** + * Purges all entries whose wrapped keys + * have been garbage collected. + */ + private void purge() { + synchronized (queue) { + WeakKey key; + while ((key = (WeakKey) queue.poll()) != null) { + super.remove(key.getReferenced()); + } + } + } + + /** + * Purges one entry whose wrapped key + * has been garbage collected. + */ + private void purgeOne() { + + synchronized (queue) { + WeakKey key = (WeakKey) queue.poll(); + if (key != null) { + super.remove(key.getReferenced()); + } + } + } + + /** Entry implementation */ + private final static class Entry implements Map.Entry { + + private final Object key; + private final Object value; + + private Entry(Object key, Object value) { + this.key = key; + this.value = value; + } + + public boolean equals(Object o) { + boolean result = false; + if (o != null && o instanceof Map.Entry) { + Map.Entry entry = (Map.Entry) o; + result = (getKey()==null ? + entry.getKey() == null : + getKey().equals(entry.getKey())) + && + (getValue()==null ? + entry.getValue() == null : + getValue().equals(entry.getValue())); + } + return result; + } + + public int hashCode() { + + return (getKey()==null ? 0 : getKey().hashCode()) ^ + (getValue()==null ? 0 : getValue().hashCode()); + } + + public Object setValue(Object value) { + throw new UnsupportedOperationException("Entry.setValue is not supported."); + } + + public Object getValue() { + return value; + } + + public Object getKey() { + return key; + } + } + + + /** Wrapper giving correct symantics for equals and hashcode */ + private final static class Referenced { + + private final WeakReference reference; + private final int hashCode; + + /** + * + * @throws NullPointerException if referant is null + */ + private Referenced(Object referant) { + reference = new WeakReference(referant); + // Calc a permanent hashCode so calls to Hashtable.remove() + // work if the WeakReference has been cleared + hashCode = referant.hashCode(); + } + + /** + * + * @throws NullPointerException if key is null + */ + private Referenced(Object key, ReferenceQueue queue) { + reference = new WeakKey(key, queue, this); + // Calc a permanent hashCode so calls to Hashtable.remove() + // work if the WeakReference has been cleared + hashCode = key.hashCode(); + + } + + public int hashCode() { + return hashCode; + } + + private Object getValue() { + return reference.get(); + } + + public boolean equals(Object o) { + boolean result = false; + if (o instanceof Referenced) { + Referenced otherKey = (Referenced) o; + Object thisKeyValue = getValue(); + Object otherKeyValue = otherKey.getValue(); + if (thisKeyValue == null) { + result = (otherKeyValue == null); + + // Since our hashcode was calculated from the original + // non-null referant, the above check breaks the + // hashcode/equals contract, as two cleared Referenced + // objects could test equal but have different hashcodes. + // We can reduce (not eliminate) the chance of this + // happening by comparing hashcodes. + if (result == true) { + result = (this.hashCode() == otherKey.hashCode()); + } + // In any case, as our c'tor does not allow null referants + // and Hashtable does not do equality checks between + // existing keys, normal hashtable operations should never + // result in an equals comparison between null referants + } + else + { + result = thisKeyValue.equals(otherKeyValue); + } + } + return result; + } + } + + /** + * WeakReference subclass that holds a hard reference to an + * associated value and also makes accessible + * the Referenced object holding it. + */ + private final static class WeakKey extends WeakReference { + + private final Referenced referenced; + + private WeakKey(Object key, + ReferenceQueue queue, + Referenced referenced) { + super(key, queue); + this.referenced = referenced; + } + + private Referenced getReferenced() { + return referenced; + } + } +} diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/package.html b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/package.html new file mode 100644 index 0000000..5344784 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/impl/package.html @@ -0,0 +1,22 @@ + + + +

    Concrete implementations of commons-logging wrapper APIs.

    + diff --git a/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/package.html b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/package.html new file mode 100644 index 0000000..e9b32a5 --- /dev/null +++ b/vendor/commons-logging/1.1.1/java/org/apache/commons/logging/package.html @@ -0,0 +1,255 @@ + + + +

    Simple wrapper API around multiple logging APIs.

    + + +

    Overview

    + +

    This package provides an API for logging in server-based applications that +can be used around a variety of different logging implementations, including +prebuilt support for the following:

    +
      +
    • Log4J (version 1.2 or later) + from Apache's Logging project. Each named Log + instance is connected to a corresponding Log4J Logger.
    • +
    • + JDK Logging API, included in JDK 1.4 or later systems. Each named + Log instance is connected to a corresponding + java.util.logging.Logger instance.
    • +
    • LogKit from Apache's + Avalon project. Each named Log instance is + connected to a corresponding LogKit Logger.
    • +
    • NoOpLog implementation that simply swallows + all log output, for all named Log instances.
    • +
    • SimpleLog implementation that writes all + log output, for all named Log instances, to + System.err.
    • +
    + + +

    Quick Start Guide

    + +

    For those impatient to just get on with it, the following example +illustrates the typical declaration and use of a logger that is named (by +convention) after the calling class: + +

    +    import org.apache.commons.logging.Log;
    +    import org.apache.commons.logging.LogFactory;
    +
    +    public class Foo {
    +
    +        private Log log = LogFactory.getLog(Foo.class);
    +
    +        public void foo() {
    +            ...
    +            try {
    +                if (log.isDebugEnabled()) {
    +                    log.debug("About to do something to object " + name);
    +                }
    +                name.bar();
    +            } catch (IllegalStateException e) {
    +                log.error("Something bad happened to " + name, e);
    +            }
    +            ...
    +        }
    +
    + +

    Unless you configure things differently, all log output will be written +to System.err. Therefore, you really will want to review the remainder of +this page in order to understand how to configure logging for your +application.

    + + +

    Configuring the Commons Logging Package

    + + +

    Choosing a LogFactory Implementation

    + +

    From an application perspective, the first requirement is to retrieve an +object reference to the LogFactory instance that will be used +to create Log instances for this +application. This is normally accomplished by calling the static +getFactory() method. This method implements the following +discovery algorithm to select the name of the LogFactory +implementation class this application wants to use:

    +
      +
    • Check for a system property named + org.apache.commons.logging.LogFactory.
    • +
    • Use the JDK 1.3 JAR Services Discovery mechanism (see + + http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html for + more information) to look for a resource named + META-INF/services/org.apache.commons.logging.LogFactory + whose first line is assumed to contain the desired class name.
    • +
    • Look for a properties file named commons-logging.properties + visible in the application class path, with a property named + org.apache.commons.logging.LogFactory defining the + desired implementation class name.
    • +
    • Fall back to a default implementation, which is described + further below.
    • +
    + +

    If a commons-logging.properties file is found, all of the +properties defined there are also used to set configuration attributes on +the instantiated LogFactory instance.

    + +

    Once an implementation class name is selected, the corresponding class is +loaded from the current Thread context class loader (if there is one), or +from the class loader that loaded the LogFactory class itself +otherwise. This allows a copy of commons-logging.jar to be +shared in a multiple class loader environment (such as a servlet container), +but still allow each web application to provide its own LogFactory +implementation, if it so desires. An instance of this class will then be +created, and cached per class loader. + + +

    The Default LogFactory Implementation

    + +

    The Logging Package APIs include a default LogFactory +implementation class ( +org.apache.commons.logging.impl.LogFactoryImpl) that is selected if no +other implementation class name can be discovered. Its primary purpose is +to create (as necessary) and return Log instances +in response to calls to the getInstance() method. The default +implementation uses the following rules:

    +
      +
    • At most one Log instance of the same name will be created. + Subsequent getInstance() calls to the same + LogFactory instance, with the same name or Class + parameter, will return the same Log instance.
    • +
    • When a new Log instance must be created, the default + LogFactory implementation uses the following discovery + process: +
        +
      • Look for a configuration attribute of this factory named + org.apache.commons.logging.Log (for backwards + compatibility to pre-1.0 versions of this API, an attribute + org.apache.commons.logging.log is also consulted).
      • +
      • Look for a system property named + org.apache.commons.logging.Log (for backwards + compatibility to pre-1.0 versions of this API, a system property + org.apache.commons.logging.log is also consulted).
      • +
      • If the Log4J logging system is available in the application + class path, use the corresponding wrapper class + (Log4JLogger).
      • +
      • If the application is executing on a JDK 1.4 system, use + the corresponding wrapper class + (Jdk14Logger).
      • +
      • Fall back to the default simple logging implementation + (SimpleLog).
      • +
    • +
    • Load the class of the specified name from the thread context class + loader (if any), or from the class loader that loaded the + LogFactory class otherwise.
    • +
    • Instantiate an instance of the selected Log + implementation class, passing the specified name as the single + argument to its constructor.
    • +
    + +

    See the SimpleLog JavaDocs for detailed +configuration information for this default implementation.

    + + +

    Configuring the Underlying Logging System

    + +

    The basic principle is that the user is totally responsible for the +configuration of the underlying logging system. +Commons-logging should not change the existing configuration.

    + +

    Each individual Log implementation may +support its own configuration properties. These will be documented in the +class descriptions for the corresponding implementation class.

    + +

    Finally, some Log implementations (such as the one for Log4J) +require an external configuration file for the entire logging environment. +This file should be prepared in a manner that is specific to the actual logging +technology being used.

    + + +

    Using the Logging Package APIs

    + +

    Use of the Logging Package APIs, from the perspective of an application +component, consists of the following steps:

    +
      +
    1. Acquire a reference to an instance of + org.apache.commons.logging.Log, by calling the + factory method + + LogFactory.getInstance(String name). Your application can contain + references to multiple loggers that are used for different + purposes. A typical scenario for a server application is to have each + major component of the server use its own Log instance.
    2. +
    3. Cause messages to be logged (if the corresponding detail level is enabled) + by calling appropriate methods (trace(), debug(), + info(), warn(), error, and + fatal()).
    4. +
    + +

    For convenience, LogFactory also offers a static method +getLog() that combines the typical two-step pattern:

    +
    +  Log log = LogFactory.getFactory().getInstance(Foo.class);
    +
    +

    into a single method call:

    +
    +  Log log = LogFactory.getLog(Foo.class);
    +
    + +

    For example, you might use the following technique to initialize and +use a Log instance in an application component:

    +
    +import org.apache.commons.logging.Log;
    +import org.apache.commons.logging.LogFactory;
    +
    +public class MyComponent {
    +
    +  protected Log log =
    +    LogFactory.getLog(MyComponent.class);
    +
    +  // Called once at startup time
    +  public void start() {
    +    ...
    +    log.info("MyComponent started");
    +    ...
    +  }
    +
    +  // Called once at shutdown time
    +  public void stop() {
    +    ...
    +    log.info("MyComponent stopped");
    +    ...
    +  }
    +
    +  // Called repeatedly to process a particular argument value
    +  // which you want logged if debugging is enabled
    +  public void process(String value) {
    +    ...
    +    // Do the string concatenation only if logging is enabled
    +    if (log.isDebugEnabled())
    +      log.debug("MyComponent processing " + value);
    +    ...
    +  }
    +
    +}
    +
    + + diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITArtwork.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITArtwork.java new file mode 100644 index 0000000..53846c9 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITArtwork.java @@ -0,0 +1,55 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a artwork. + * + * Defines a single piece of artwork. + * + * Artwork is always associated with an individual track. + * To add a piece of artwork to a track, use IITTrack::AddArtworkFromFile(). + * The IITTrack::Artwork property + * + * To get a collection of artwork associated with a track call + * ITTrack.getArtwork(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITArtwork extends ITObject { + + public ITArtwork (Dispatch d) { + super(d); + } + + /** + * Delete this object. + */ + public void delete() { + Dispatch.call(object, "Delete"); + } + + /** + * Returns the kind of the object. + * @return Returns the kind of the object. + */ + public ITArtworkFormat getFormat() { + return ITArtworkFormat.values()[Dispatch.get(object, "Format").getInt()]; + } + + // TODO: Comments + + public boolean getIsDownloadedArtwork() { + return Dispatch.get(object, "IsDownloadedArtwork").getBoolean(); + } + + public String getDescription() { + return Dispatch.get(object, "Description").getString(); + + } + + public void SaveArtworkToFile(String filePath) { + Dispatch.call(object, "SaveArtworkToFile",filePath); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITArtworkCollection.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITArtworkCollection.java new file mode 100644 index 0000000..c1d8afa --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITArtworkCollection.java @@ -0,0 +1,55 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a collection of Artwork objects. + * + * Note that collection indices are always 1-based. + * + * You can retrieve all the Artworks defined for a source using + * ITSource.getArtwork(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITArtworkCollection { + + protected Dispatch object; + + public ITArtworkCollection(Dispatch d) { + object = d; + } + + /** + * Returns the number of playlists in the collection. + * @return Returns the number of playlists in the collection. + */ + public int getCount() { + return Dispatch.get(object, "Count").getInt(); + } + + /** + * Returns an ITArtwork object corresponding to the given index (1-based). + * @param index Index of the playlist to retrieve, must be less than or + * equal to ITArtworkCollection.getCount(). + * @return Returns an ITArtwork object corresponding to the given index. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITArtwork getItem (int index) { + Dispatch item = Dispatch.call(object, "Item", index).toDispatch(); + return new ITArtwork(item); + } + + /** + * Returns an ITArtwork object with the specified persistent ID. See the + * documentation on ITObject for more information on persistent IDs. + * @param highID The high 32 bits of the 64-bit persistent ID. + * @param lowID The low 32 bits of the 64-bit persistent ID. + * @return Returns an ITArtwork object with the specified persistent ID. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITArtwork getItemByPersistentID (int highID, int lowID) { + Dispatch item = Dispatch.call(object, "ItemByPersistentID", highID, lowID).toDispatch(); + return new ITArtwork(item); + } +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITArtworkFormat.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITArtworkFormat.java new file mode 100644 index 0000000..ed4b61e --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITArtworkFormat.java @@ -0,0 +1,13 @@ +package com.dt.iTunesController; + +/** + * Specifies the Artwork kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITArtworkFormat { + ITArtworkFormatUnknown, + ITArtworkFormatJPEG, + ITArtworkFormatPNG, + ITArtworkFormatBMP; +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITAudioCDPlaylist.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITAudioCDPlaylist.java new file mode 100644 index 0000000..bc12943 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITAudioCDPlaylist.java @@ -0,0 +1,76 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents an audio CD playlist. + * + * An audio CD playlist is always associated with an IITSource of kind + * ITSourceKindAudioCD. + * + * You can retrieve all the playlists defined for a source using + * ITSource.getPlaylists(). + * @author Steve Eyre + * @version 0.2 + */ +public class ITAudioCDPlaylist extends ITPlaylist { + + public ITAudioCDPlaylist(Dispatch d) { + super(d); + } + + /** + * Returns the audio CD's artist. + * @return Returns the audio CD's artist. + */ + public String getArtist() { + return Dispatch.get(object, "Artist").getString(); + } + + /** + * Returns true if this audio CD is a compilation album. + * @return Returns true if this audio CD is a compilation album. + */ + public boolean isCompilation() { + return Dispatch.get(object, "Compilation").getBoolean(); + } + + /** + * Returns the audio CD's composer. + * @return Returns the audio CD's composer. + */ + public String getComposer() { + return Dispatch.get(object, "Composer").getString(); + } + + /** + * Returns the total number of discs in this CD's album. + * @return Returns the total number of discs in this CD's album. + */ + public long getDiscCount() { + return Dispatch.get(object, "DiscCount").getLong(); + } + + /** + * Returns the index of the CD disc in the source album. + * @return Returns the index of the CD disc in the source album. + */ + public long getDiscNumber() { + return Dispatch.get(object, "DiscNumber").getLong(); + } + + /** + * Returns the audio CD's genre. + * @return Returns the audio CD's genre. + */ + public String getGenre() { + return Dispatch.get(object, "Genre").getString(); + } + + /** + * Reveals the CD playlist in the main browser window. + */ + public void reveal() { + Dispatch.call(object, "Reveal"); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITBrowserWindow.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITBrowserWindow.java new file mode 100644 index 0000000..16dc6cf --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITBrowserWindow.java @@ -0,0 +1,45 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents the main browser window. + * + * You can retrieve the main browser window using + * iTunes.BrowserWindow(). + * + * @author Steve Eyre + * @version 0.2 + */ + +public class ITBrowserWindow extends ITWindow { + + public ITBrowserWindow (Dispatch d) { + super(d); + } + + /** + * Returns the kind of the object. + * @return Returns the kind of the object. + */ + public boolean getMiniPlayer() { + return Dispatch.get(object, "MiniPlayer").getBoolean(); + } + + // TODO: Comments + + public ITTrackCollection getSelectedTracks() { + Dispatch collection = Dispatch.call(object, "SelectedTracks").getDispatch(); + return new ITTrackCollection(collection); + } + + public ITPlaylist getSelectedPlaylist() { + Dispatch playlist = Dispatch.get(object, "SelectedPlaylist").toDispatch(); + return new ITPlaylist(playlist); + } + + public void setSelectedPlaylist(ITPlaylist playlist) { + Dispatch dispatchRef = playlist.fetchDispatch(); + Dispatch.put(object, "SelectedPlaylist", dispatchRef); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITCOMDisabledReason.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITCOMDisabledReason.java new file mode 100644 index 0000000..500280c --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITCOMDisabledReason.java @@ -0,0 +1,12 @@ +package com.dt.iTunesController; + +/** + * Specifies the reason the COM interface is being disabled. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITCOMDisabledReason { + ITCOMDisabledReasonOther, + ITCOMDisabledReasonDialog, + ITCOMDisabledReasonQuitting; +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITEQPreset.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITEQPreset.java new file mode 100644 index 0000000..1d00cfb --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITEQPreset.java @@ -0,0 +1,236 @@ +package com.dt.iTunesController; + +import com.jacob.com.Dispatch; + +/** + * Represents an equalizer preset. + * You can retrieve or set the currently selected EQ preset using the + * iTunes.getCurrentEQPreset() method. + * @author Steve Eyre + * @version 0.2 + */ +public class ITEQPreset { + + protected Dispatch object; + + public ITEQPreset(Dispatch d) { + object = d; + } + + /** + * Returns the name of the EQ Preset (e.g. "Acoustic"). + * @return Returns the name of the EQ Preset (e.g. "Acoustic"). + */ + public String getName() { + return Dispatch.get(object, "Name").getString(); + } + + /** + * Returns true if the EQ preset can be modified. + * @return True if the EQ preset can be modified. + */ + public boolean getModifiable() { + return Dispatch.get(object, "Modifiable").getBoolean(); + } + + /** + * Set the equalizer preamp level (-12.0 db to +12.0 db). + * @param level The new equalizer preamp level (-12.0 db to +12.0 db). + */ + public void setPreamp(double level) { + Dispatch.put(object, "Preamp", level); + } + + /** + * Returns the equalizer preamp level (-12.0db to +12.0db). + * @return Returns the equalizer preamp level (-12.0db to +12.0db). + */ + public double getPreamp() { + return Dispatch.get(object, "Preamp").getDouble(); + } + + /** + * Set the equalizer 32Hz level (-12.0 db to +12.0 db). + * @param level The new equalizer 32Hz level (-12.0 db to +12.0db). + */ + public void setBand1(double level) { + Dispatch.put(object, "Band1", level); + } + + /** + * Returns the equalizer 32Hz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 32Hz level (-12.0 db to +12.0 db). + */ + public double getBand1() { + return Dispatch.get(object, "Band1").getDouble(); + } + + /** + * Set the equalizer 64Hz level (-12.0 db to +12.0 db). + * @param level The new equalizer 64Hz level (-12.0 db to +12.0db). + */ + public void setBand2(double level) { + Dispatch.put(object, "Band2", level); + } + + /** + * Returns the equalizer 64Hz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 64Hz level (-12.0 db to +12.0 db). + */ + public double getBand2() { + return Dispatch.get(object, "Band2").getDouble(); + } + + /** + * Set the equalizer 125Hz level (-12.0 db to +12.0 db). + * @param level The new equalizer 125Hz level (-12.0 db to +12.0db). + */ + public void setBand3(double level) { + Dispatch.put(object, "Band3", level); + } + + /** + * Returns the equalizer 125Hz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 125Hz level (-12.0 db to +12.0 db). + */ + public double getBand3() { + return Dispatch.get(object, "Band3").getDouble(); + } + + /** + * Set the equalizer 250Hz level (-12.0 db to +12.0 db). + * @param level The new equalizer 250Hz level (-12.0 db to +12.0db). + */ + public void setBand4(double level) { + Dispatch.put(object, "Band4", level); + } + + /** + * Returns the equalizer 250Hz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 250Hz level (-12.0 db to +12.0 db). + */ + public double getBand4() { + return Dispatch.get(object, "Band4").getDouble(); + } + + /** + * Set the equalizer 500Hz level (-12.0 db to +12.0 db). + * @param level The new equalizer 500Hz level (-12.0 db to +12.0db). + */ + public void setBand5(double level) { + Dispatch.put(object, "Band5", level); + } + + /** + * Returns the equalizer 500Hz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 500Hz level (-12.0 db to +12.0 db). + */ + public double getBand5() { + return Dispatch.get(object, "Band5").getDouble(); + } + + /** + * Set the equalizer 1KHz level (-12.0 db to +12.0 db). + * @param level The new equalizer 1KHz level (-12.0 db to +12.0db). + */ + public void setBand6(double level) { + Dispatch.put(object, "Band6", level); + } + + /** + * Returns the equalizer 1KHz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 1KHz level (-12.0 db to +12.0 db). + */ + public double getBand6() { + return Dispatch.get(object, "Band6").getDouble(); + } + + /** + * Set the equalizer 2KHz level (-12.0 db to +12.0 db). + * @param level The new equalizer 2KHz level (-12.0 db to +12.0db). + */ + public void setBand7(double level) { + Dispatch.put(object, "Band7", level); + } + + /** + * Returns the equalizer 2KHz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 2KHz level (-12.0 db to +12.0 db). + */ + public double getBand7() { + return Dispatch.get(object, "Band7").getDouble(); + } + + /** + * Set the equalizer 4KHz level (-12.0 db to +12.0 db). + * @param level The new equalizer 4KHz level (-12.0 db to +12.0db). + */ + public void setBand8(double level) { + Dispatch.put(object, "Band8", level); + } + + /** + * Returns the equalizer 4KHz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 4KHz level (-12.0 db to +12.0 db). + */ + public double getBand8() { + return Dispatch.get(object, "Band8").getDouble(); + } + + /** + * Set the equalizer 8KHz level (-12.0 db to +12.0 db). + * @param level The new equalizer 8KHz level (-12.0 db to +12.0db). + */ + public void setBand9(double level) { + Dispatch.put(object, "Band9", level); + } + + /** + * Returns the equalizer 8KHz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 8KHz level (-12.0 db to +12.0 db). + */ + public double getBand9() { + return Dispatch.get(object, "Band9").getDouble(); + } + + /** + * Set the equalizer 16KHz level (-12.0 db to +12.0 db). + * @param level The new equalizer 16KHz level (-12.0 db to +12.0db). + */ + public void setBand10(double level) { + Dispatch.put(object, "Band10", level); + } + + /** + * Returns the equalizer 16KHz level (-12.0 db to +12.0 db). + * @return Returns the equalizer 16KHz level (-12.0 db to +12.0 db). + */ + public double getBand10() { + return Dispatch.get(object, "Band10").getDouble(); + } + + /** + * Delete this EQ Preset. + * Any EQ preset can be deleted, including built-in presets, except for the + * Manual preset. + * @param updateAllTracks If true, any tracks that use this EQ preet will be + * set to have no assigned EQ preset. + */ + public void delete(boolean updateAllTracks) { + Dispatch.call(object, "Delete", updateAllTracks); + } + + /** + * Rename this EQ Preset. + * The name of any EQ preset can be changed, including built-in presets, + * except for the Manual preset. + * EQ preset names cannot start with leading spaces. If you specify a name + * that starts with leading spaces they will be stripped out. + * @param updateAllTracks If true, any tracks that use this EQ preet will be + * updated with the new preset name. + */ + public void rename(String newName, boolean updateAllTracks) { + Dispatch.call(object, "Rename", newName, updateAllTracks); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITFileOrCDTrack.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITFileOrCDTrack.java new file mode 100644 index 0000000..570896c --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITFileOrCDTrack.java @@ -0,0 +1,39 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a file or CD track. + * @author Steve Eyre + * @version 0.2 + */ +public class ITFileOrCDTrack extends ITTrack { + + public ITFileOrCDTrack (Dispatch d) { + super(d); + } + + /** + * Reveals the track in the main browser window. + */ + public void reveal() { + Dispatch.call(object, "Reveal"); + } + + public ITVideoKind getVideoKind() { + return ITVideoKind.values()[Dispatch.get(object, "VideoKind").getInt()]; + } + + public ITRatingKind getRatingKind() { + return ITRatingKind.values()[Dispatch.get(object, "RatingKind").getInt()]; + } + + public String getLocation() { + return Dispatch.get(object, "Location").getString(); + } + + public ITArtworkCollection getArtworks() { + Dispatch artworks = Dispatch.get(object, "Artwork").toDispatch(); + return new ITArtworkCollection(artworks); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITLibraryPlaylist.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITLibraryPlaylist.java new file mode 100644 index 0000000..c19cba8 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITLibraryPlaylist.java @@ -0,0 +1,20 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a library playlist. + * + * A library playlist consists of all the tracks in a user's library. + * + * For convenience, you can retrieve the main library playlist using + * iTunes.getLibraryPlaylist(). + * @author Steve Eyre + * @version 0.2 + */ +public class ITLibraryPlaylist extends ITPlaylist { + + public ITLibraryPlaylist(Dispatch d) { + super(d); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITObject.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITObject.java new file mode 100644 index 0000000..27475fd --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITObject.java @@ -0,0 +1,112 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Defines a source, playlist or track. + * + * An ITObject uniquely identifies a source, playlist, or track in iTunes using + * four separate IDs. These are runtime IDs, they are only valid while the + * current instance of iTunes is running. + * + * As of iTunes 7.7, you can also identify an ITObject using a 64-bit persistent + * ID, which is valid across multiple invocations of iTunes. + * + * The main use of the ITObject interface is to allow clients to track iTunes + * database changes using + * iTunesEventsInterface.onDatabaseChangedEvent(). + * + * You can retrieve an ITObject with a specified runtime ID using + * iTunes.getITObjectByID(). + * + * An ITObject will always have a valid, non-zero source ID. + * + * An ITObject corresponding to a playlist or track will always have a valid + * playlist ID. The playlist ID will be zero for a source. + * + * An ITObject corresponding to a track will always have a valid track and + * track database ID. These IDs will be zero for a source or playlist. + * + * A track ID is unique within the track's playlist. A track database ID is + * unique across all playlists. For example, if the same music file is in two + * different playlists, each of the tracks could have different track IDs, but + * they will have the same track database ID. + * + * An ITObject also has a 64-bit persistent ID which can be used to identify + * the ITObject across multiple invocations of iTunes. + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITObject { + + protected Dispatch object; + + public ITObject(Dispatch d) { + object = d; + } + + /** + * Returns the JACOB Dispatch object for this object. + * @return Returns the JACOB Dispatch object for this object. + */ + public Dispatch fetchDispatch() { + return object; + } + + /** + * Set the name of the object. + * @param name The new name of the object. + */ + public void setName (String name) { + Dispatch.put(object, "Name", name); + } + + /** + * Returns the name of the object. + * @return Returns the name of the object. + */ + public String getName() { + return Dispatch.get(object, "Name").getString(); + } + + /** + * Returns the index of the object in internal application order. + * @return The index of the object in internal application order. + */ + public int getIndex() { + return Dispatch.get(object, "Index").getInt(); + } + + /** + * Returns the ID that identifies the source. + * @return Returns the ID that identifies the source. + */ + public int getSourceID() { + return Dispatch.get(object, "SourceID").getInt(); + } + + /** + * Returns the ID that identifies the playlist. + * @return Returns the ID that identifies the playlist. + */ + public int getPlaylistID() { + return Dispatch.get(object, "PlaylistID").getInt(); + } + + /** + * Returns the ID that identifies the track within the playlist. + * @return Returns the ID that identifies the track within the playlist. + */ + public int getTrackID() { + return Dispatch.get(object, "TrackID").getInt(); + } + + /** + * Returns the ID that identifies the track, independent of its playlist. + * @return Returns the ID that identifies the track, independent of its playlist. + */ + public int getTrackDatabaseID() { + return Dispatch.get(object, "TrackDatabaseID").getInt(); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITObjectPersistentID.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITObjectPersistentID.java new file mode 100644 index 0000000..e5c674b --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITObjectPersistentID.java @@ -0,0 +1,53 @@ +package com.dt.iTunesController; + +/** + * Simple utility wrapper class to represent the persistent object identity + * ID numbers. Use the getHigh() and getLow() methods individually to get + * each ID, or the combined hex string through toString(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITObjectPersistentID { + + private long High; + private long Low; + private String hexString; + + /** + * Create the ITObjectPersistentID. This class is not intended to be created + * manually, and this function should only be used by classes implementing + * this utility. + * @param high The High Persistent ID + * @param low The Low Persistent ID + */ + public ITObjectPersistentID(long high, long low) { + this.High=high; + this.Low=low; + this.hexString = String.format("%8s%8s",Long.toHexString(this.High),Long.toHexString(this.Low)).toUpperCase().replace(' ','0'); + } + + /** + * Returns the high persistent ID. + * @return The high persistent ID. + */ + public long getHigh() { + return this.High; + } + + /** + * Returns the low persistent ID. + * @return The low persistent ID. + */ + public long getLow() { + return this.Low; + } + + /** + * Return a string representation (in hex) of the persistent IDs. + * @return String representation of the persistent IDs. + */ + public String toString() { + return this.hexString; + } +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITOperationStatus.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITOperationStatus.java new file mode 100644 index 0000000..cf764aa --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITOperationStatus.java @@ -0,0 +1,62 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents the status of an asynchronous add or convert operation. + * + * When a track is added using TLibraryPlaylist.addFile(), + * ITLibraryPlaylist.AddFiles(), IITUserPlaylist.addFile(), or + * ITUserPlaylist.addFiles(), the add may not complete immediately if iTunes + * needs to make a copy of the file. + * + * Similarly, when converting or importing a file or track using + * iTunes.convertFile(), iTunes.convertFiles(), + * iTunes.convertTrack() or iTunes.convertTracks(), + * the conversion will never complete immediately. + * + * These methods return an ITOperationStatus object, which can be + * polled todetermine when the operation is done. This object will also return + * the collection of newly added or converted tracks. + * + * As of version 1.1 of the iTunes type library, you should use + * iTunes.convertFile2(), iTunes.convertFiles2(), + * iTunes.convertTrack2() or iTunes.convertTracks2() + * instead of the original convert methods. These new methods return an + * ITConvertOperationStatus object to allow clients to retrieve + * additional conversion progress information. + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITOperationStatus { + + protected Dispatch object; + + public ITOperationStatus(Dispatch d) { + object = d; + } + + /** + * Returns true if the operation is still in progress. + * You cannot retrieve the ITOperationStatus.getTracks() + * property until the operation completes. + * @return Returns true if the operation is still in progress. + */ + public boolean getInProgress() { + return Dispatch.get(object, "InProgress").getBoolean(); + } + + /** + * Returns a collection containing the tracks that were generated by the + * operation. + * You cannot retrieve this property until + * ITOperationStatus.getInProgress() returns false + * @return Returns a collection containing the tracks that were generated by + * the operation. + */ + public ITTrackCollection getTracks() { + Dispatch tracks = Dispatch.get(object, "Tracks").toDispatch(); + return new ITTrackCollection(tracks); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlayerState.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlayerState.java new file mode 100644 index 0000000..4be2a70 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlayerState.java @@ -0,0 +1,13 @@ +package com.dt.iTunesController; + +/** + * Specifies the state of the player. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITPlayerState { + ITPlayerStateStopped, + ITPlayerStatePlaying, + ITPlayerStateFastForward, + ITPlayerStateRewind; +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylist.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylist.java new file mode 100644 index 0000000..23bf2b9 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylist.java @@ -0,0 +1,154 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a playlist. + * + * A playlist is always associated with an ITSource. + * + * You can retrieve all the playlists defined for a source using + * ITSource.getPlaylists(). + * + * For convenience, you can retrieve the main library playlist using + * iTunes.getLibraryPlaylist(). + * + * You can create a new playlist using iTunes.createPlaylist(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITPlaylist extends ITObject { + + public ITPlaylist (Dispatch d) { + super(d); + } + + /** + * Delete this object. + */ + public void delete() { + Dispatch.call(object, "Delete"); + } + + /** + * Start playing the first track in this object. + */ + public void playFirstTrack() { + Dispatch.call(object, "PlayFirstTrack"); + } + + /** + * Print this object. + * @param showPrintDialog If true, display the print dialog. + * @param printKind The printout kind. + * @param theme The name of the theme to use. This corresponds to the name + * of a Theme combo box item in the print dialog for the specified printKind + * (e.g. "Track length"). This string cannot be longer than 255 characters, + * but it may be empty. + */ + public void print(boolean showPrintDialog, ITPlaylistPrintKind printKind, String theme) { + Dispatch.call(object, "Print", showPrintDialog, printKind.ordinal(), theme); + } + + /** + * Returns a collection containing the tracks with the specified text. + * @param searchText The text to search for. This string cannot be longer + * than 255 chracters. + * @param searchFields Specifies which fields of each track should be + * searched for searchText. + * @return Collection of IITTrack objects. This will be NULL if no tracks + * meet the search criteria. + */ + public ITTrackCollection search (String searchText, ITPlaylistSearchField searchFields) { + Dispatch collection = Dispatch.call(object, "Search", searchText, searchFields.ordinal()).getDispatch(); + return new ITTrackCollection(collection); + } + + /** + * Returns the kind of the object. + * @return Returns the kind of the object. + */ + public ITPlaylistKind getKind() { + return ITPlaylistKind.values()[Dispatch.get(object, "Kind").getInt()]; + } + + /** + * Returns an ITSource object corresponding to the source that contains the + * object. + * @return Returns an ITSource object corresponding to the source that + * contains the object. + */ + public ITSource getSource() { + Dispatch source = Dispatch.get(object, "Source").toDispatch(); + return new ITSource(source); + } + + /** + * Returns the total length of all songs in the object (in seconds). + * @return Returns the total length of all songs in the object (in + * seconds). + */ + public int getDuration() { + return Dispatch.get(object, "Duration").getInt(); + } + + /** + * Set whether songs in the object should be played in random order. + * @param shouldShuffle True if songs in the object should be played in + * random order. + */ + public void setShuffle(boolean shouldShuffle) { + Dispatch.put(object, "Shuffle", shouldShuffle); + } + + /** + * Returns the total size of all songs in the object (in bytes). + * @return Returns the total size of all songs in the object (in bytes). + */ + public double getSize() { + return Dispatch.get(object, "Size").getDouble(); + } + + /** + * Sets the playback repeat mode. + * @param repeatMode The new playback repeat mode. + */ + public void setSongRepeat(ITPlaylistRepeatMode repeatMode) { + Dispatch.put(object, "SongRepeat", repeatMode.ordinal()); + } + + /** + * Returns the playback repeat mode. + * @return Returns the playback repeat mode. + */ + public ITPlaylistRepeatMode getSongRepeat() { + return ITPlaylistRepeatMode.values()[Dispatch.get(object, "SongRepeat").getInt()]; + } + + /** + * Returns the total length of all songs in the object (in MM:SS format). + * @return Returns the total length of all songs in the object (in + * MM:SS format). + */ + public String getTime() { + return Dispatch.get(object, "Time").getString(); + } + + /** + * Returns true if the object is visible in the sources list. + * @return True if the object is visible in the sources list. + */ + public boolean getVisible() { + return Dispatch.get(object, "Visible").getBoolean(); + } + + /** + * Returns a collection containing the tracks in this object. + * @return Collection of ITTrack objects. + */ + public ITTrackCollection getTracks() { + Dispatch tracks = Dispatch.get(object, "Tracks").toDispatch(); + return new ITTrackCollection(tracks); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistCollection.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistCollection.java new file mode 100644 index 0000000..3717735 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistCollection.java @@ -0,0 +1,67 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a collection of playlist objects. + * + * Note that collection indices are always 1-based. + * + * You can retrieve all the playlists defined for a source using + * ITSource.getPlaylists(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITPlaylistCollection { + + protected Dispatch object; + + public ITPlaylistCollection(Dispatch d) { + object = d; + } + + /** + * Returns the number of playlists in the collection. + * @return Returns the number of playlists in the collection. + */ + public int getCount() { + return Dispatch.get(object, "Count").getInt(); + } + + /** + * Returns an ITPlaylist object corresponding to the given index (1-based). + * @param index Index of the playlist to retrieve, must be less than or + * equal to ITPlaylistCollection.getCount(). + * @return Returns an ITPlaylist object corresponding to the given index. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITPlaylist getItem (int index) { + Dispatch item = Dispatch.call(object, "Item", index).toDispatch(); + return new ITPlaylist(item); + } + + /** + * Returns an ITPlaylist object withthe specified name. + * @param name The name of the playlist to retrieve. + * @return Returns an ITPlaylist object corresponding to the given index. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITPlaylist ItemByName (String name) { + Dispatch item = Dispatch.call(object, "ItemByName", name).toDispatch(); + return new ITPlaylist(item); + } + + /** + * Returns an ITPlaylist object with the specified persistent ID. See the + * documentation on ITObject for more information on persistent IDs. + * @param highID The high 32 bits of the 64-bit persistent ID. + * @param lowID The low 32 bits of the 64-bit persistent ID. + * @return Returns an ITPlaylist object with the specified persistent ID. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITPlaylist getItemByPersistentID (int highID, int lowID) { + Dispatch item = Dispatch.call(object, "ItemByPersistentID", highID, lowID).toDispatch(); + return new ITPlaylist(item); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistKind.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistKind.java new file mode 100644 index 0000000..e6f685f --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistKind.java @@ -0,0 +1,15 @@ +package com.dt.iTunesController; + +/** + * Specifies the playlist kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITPlaylistKind { + ITPlaylistKindUnknown, + ITPlaylistKindLibrary, + ITPlaylistKindUser, + ITPlaylistKindCD, + ITPlaylistKindDevice, + ITPlaylistKindRadioTuner; +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistPrintKind.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistPrintKind.java new file mode 100644 index 0000000..6fc8ef8 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistPrintKind.java @@ -0,0 +1,14 @@ +package com.dt.iTunesController; + +/** + * Specifies the kind of playlist printout. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITPlaylistPrintKind { + + ITPlaylistPrintKindPlaylist, + ITPlaylistPrintKindAlbumlist, + ITPlaylistPrintKindInsert; + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistRepeatMode.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistRepeatMode.java new file mode 100644 index 0000000..4b6fc16 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistRepeatMode.java @@ -0,0 +1,14 @@ +package com.dt.iTunesController; + +/** + * Specifies the playlist playback repeat mode. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITPlaylistRepeatMode { + + ITPlaylistRepeatModeOff, + ITPlaylistRepeatModeOne, + ITPlaylistRepeatModeAll; + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistSearchField.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistSearchField.java new file mode 100644 index 0000000..420b305 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITPlaylistSearchField.java @@ -0,0 +1,16 @@ +package com.dt.iTunesController; + +/** + * Specifies the fields in each track that will be searched by + * ITPlaylist.search(). + * @author Steve Eyre + * @version 0.2 + */ +public enum ITPlaylistSearchField { + ITPlaylistSearchFieldAll, + ITPlaylistSearchFieldVisible, + ITPlaylistSearchFieldArtists, + ITPlaylistSearchFieldAlbums, + ITPlaylistSearchFieldComposers, + ITPlaylistSearchFieldSongNames; +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITRatingKind.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITRatingKind.java new file mode 100644 index 0000000..7d1cb22 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITRatingKind.java @@ -0,0 +1,11 @@ +package com.dt.iTunesController; + +/** + * Specifies the rating kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITRatingKind { + ITRatingKindUser, + ITRatingKindComputed; +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITSource.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITSource.java new file mode 100644 index 0000000..b0d93fc --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITSource.java @@ -0,0 +1,51 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents an entry in the Source list (music library, CD, device, etc.). + * You can retrieve all the sources using iTunes.getSources(). + * @author Steve Eyre + * @version 0.2 + */ +public class ITSource extends ITObject { + + public ITSource(Dispatch d) { + super(d); + } + + /** + * Returns the kind of the source. + * @return Returns the kind of the source. + */ + public ITSourceKind getKind() { + return ITSourceKind.values()[Dispatch.get(object, "Kind").getInt()]; + } + + /** + * Returns the total size of the source, if it has a fixed size. + * @return Returns the total size of the source, if it has a fixed size. + */ + public double getCapacity() { + return Dispatch.get(object, "Capacity").getDouble(); + } + + /** + * Returns the free space on the source, if it has a fixed size. + * @return Returns the free space on the source, if it has a fixed size. + */ + public double getFreespace() { + return Dispatch.get(object, "Freespace").getDouble(); + } + + /** + * Returns a collection containing the playlists in this source. + * The source's primary playlist is always the first playlist in the + * collection. + * @return Collection of IITPlaylist objects. + */ + public ITPlaylistCollection getPlaylists() { + Dispatch playlists = Dispatch.get(object, "Playlists").toDispatch(); + return new ITPlaylistCollection(playlists); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITSourceCollection.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITSourceCollection.java new file mode 100644 index 0000000..357bdec --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITSourceCollection.java @@ -0,0 +1,66 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a collection of source objects. + * + * Note that collection indices are always 1-based. + * + * You can retrieve all the sources using ITSource.getSources(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITSourceCollection { + + protected Dispatch object; + + public ITSourceCollection(Dispatch d) { + object = d; + } + + /** + * Returns the number of sources in the collection. + * @return Returns the number of sources in the collection. + */ + public int getCount() { + return Dispatch.get(object, "Count").getInt(); + } + + /** + * Returns an ITSource object corresponding to the given index (1-based). + * @param index Index of the source to retrieve, must be less than or + * equal to ITSourceCollection.getCount(). + * @return Returns an ITSource object corresponding to the given index. + * Will be set to NULL if no source could be retrieved. + */ + public ITSource getItem (int index) { + Dispatch item = Dispatch.call(object, "Item", index).toDispatch(); + return new ITSource(item); + } + + /** + * Returns an ITSource object withthe specified name. + * @param name The name of the source to retrieve. + * @return Returns an ITSource object corresponding to the given index. + * Will be set to NULL if no source could be retrieved. + */ + public ITSource getItemByName (String name) { + Dispatch item = Dispatch.call(object, "ItemByName", name).toDispatch(); + return new ITSource(item); + } + + /** + * Returns an ITSource object with the specified persistent ID. See the + * documentation on ITObject for more information on persistent IDs. + * @param highID The high 32 bits of the 64-bit persistent ID. + * @param lowID The low 32 bits of the 64-bit persistent ID. + * @return Returns an ITSource object with the specified persistent ID. + * Will be set to NULL if no source could be retrieved. + */ + public ITSource getItemByPersistentID (int highID, int lowID) { + Dispatch item = Dispatch.call(object, "ItemByPersistentID", highID, lowID).toDispatch(); + return new ITSource(item); + } + +} \ No newline at end of file diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITSourceKind.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITSourceKind.java new file mode 100644 index 0000000..f332249 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITSourceKind.java @@ -0,0 +1,17 @@ +package com.dt.iTunesController; + +/** + * Specifies the source kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITSourceKind { + ITSourceKindUnknown, + ITSourceKindLibrary, + ITSourceKindIPod, + ITSourceKindAudioCD, + ITSourceKindMP3CD, + ITSourceKindDevice, + ITSourceKindRadioTuner, + ITSourceKindSharedLibrary; +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITTrack.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITTrack.java new file mode 100644 index 0000000..0046c7e --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITTrack.java @@ -0,0 +1,492 @@ +package com.dt.iTunesController; +import com.jacob.com.*; +import java.util.Date; + +/** + * Represents a track. + * + * A track represents a song in a single playlist. A song may be in more than + * one playlist, in which case it would be represented by multiple tracks. + * + * You can retrieve the currently targeted (playing) track using + * iTunes.getCurrentTrack(). + * + * Typically, an ITrack is accessed through an ITTrackCollection. + * + * You can retrieve all the tracks defined for a playlist using + * ITPlaylist.getTracks(). + * + * You can retrieve the currently selected track or tracks using + * iTunes.getSelectedTracks(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITTrack extends ITObject { + + public ITTrack (Dispatch d) { + super(d); + } + + /** + * Delete this object. + */ + public void delete() { + Dispatch.call(object, "Delete"); + } + + /** + * Start playing this object. + */ + public void play() { + Dispatch.call(object, "Play"); + } + + /** + * Set the name of the album containing the object.; + * @param album The new name of the album containing the object. + */ + public void setAlbum(String album) { + Dispatch.put(object, "Album", album); + } + + /** + * Returns the name of the album containing the object. + * @return Returns the name of the album containing the object. + */ + public String getAlbum() { + return Dispatch.get(object, "Album").getString(); + } + + /** + * Set the name of the artist/source of the object. + * @param artist The new artist/source of the object. + */ + public void setArtist(String artist) { + Dispatch.put(object, "Artist", artist); + } + + /** + * Returns the name of the artist/source of the object. + * @return Returns the name of the artist/source of the object. + */ + public String getArtist() { + return Dispatch.get(object, "Artist").getString(); + } + + /** + * Returns the bit rate of the object (in kbps). + * @return Returns the bit rate of the object (in kbps). + */ + public int getBitRate() { + return Dispatch.get(object, "BitRate").getInt(); + } + + /** + * Set the tempo of the object (in beats per minute). + * @param beatsPerMinute The new tempo of the object (in beats per minute). + */ + public void setBPM(int beatsPerMinute) { + Dispatch.put(object, "BPM", beatsPerMinute); + } + + /** + * Returns the tempo of the object (in beats per minute). + * @return Returns the tempo of the object (in beats per minute). + */ + public int getBPM() { + return Dispatch.get(object, "BPM").getInt(); + } + + /** + * Set freeform notes about the object. + * @param comment The new freeform notes about the object. + */ + public void setComment(String comment) { + Dispatch.put(object, "Comment", comment); + } + + /** + * Returns freeform notes about the object. + * @return Returns freeform notes about the object. + */ + public String getComment() { + return Dispatch.get(object, "Comment").getString(); + } + + /** + * Set whether this object is from a compilation album. + * @param isCompilation True if this object should be from a compilation album. + */ + public void setCompilation(boolean isCompilation) { + Dispatch.put(object, "Compilation", isCompilation); + } + + /** + * Returns true if this object is from a compilation album. + * @return Returns true if this object is from a compilation album. + */ + public boolean getCompilation() { + return Dispatch.get(object, "Compilation").getBoolean(); + } + + /** + * Set the composer of the object. + * @param composer The new composer of the object. + */ + public void setComposer (String composer) { + Dispatch.put(object, "Composer", composer); + } + + /** + * Returns the composer of the object. + * @return Returns the composer of the object. + */ + public String getComposer() { + return Dispatch.get(object, "Composer").getString(); + } + + /** + * Returns the date the object was added to the playlist. + * @return Returns the date the object was added to the playlist. + */ + public Date getDateAdded() { + return Dispatch.get(object, "DateAdded").getJavaDate(); + } + + /** + * Set the total number of discs in the source album. + * @param discCount The new total number of discs in the source album. + */ + public void setDiscCount (int discCount) { + Dispatch.put(object, "DiscCount", discCount); + } + + /** + * Returns the total number of discs in the source album. + * @return Returns the total number of discs in the source album. + */ + public int getDiscCount() { + return Dispatch.get(object, "DiscCount").getInt(); + } + + /** + * Set the index of the disc containing the object on the source album. + * @param discNumber The new index of the disc containing the object on the + * source album. + */ + public void setDiscNumber (int discNumber) { + Dispatch.put(object, "DiscNumber", discNumber); + } + + /** + * Returns the index of the disc containing the object on the source album. + * @return Returns the index of the disc containing the object on the source + * album. + */ + public int getDiscNumber() { + return Dispatch.get(object, "DiscNumber").getInt(); + } + + /** + * Returns the length of the object (in seconds). + * @return Returns the length of the object (in seconds). + */ + public int getDuration() { + return Dispatch.get(object, "Duration").getInt(); + } + + /** + * Set whether this object is checked for playback. + * @param shouldBeEnabled True if the object should be checked for playback. + */ + public void setEnabled (boolean shouldBeEnabled) { + Dispatch.put(object, "Enabled", shouldBeEnabled); + } + + /** + * Returns true if the object is checked for playback. + * @return Returns true if the object is checked for playback. + */ + public boolean getEnabled() { + return Dispatch.get(object, "Enabled").getBoolean(); + } + + /** + * Set the name of the EQ preset of the object. + * @param eq The new name of the EQ preset of the object. + */ + public void setEQ (String eq) { + Dispatch.put(object, "EQ", eq); + } + + /** + * Returns the name of the EQ preset of the object. + * @return Returns the name of the EQ preset of the object. + */ + public String getEQ() { + return Dispatch.get(object, "EQ").getString(); + } + + /** + * Set the stop time of the object (in seconds). + * @param finish The new stop time of the object (in seconds). + */ + public void setFinish(int finish) { + Dispatch.put(object, "Finish", finish); + } + + /** + * Returns the stop time of the object (in seconds). + * @return Returns the stop time of the object (in seconds). + */ + public int getFinish() { + return Dispatch.get(object, "Finish").getInt(); + } + + /** + * Returns the music/audio genre (category) of the object. + * @param genre Returns the music/audio genre (category) of the object. + */ + public void setGenre(String genre) { + Dispatch.put(object, "Genre", genre); + } + + /** + * Set the music/audio genre (category) of the object. + * @return The new music/audio genre (category) of the object. + */ + public String getGenre() { + return Dispatch.get(object, "Genre").getString(); + } + + /** + * Set the grouping (piece) of the object. + * Generally used to denote movements within classical work. + * @param grouping The new grouping (piece) of the object. + */ + public void setGrouping (String grouping) { + Dispatch.put(object, "Grouping", grouping); + } + + /** + * Returns the grouping (piece) of the object. + * Generally used to denote movements within classical work. + * @return Returns the grouping (piece) of the object. + */ + public String getGrouping() { + return Dispatch.get(object, "Grouping").getString(); + } + + public ITTrackKind getKind() { + return ITTrackKind.values()[Dispatch.get(object, "Kind").getInt()]; + } + + /** + * Returns the text description of the object (e.g. "AAC audio file"). + * @return Returns the text description of the object (e.g. "AAC audio file"). + */ + public String getKindAsString() { + return Dispatch.get(object, "KindAsString").getString(); + } + + /** + * Returns the modification date of the content of the object. + * @return Returns the modification date of the content of the object. + */ + public Date getModificationDate() { + return Dispatch.get(object, "ModificationDate").getJavaDate(); + } + + /** + * Set the number of times the object has been played. This property cannot + * be set if the object is not playable (e.g. a PDF file). + * @param playedCount The new number of times the object has been played. + */ + public void setPlayedCount (int playedCount) { + Dispatch.put(object, "PlayedCount", playedCount); + } + + /** + * Returns the number of times the object has been played. + * @return Returns the number of times the object has been played. + */ + public int getPlayedCount() { + return Dispatch.get(object, "PlayedCount").getInt(); + } + + /** + * Set the date and time the object was last played. This property cannot be + * set if the object is not playable (e.g. a PDF file). + * A value of zero means no played date. + * @param playedDate The new date and time the object was last played. + */ + public void setPlayedDate (Date playedDate) { + Dispatch.put(object, "PlayedDate", playedDate); + } + + /** + * Returns the date and time the object was last played. + * A value of zero means no played date. + * @return Returns the date and time the object was last played. + */ + public Date getPlayedDate() { + return Dispatch.get(object, "PlayedDate").getJavaDate(); + } + + /** + * Returns an ITPlaylist object corresponding to the playlist that contains + * the object. Use ITFileOrCDTrack::Playlists() or IITURLTrack::Playlists() + * to get the collection of all playlists that contain the song this object + * represents. + * @return Returns an ITPlaylist object corresponding to the playlist that + * contains the object. + */ + public ITPlaylist getPlaylist() { + Dispatch playlist = Dispatch.get(object, "Playlist").toDispatch(); + return new ITPlaylist(playlist); + } + + /** + * Returns the play order index of the object in the owner playlist + * (1-based). + * You can pass this index to IITTrackCollection::ItemByPlayOrder() for the + * collection returned by ITPlaylist::Tracks() to retrieve an ITTrack + * object corresponding to this object. + * @return Returns the play order index of the object in the owner playlist. + */ + public int getPlayOrderIndex() { + return Dispatch.get(object, "PlayOrderIndex").getInt(); + } + + /** + * Set the rating of the object (0 to 100). If the object rating is set to 0, + * it will be computed based on the album rating. + * @param rating The new rating of the object (0 to 100). + */ + public void setRating (int rating) { + Dispatch.put(object, "Rating", rating); + } + + /** + * Returns the rating of the object (0 to 100). If the object rating has never + * been set, or has been set to 0, it will be computed based on the album + * rating. + * @return Returns the rating of the object (0 to 100). + */ + public int getRating() { + return Dispatch.get(object, "Rating").getInt(); + } + + /** + * Returns the sample rate of the object (in Hz). + * @return Returns the sample rate of the object (in Hz). + */ + public int getSampleRate() { + return Dispatch.get(object, "SampleRate").getInt(); + } + + /** + * Returns the size of the object (in bytes). + * @return Returns the size of the object (in bytes). + */ + public int getSize() { + return Dispatch.get(object, "Size").getInt(); + } + + /** + * Set the start time of the object (in seconds). + * @param start The new start time of the object (in seconds). + */ + public void setStart (int start) { + Dispatch.put(object, "Start", start); + } + + /** + * Returns the start time of the object (in seconds). + * @return Returns the start time of the object (in seconds). + */ + public int getStart() { + return Dispatch.get(object, "Start").getInt(); + } + + /** + * Returns the length of the object (in MM:SS format). + * @return Returns the length of the object (in MM:SS format). + */ + public String getTime() { + return Dispatch.get(object, "Time").getString(); + } + + /** + * Set the total number of tracks on the source album. + * @param trackCount The new total number of tracks on the source album. + */ + public void setTrackCount (int trackCount) { + Dispatch.put(object, "TrackCount", trackCount); + } + + /** + * Returns the total number of tracks on the source album. + * @return Returns the total number of tracks on the source album. + */ + public int getTrackCount() { + return Dispatch.get(object, "TrackCount").getInt(); + } + + /** + * Set the index of the object on the source album. + * @param trackNumber The new index of the object on the source album. + */ + public void setTrackNumber (int trackNumber) { + Dispatch.put(object, "TrackNumber", trackNumber); + } + + /** + * Returns the index of the object on the source album. + * @return Returns the index of the object on the source album. + */ + public int getTrackNumber() { + return Dispatch.get(object, "TrackNumebr").getInt(); + } + + /** + * Set the relative volume adjustment of the object (-100% to 100%). + * @param volumeAdjustment Set the relative volume adjustment of the object + * (-100% to 100%). + */ + public void setVolumeAdjustment (int volumeAdjustment) { + Dispatch.put(object, "VolumeAdjustment", volumeAdjustment); + } + + /** + * Returns the relative volume adjustment of the object (-100% to 100%). + * @return Returns the relative volume adjustment of the object (-100% to 100%). + */ + public int getVolumeAdjustment() { + return Dispatch.get(object, "VolumeAdjustment").getInt(); + } + + /** + * Set the year the object was recorded/released. + * @param year The new year the object was recorded/released. + */ + public void setYear (int year) { + Dispatch.put(object, "Year", year); + } + + /** + * Returns the year the object was recorded/released. + * @return Returns the year the object was recorded/released. + */ + public int getYear() { + return Dispatch.get(object, "Year").getInt(); + } + + public ITArtworkCollection getArtwork() { + Dispatch art = Dispatch.get(object, "Artwork").toDispatch(); + return new ITArtworkCollection(art); + + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITTrackCollection.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITTrackCollection.java new file mode 100644 index 0000000..b87208f --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITTrackCollection.java @@ -0,0 +1,91 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a collection of track objects. + * + * Note that collection indices are always 1-based. + * + * You can retrieve all the tracks defined for a playlist using + * ITPlaylist.getTracks(). + * + * You can retrieve the currently selected track or tracks using + * iTunes.getSelectedTracks(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITTrackCollection { + + protected Dispatch object; + + public ITTrackCollection(Dispatch d) { + object = d; + } + + /** + * Returns the number of tracks in the collection. + * @return Returns the number of tracks in the collection. + */ + public int getCount() { + return Dispatch.get(object, "Count").getInt(); + } + + /** + * Returns an ITTrack object corresponding to the given index (1-based). + * @param index Index of the track to retrieve, must be less than or + * equal to ITTrackCollection.getCount(). + * @return Returns an ITTrack object corresponding to the given index. + * Will be set to NULL if no track could be retrieved. + */ + public ITTrack getItem (int index) { + Dispatch item = Dispatch.call(object, "Item", index).toDispatch(); + ITTrack track = new ITTrack(item); + if (track.getKind()==ITTrackKind.ITTrackKindFile) { + return new ITFileOrCDTrack(item); + } else if (track.getKind()==ITTrackKind.ITTrackKindCD) { + return new ITFileOrCDTrack(item); + } else if (track.getKind()==ITTrackKind.ITTrackKindURL ) { + return new ITURLTrack(item); + } else { + return track; + } + } + + /** + * Returns an ITTrack object corresponding to the given index (1-based). + * @param index Index of the track to retrieve, must be less than or + * equal to ITTrackCollection.getCount(). + * @return Returns an ITTrack object corresponding to the given index. + * Will be set to NULL if no track could be retrieved. + */ + public ITTrack getItemByPlayOrder(int index) { + Dispatch item = Dispatch.call(object, "ItemByPlayOrder", index).toDispatch(); + return new ITTrack(item); + } + + /** + * Returns an ITTrack object withthe specified name. + * @param name The name of the track to retrieve. + * @return Returns an ITTrack object corresponding to the given index. + * Will be set to NULL if no track could be retrieved. + */ + public ITTrack ItemByName (String name) { + Dispatch item = Dispatch.call(object, "ItemByName", name).toDispatch(); + return new ITTrack(item); + } + + /** + * Returns an ITTrack object with the specified persistent ID. See the + * documentation on ITObject for more information on persistent IDs. + * @param highID The high 32 bits of the 64-bit persistent ID. + * @param lowID The low 32 bits of the 64-bit persistent ID. + * @return Returns an ITTrack object with the specified persistent ID. + * Will be set to NULL if no track could be retrieved. + */ + public ITTrack getItemByPersistentID (int highID, int lowID) { + Dispatch item = Dispatch.call(object, "ItemByPersistentID", highID, lowID).toDispatch(); + return new ITTrack(item); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITTrackKind.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITTrackKind.java new file mode 100644 index 0000000..ec233a1 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITTrackKind.java @@ -0,0 +1,15 @@ +package com.dt.iTunesController; + +/** + * Specifies the track kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITTrackKind { + ITTrackKindUnknown, + ITTrackKindFile, + ITTrackKindCD, + ITTrackKindURL, + ITTrackKindDevice, + ITTrackKindSharedLibrary; +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITURLTrack.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITURLTrack.java new file mode 100644 index 0000000..9829190 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITURLTrack.java @@ -0,0 +1,175 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a URL track. + * + * A URL track references a network audio stream. + * @author Steve Eyre + * @version 0.2 + */ +public class ITURLTrack extends ITTrack { + + public ITURLTrack (Dispatch d) { + super(d); + } + + /** + * Returns the URL of the stream represented by this track. + * @return The URL of the stream represented by this track. + */ + public String getURL () { + return Dispatch.get(object, "URL").getString(); + } + + /** + * Set the URL of the stream represented by this track. + * @param url The URL of the stream represented by this track. + */ + public void setURL (String url) { + Dispatch.call(object, "URL", url); + } + + /** + * Returns true if this track is a podcast track. If a podcast track is an + * IITURLTrack, the podcast episode has not been downloaded. + * @return Returns true if this track is a podcast track. + */ + public boolean isPodcast () { + return Dispatch.get(object, "Podcast").getBoolean(); + } + + /** + * Returns the category for the track. + * @return Returns the category for the track. + */ + public String getCategory () { + return Dispatch.get(object, "Category").getString(); + } + + /** + * Sets the category for the track. + * @param category Sets the category for the track. + */ + public void setCategory (String category) { + Dispatch.call(object, "Category", category); + } + + /** + * Returns the description for the track. + * @return Returns the description for the track. + */ + public String getDescription () { + return Dispatch.get(object, "Description").getString(); + } + + /** + * Sets the description for the track. + * @param description The new description for the track. + */ + public void setDescription (String description) { + Dispatch.call(object, "Description", description); + } + + /** + * Returns the long description for the track. + * @return Returns the description for the track. + */ + public String getLongDescription () { + return Dispatch.get(object, "LongDescription").getString(); + } + + /** + * Sets the long description for the track. + * @param longDescription The new long description for the track. + */ + public void setLongDescription (String longDescription) { + Dispatch.call(object, "LongDescription", longDescription); + } + + /** + * Returns the user or computed rating of the album that this track belongs + * to (0 to 100). If the album rating has never been set, or has been set to + * 0, it will be computed based on the ratings of tracks in the album. + * @return Returns the album rating of the album that this track belongs to (0 to 100). + */ + public long getAlbumRating () { + return Dispatch.get(object, "AlbumRating").getLong(); + } + + /** + * Set the album rating of the album that this track belongs to (0 to 100). + * If the album rating is set to 0, it will be computed based on the ratings + * of tracks in the album. + * @param albumRating The new album rating of the album that this track + * belongs to (0 to 100). If rating is outside this range, it will be + * pinned. + */ + public void setAlbumRating (long albumRating) { + Dispatch.call(object, "AlbumRating", albumRating); + } + + /** + * Returns the album rating kind. If the album rating has never been set, or + * has been set to 0, the kind is ITRatingKindComputed. Otherwise, the kind + * is ITRatingKindUser. + * @return Returns the album rating kind. + */ + public ITRatingKind getAlbumRatingKind () { + return ITRatingKind.values()[Dispatch.get(object, "AlbumRatingKind").getInt()]; + } + + /** + * Returns the track rating kind. If the track rating has never been set, or + * has been set to 0, the kind is ITRatingKindComputed. Otherwise, the kind + * is ITRatingKindUser. + * @return Returns the track rating kind. + */ + public ITRatingKind getRatingKind () { + return ITRatingKind.values()[Dispatch.get(object, "RatingKind").getInt()]; + } + + /** + * Returns a collection of playlists that contain the song that this track + * represents. + * + * This is the same collection of playlists that are shown in the "Show in + * Playlist" contextual menu for a track, plus the specific playlist that + * contains this track. + * + * A track represents a song in a single playlist, use + * ITTrack.getPlaylist() to get the specific playlist that + * contains this track. + * @return Collection of ITPlaylist objects. + */ + public ITPlaylistCollection getPlaylists () { + Dispatch playlists = Dispatch.get(object, "Playlists").toDispatch(); + return new ITPlaylistCollection(playlists); + } + + /** + * Update the podcast feed for this track. This is equivalent to the user + * choosing Update Podcast from the contextual menu for the podcast feed + * that contains this track. + */ + public void updatePodcastFeed () { + Dispatch.call(object, "UpdatePodcastFeed"); + } + + /** + * Start downloading the podcast episode that corresponds to this track. + * This is equivalent to the user clicking the Get button next to this + * track. + */ + public void downloadPodcastEpisode () { + Dispatch.call(object, "DownloadPodcastEpisode"); + } + + /** + * Reveals the track in the main browser window. + */ + public void reveal() { + Dispatch.call(object, "Reveal"); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITUserPlaylist.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITUserPlaylist.java new file mode 100644 index 0000000..b4025cf --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITUserPlaylist.java @@ -0,0 +1,60 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a user-defined playlist. + * + * A user playlist includes both smart and manual user-defined playlists. + * @author Steve Eyre + * @version 0.2 + */ +public class ITUserPlaylist extends ITPlaylist { + + public ITUserPlaylist(Dispatch d) { + super(d); + } + + /** + * Add a file or files inside a folder to the playlist. + * You cannot use this method to add a file that requires conversion to be + * added (e.g. a CD track), use iTunes.convertFile() or + * iTunes.convertFile2() instead. If you add a folder that + * contains files that require conversion, they will be skipped. + * @param filePath The full path to the file or folder to add. + * @return Returns an ITOperationStatus object corresponding to the + * asynchronous operation. If an error occurs, or no files were added, this + * will be set to NULL. + */ + public ITOperationStatus addFile (String filePath) { + Dispatch status = Dispatch.call(object, "AddFile", filePath).toDispatch(); + return new ITOperationStatus(status); + } + + /** + * Add a streaming audio URL to the playlist. + * @param url The URL to add. The length of the URL can be 255 characters or + * less. + * @return Returns an ITURLTrack object corresponding to the new track. + */ + public ITURLTrack addURL (String url) { + Dispatch URLTrack = Dispatch.call(object, "AddURL", url).toDispatch(); + return new ITURLTrack(URLTrack); + } + + /** + * Add an existing track to the playlist. + * You cannot use this method to add a CD track (ITTrackKindCD) to another + * playlist, use iTunes.convertTrack() or + * iTunes.convertTrack2() instead. + * You cannot add a shared library track (ITTrackKindSharedLibrary) to + * another playlist. + * @param track The track to add. + * @return Returns an IITTrack object corresponding to the new track. + */ + public ITTrack addTrack (ITTrack track) { + Dispatch trackToAdd = track.fetchDispatch(); + Dispatch addedTrack = Dispatch.call(object, "AddTrack", trackToAdd).toDispatch(); + return new ITTrack(addedTrack); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITVideoKind.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITVideoKind.java new file mode 100644 index 0000000..d318724 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITVideoKind.java @@ -0,0 +1,13 @@ +package com.dt.iTunesController; + +/** + * Specifies the Video kind. + * @author Steve Eyre + * @version 0.2 + */ +public enum ITVideoKind { + ITVideoKindNone, + ITVideoKindMovie, + ITVideoKindMusicVideo, + ITVideoKindTVShow; +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITWindow.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITWindow.java new file mode 100644 index 0000000..4af825f --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITWindow.java @@ -0,0 +1,32 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents an iTunes window. + */ + +public class ITWindow { + + protected Dispatch object; + + public ITWindow(Dispatch d) { + object = d; + } + + /** + * Returns the JACOB Dispatch object for this object. + * @return Returns the JACOB Dispatch object for this object. + */ + public Dispatch fetchDispatch() { + return object; + } + + /** + * Returns the name of the object. + * @return Returns the name of the object. + */ + public String getName() { + return Dispatch.get(object, "Name").getString(); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/ITWindowCollection.java b/vendor/iTunesController/0.2/com/dt/iTunesController/ITWindowCollection.java new file mode 100644 index 0000000..df1f3cf --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/ITWindowCollection.java @@ -0,0 +1,55 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; + +/** + * Represents a collection of window objects. + * + * Note that collection indices are always 1-based. + * + * You can retrieve all the windows using + * iTunes.getWindows(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class ITWindowCollection { + + protected Dispatch object; + + public ITWindowCollection(Dispatch d) { + object = d; + } + + // TODO: iTunes.getWindows() + + /** + * Returns the number of playlists in the collection. + * @return Returns the number of playlists in the collection. + */ + public int getCount() { + return Dispatch.get(object, "Count").getInt(); + } + + /** + * Returns an ITWindow object corresponding to the given index (1-based). + * @param index Index of the playlist to retrieve, must be less than or + * equal to ITWindowCollection.getCount(). + * @return Returns an ITWindow object corresponding to the given index. + * Will be set to NULL if no playlist could be retrieved. + */ + public ITWindow getItem (int index) { + Dispatch item = Dispatch.call(object, "Item", index).toDispatch(); + return new ITWindow(item); + } + /** + * Returns an ITWindow object with the specified name. + * @param name The name of the window to retrieve. + * @return Returns an ITWindow object corresponding to the given index. + * Will be set to NULL if no ITWindow could be retrieved. + */ + public ITWindow ItemByName (String name) { + Dispatch item = Dispatch.call(object, "ItemByName", name).toDispatch(); + return new ITWindow(item); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/iTunes.java b/vendor/iTunesController/0.2/com/dt/iTunesController/iTunes.java new file mode 100644 index 0000000..150ae7a --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/iTunes.java @@ -0,0 +1,488 @@ +package com.dt.iTunesController; +import com.jacob.activeX.*; +import com.jacob.com.Dispatch; +import com.jacob.com.DispatchEvents; +import com.jacob.com.Variant; + +/** + * Defines the top-level iTunes application object. + * + * This interface defines the top-level iTunes application object. All other + * iTunes interfaces are accessed through this object. + * + * @author Steve Eyre + * @version 0.2 + */ +public class iTunes { + + ActiveXComponent iTunes; + iTunesEvents iTunesEvents; + DispatchEvents dispatchEvents; + + /** + * Initiate iTunes Controller. + */ + public iTunes() { + iTunes = new ActiveXComponent("iTunes.Application"); + } + + /** + * Add an event handler to the iTunes controller. + * @param itef The class that will handle the iTunes events. + */ + public void addEventHandler(iTunesEventsInterface itef) { + iTunesEvents = new iTunesEvents(itef); + dispatchEvents = new DispatchEvents(iTunes, iTunesEvents); + System.out.println("New event handler added."); + } + + /** + * Reposition to the beginning of the current track or go to the previous + * track if already at start of current track. + */ + public void backTrack() { + iTunes.invoke("BackTrack"); + } + + /** + * Skip forward in a playing track. + */ + public void fastForward() { + iTunes.invoke("FastForward"); + } + + /** + * Advance to the next track in the current playlist. + */ + public void nextTrack() { + iTunes.invoke("NextTrack"); + } + + /** + * Pause playback. + */ + public void pause() { + iTunes.invoke("Pause"); + } + + /** + * Play the currently targeted track. + */ + public void play() { + Variant s = iTunes.invoke("ASDSDPlay"); + } + + /** + * Play the specified file path, adding it to the library if not already + * present. + */ + public void playFile(String filePath) { + iTunes.invoke("PlayFile", filePath); + } + + /** + * Toggle the playing/paused state of the current track. + */ + public void playPause() { + iTunes.invoke("PlayPause"); + } + + /** + * Return to the previous track in the current playlist. + */ + public void previousTrack() { + iTunes.invoke("PreviousTrack"); + } + + /** + * Disable fast forward/rewind and resume playback, if playing. + */ + public void resume() { + iTunes.invoke("Resume"); + } + + /** + * Skip backwards in a playing track. + */ + public void rewind() { + iTunes.invoke("Rewind"); + } + + /** + * Stop playback. + */ + public void stop() { + iTunes.invoke("Stop"); + } + + /** + * Retrieves the current state of the player buttons in the window + * containing the currently targeted track. If there is no currently + * targeted track, returns the current state of the player buttons + * in the main browser window. + */ + public void getPlayerButtonsState(boolean previousEnabled, + String playPause, boolean nextEnabled) { + + } + + /** + * Returns true if this version of the iTunes type library is compatible + * with the specified version. + * @param majorVersion Major version of iTunes interface. + * @param minorVersion Minor version of iTunes interface. + * @return Returns true if this version is compatible with the indicated + * interface version. + */ + public boolean getCheckVersion (int majorVersion, int minorVersion) { + return iTunes.invoke("CheckVersion", majorVersion, minorVersion).getBoolean(); + } + + /** + * Returns an IITObject corresponding to the specified IDs. + * The object may be a source, playlist, or track. + * @param sourceID The ID that identifies the source. Valid for a source, + * playlist, or track. + * @param playlistID The ID that identifies the playlist. Valid for a + * playlist or track. Must be zero for a source. + * @param trackID The ID that identifies the track within the playlist. + * Valid for a track. Must be zero for a source or playlist. + * @param databaseID The ID that identifies the track, independent of its + * playlist. Valid for a track. Must be zero for a source or playlist. + * @return Returns an IITObject object corresponding to the specified IDs. + * Will be set to NULL if no object could be retrieved. + */ + public ITObject getITObjectByID(int sourceID, int playlistID, int trackID, int databaseID) { + Dispatch object = Dispatch.call(iTunes, "GetITObjectByID", sourceID, playlistID, trackID, databaseID).toDispatch(); + return new ITObject(object); + } + + /** + * Creates a new playlist in the main library. + * @param playlistName The name of the new playlist (may be empty). + * @return Returns an ITPlaylist object corresponding to the new playlist. + */ + public ITPlaylist createPlaylist(String playlistName) { + Dispatch cplaylist = Dispatch.call(iTunes, "CreatePlaylist", playlistName).toDispatch(); + ITPlaylist playlist = new ITPlaylist(cplaylist); + ITPlaylistKind playlistKind = playlist.getKind(); + if (playlistKind == ITPlaylistKind.ITPlaylistKindCD) + return new ITAudioCDPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindLibrary) + return new ITLibraryPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindUser) + return new ITUserPlaylist(cplaylist); + else + return playlist; + } + + /** + * Open the specified iTunes Store or streaming audio URL. + * @param url The URL to open. The length of the URL cannot exceed 512 + * characters. iTunes Store URLs start with itms:// or itmss://. Streaming + * audio URLs start with http://. + */ + public void openURL (String url) { + iTunes.invoke("OpenURL", url); + } + + /** + * Go to the iTunes Store home page. + */ + public void gotoMusicStoreHomePage() { + iTunes.invoke("GoToMusicStoreHomePage"); + } + + /** + * Update the contents of the iPod. + */ + public void updateIPod() { + iTunes.invoke("UpdateIPod"); + } + + /** + * Exits the iTunes application. + */ + public void quit() { + iTunes.invoke("Quit"); + } + + /** + * Creates a new EQ preset. + * The EQ preset will be created "flat", i.e. the preamp and all band levels + * will be set to 0. + * EQ preset names cannot start with leading spaces. If you specify a name + * that starts with leading spaces they will be stripped out. + * If eqPresetName is empty, the EQ preset will be created with + * a default name. + * @param eqPresetName The name of the new EQ Preset (may be empty) + * @return Returns an ITEQPreset object corresponding to the new EQ Preset. + */ + public ITEQPreset createEQPreset(String eqPresetName) { + Dispatch eqPreset = Dispatch.call(iTunes, "CreateEQPreset", eqPresetName).toDispatch(); + return new ITEQPreset(eqPreset); + } + + /** + * Creates a new playlist in an existing source. + * You may not be able to create a playlist in every source. For example, + * you cannot create a playlist in an audio CD source, or in an iPod source + * if it is in auto update mode. + * If playlistName is empty, the playlist will be created with + * a default name. + * @param playlistName The name of the new playlist (may be empty). + * @param source The source that will contain the new playlist. + * @return Returns an ITPlaylist object corresponding to the new playlist. + */ + public ITPlaylist createPlaylistInSource(String playlistName, ITSource source) { + Dispatch cplaylist = Dispatch.call(iTunes, "CreatePlaylistInSource", playlistName, source.fetchDispatch()).toDispatch(); + ITPlaylist playlist = new ITPlaylist(cplaylist); + ITPlaylistKind playlistKind = playlist.getKind(); + if (playlistKind == ITPlaylistKind.ITPlaylistKindCD) + return new ITAudioCDPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindLibrary) + return new ITLibraryPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindUser) + return new ITUserPlaylist(cplaylist); + else + return playlist; + } + + /** + * Subscribes to the specified podcast feed URL. Any "unsafe" characters in + * the URL should already be converted into their corresponding escape + * sequences, iTunes will not do this. + * @param url The URL to subscribe to. + */ + public void subscribeToPodcast(String url) { + iTunes.invoke("SubscribeToPodcast", url); + } + + /** + * Updates all podcast feeds. This is equivalent to the user pressing the + * Update button when Podcasts is selected in the Source list. + */ + public void updatePodcastFeeds() { + iTunes.invoke("UpdatePodcastFeeds"); + } + + /** + * Creates a new folder in the main library. + * If folderName is empty, the folder will be created with a + * default name. + * @param folderName The name of the new folder (may be empty). + * @return Returns an ITPlaylist object corresponding to the new folder. + */ + public ITUserPlaylist createFolder(String folderName) { + Dispatch folder = Dispatch.call(iTunes, "CreateFolder", folderName).toDispatch(); + return new ITUserPlaylist(folder); + } + + /** + * Creates a new folder in an existing source. + * You may not be able to create a folder in every source. For example, you + * cannot create a folder in an audio CD source, or in an iPod source if it + * is in auto update mode. + * If folderName is empty, the folder will be created with a + * default name. + * @param folderName The name of the new folder (may be empty) + * @param iSource The source that will contain the new folder. + * @return Returns an ITPlaylist object corresponding to the new folder. + */ + public ITUserPlaylist createFolderInSource(String folderName, ITSource iSource) { + Dispatch folder = Dispatch.call(iTunes, "CreateFolderInSource", folderName, iSource.fetchDispatch()).toDispatch(); + return new ITUserPlaylist(folder); + } + + /** + * Returns a collection of music sources (music library, CD, device, etc.). + * @return Collection of ITSource objects. + */ + public ITSourceCollection getSources() { + Dispatch sources = Dispatch.call(iTunes, "Sources").toDispatch(); + return new ITSourceCollection(sources); + } + + /** + * Sets the sound output volume (0=minimum, 100=maximum). + * @param volume New sound output volume + */ + public void setSoundVolume(int volume) { + iTunes.setProperty("SoundVolume", volume); + } + + /** + * Returns the sound output volume (0=minimum, 100=maximum). + * @return Current sound output volume + */ + public int getSoundVolume() { + return iTunes.getPropertyAsInt("SoundVolume"); + } + + /** + * Sets sound output mute state. + * @param shouldMute If true, sound output will be muted. + */ + public void setMute(boolean shouldMute) { + iTunes.setProperty("Mute", shouldMute); + } + + /** + * Returns true if the sound output is muted. + * @return True if sound output is muted. + */ + public boolean getMute() { + return iTunes.getPropertyAsBoolean("Mute"); + } + + /** + * Returns the current player state. + * @return Returns the current player state. + */ + public ITPlayerState getPlayerState() { + return ITPlayerState.values()[Dispatch.get(iTunes, "PlayerState").getInt()]; + } + + /** + * Sets the player's position within the currently playing track in + * seconds. + * If playerPos specifies a position before the beginning of the track, + * the position will be set to the beginning. If playerPos specifies a + * position after the end of the track, the position will be set to the + * end. + * @param playerPos The player's position within the currently playing + * track in seconds. + */ + public void setPlayerPosition(int playerPos) { + iTunes.setProperty("playerPosition", playerPos); + } + + /** + * Returns the player's position within the currently playing track in + * seconds. + * @return The player's position within the currently playing track in + * seconds. + */ + public int getPlayerPosition() { + return iTunes.getPropertyAsInt("playerPosition"); + } + + /** + * Returns the source that represents the main library. + * You can also find the main library source by iterating over + * iTunes.getSources() and looking for an ITSource + * of kind ITSourceKindLibrary. + * @return Returns the source that represents the main library. + */ + public ITSource getLibrarySource() { + Dispatch lsource = iTunes.getProperty("LibrarySource").toDispatch(); + return new ITSource(lsource); + } + + /** + * Returns the main library playlist in the main library source. + * @return An IITLibraryPlaylist object corresponding to the main library + * playlist. + */ + public ITLibraryPlaylist getLibraryPlaylist() { + Dispatch lplaylist = iTunes.getProperty("LibraryPlaylist").toDispatch(); + return new ITLibraryPlaylist(lplaylist); + } + + /** + * Returns the currently targetd track. + * @return An ITTrack object corresponding to the currently targeted track. + * Will be set to NULL if there is no currently targeted track. + */ + public ITTrack getCurrentTrack() { + Dispatch item = iTunes.getProperty("CurrentTrack").toDispatch(); + ITTrack track = new ITTrack(item); + if (track.getKind()==ITTrackKind.ITTrackKindFile) { + return new ITFileOrCDTrack(item); + } else if (track.getKind()==ITTrackKind.ITTrackKindCD) { + return new ITFileOrCDTrack(item); + } else if (track.getKind()==ITTrackKind.ITTrackKindURL ) { + return new ITURLTrack(item); + } else { + return track; + } + } + + /** + * Returns the playlist containing the currently targeted track. + * @return An ITPlaylist object corresponding to the playlist containing the + * currently targeted track. + * Will be set to NULL if there is no currently targeted playlist. + */ + public ITPlaylist getCurrentPlaylist() { + Dispatch cplaylist = iTunes.getProperty("CurrentPlaylist").toDispatch(); + ITPlaylist playlist = new ITPlaylist(cplaylist); + ITPlaylistKind playlistKind = playlist.getKind(); + if (playlistKind == ITPlaylistKind.ITPlaylistKindCD) + return new ITAudioCDPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindLibrary) + return new ITLibraryPlaylist(cplaylist); + else if (playlist.getKind() == ITPlaylistKind.ITPlaylistKindUser) + return new ITUserPlaylist(cplaylist); + else + return playlist; + } + + /** + * Returns a collection containing the currently selected track or tracks. + * The frontmost visible window in iTunes must be a browser or playlist + * window. If there is no frontmost visible window (e.g. iTunes is minimized + * to the system tray), the main browser window is used. + * @return Collection of ITrack objects. + * Will be set to NULL if there is no current selection. + */ + public ITTrackCollection getSelectedTracks() { + Dispatch stracks = iTunes.getProperty("SelectedTracks").toDispatch(); + return new ITTrackCollection(stracks); + } + + /** + * Returns the version of the iTunes application. + * @return + */ + public String getVersion() { + return iTunes.getPropertyAsString("Version"); + } + + /** + * Returns the high 32 bits of the persistent ID of the specified IITObject. + * See the documentation on IITObject for more information on persistent + * IDs. + * + * The object may be a source, playlist, or track. + * @param iObject The object to fetch the High Persistent ID. + * @return The high 32 bits of the 64-bit persistent ID. + */ + public long getITObjectPersistentIDHigh (ITObject iObject) { + Dispatch object = iObject.fetchDispatch(); + return Dispatch.call(object, "GetObjectPersistentIDHigh", object).getLong(); + } + + /** + * Returns the low 32 bits of the persistent ID of the specified IITObject. + * See the documentation on IITObject for more information on persistent + * IDs. + * + * The object may be a source, playlist, or track. + * @param iObject The object to fetch the Low Persistent ID. + * @return The low 32 bits of the 64-bit persistent ID. + */ + public long getITObjectPersistentIDLow (ITObject iObject) { + Dispatch object = iObject.fetchDispatch(); + return Dispatch.call(object, "GetObjectPersistentIDLow", object).getLong(); + } + + public ITObjectPersistentID getObjectPersistentIDs(ITObject iObject){ + return new ITObjectPersistentID(getITObjectPersistentIDHigh(iObject),getITObjectPersistentIDLow(iObject)); + } + + public ITBrowserWindow getBrowserWindow(){ + Dispatch window = iTunes.getProperty("BrowserWindow").toDispatch(); + return new ITBrowserWindow(window); + } +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/iTunesEvents.java b/vendor/iTunesController/0.2/com/dt/iTunesController/iTunesEvents.java new file mode 100644 index 0000000..ddbee23 --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/iTunesEvents.java @@ -0,0 +1,62 @@ +package com.dt.iTunesController; +import com.jacob.com.Dispatch; +import com.jacob.com.Variant; + +/** + * This class is used to forward all iTunes COM Events to a class that + * implements iTunesEventsInterface. To receive events, create + * a class that implements the interface, and then use + * iTunes.addEventHandler(). + * + * @author Steve Eyre + * @version 0.2 + */ +public class iTunesEvents { + + private iTunesEventsInterface eventHandler; + + public iTunesEvents (iTunesEventsInterface itef) { + eventHandler = itef; + } + + public void OnDatabaseChangedEvent(Variant[] args) { + // Not currently implemented + } + + public void OnPlayerPlayEvent(Variant[] args) { + ITTrack itt = new ITTrack((Dispatch)args[0].getDispatch()); + eventHandler.onPlayerPlayEvent(itt); + } + + public void OnPlayerStopEvent(Variant[] args) { + ITTrack itt = new ITTrack((Dispatch)args[0].getDispatch()); + eventHandler.onPlayerStopEvent(itt); + } + + public void OnPlayerPlayingTrackChangedEvent(Variant[] args) { + ITTrack itt = new ITTrack((Dispatch)args[0].getDispatch()); + eventHandler.onPlayerPlayingTrackChangedEvent(itt); + } + + public void OnCOMCallsDisabledEvent(Variant[] args) { + ITCOMDisabledReason reason = ITCOMDisabledReason.values()[args[0].getInt()]; + eventHandler.onCOMCallsDisabledEvent(reason); + } + + public void OnCOMCallsEnabledEvent(Variant[] args) { + eventHandler.onCOMCallsEnabledEvent(); + } + + public void OnQuittingEvent(Variant[] args) { + eventHandler.onQuittingEvent(); + } + + public void OnAboutToPromptUserToQuitEvent(Variant[] args) { + eventHandler.onAboutToPromptUserToQuitEvent(); + } + + public void OnSoundVolumeChangedEvent(Variant[] args) { + eventHandler.onSoundVolumeChangedEvent(args[0].getInt()); + } + +} diff --git a/vendor/iTunesController/0.2/com/dt/iTunesController/iTunesEventsInterface.java b/vendor/iTunesController/0.2/com/dt/iTunesController/iTunesEventsInterface.java new file mode 100644 index 0000000..3d8f17e --- /dev/null +++ b/vendor/iTunesController/0.2/com/dt/iTunesController/iTunesEventsInterface.java @@ -0,0 +1,115 @@ +package com.dt.iTunesController; + +/** + * Interface for receiving iTunes events. + * @author Steve Eyre + * @version 0.2 + */ +public interface iTunesEventsInterface { + + /** + * Not currently implemented. + * + * The ITEventDatabaseChanged event is fired when the iTunes database is + * changed. + * + * Each parameter is a two-dimensional array of integers. The first + * dimension is the number of objects. The second dimension is always 4 and + * specifies each of the 4 ITObject IDs, where index 0 is the source ID, + * index 1 is the playlist ID, index 2 is the track ID, and index 3 is the + * track database ID. For more information on object IDs, see + * ITObject. + * + * Note that you can use iTunes.getITObjectByID() to retrieve + * changed ITObject, but not for deleted objects (since they no longer + * exist). + * + * @param deletedObjectIDs + * @param changedObjectIDs + */ + public void onDatabaseChangedEvent(int[][] deletedObjectIDs, int[][] changedObjectIDs); + + /** + * The ITEventPlayerPlay event is fired when a track begins playing. + * @param iTrack An ITTrack object corresponding to the track that has + * started playing. + */ + public void onPlayerPlayEvent (ITTrack iTrack); + + /** + * The ITEventPlayerStop event is fired when a track stops playing. + * @param iTrack An ITTrack object corresponding to the track that has + * stopped playing. + */ + public void onPlayerStopEvent (ITTrack iTrack); + + /** + * The ITEventPlayerPlayingTrackChanged event is fired when information + * about the currently playing track has changed. + * This event is fired when the user changes information about the currently + * playing track (e.g. the name of the track). + * This event is also fired when iTunes plays the next joined CD track in a + * CD playlist, since joined CD tracks are treated as a single track. + * @param iTrack An ITTrack object corresponding to the track that is now + * playing. + */ + public void onPlayerPlayingTrackChangedEvent(ITTrack iTrack); + + /** + * The ITEventCOMCallsDisabled event is fired when calls to the iTunes COM + * interface will be deferred. + * Typically, iTunes will defer COM calls when any modal dialog is being + * displayed. When the user dismisses the last modal dialog, COM calls will + * be enabled again, and any deferred COM calls will be executed. You can + * use this event to avoid making a COM call which will be deferred. + * @param reason The reason the COM interface is being disabled. This is + * typically ITCOMDisabledReasonDialog. + */ + public void onCOMCallsDisabledEvent(ITCOMDisabledReason reason); + + /** + * The ITEventCOMCallsEnabled event is fired when calls to the iTunes COM + * interface will no longer be deferred. + * Typically, iTunes will defer COM calls when any modal dialog is being + * displayed. When the user dismisses the last modal dialog, COM calls will + * be enabled again, and any deferred COM calls will be executed. + */ + public void onCOMCallsEnabledEvent(); + + /** + * The ITEventQuitting event is fired when iTunes is about to quit. + * If the user attempts to quit iTunes while a client still has outstanding + * iTunes COM objects instantiated, iTunes will display a warning dialog. + * The user can still choose to quit iTunes anyway, in which case this event + * will be fired. After this event is fired, any existing iTunes COM objects + * will no longer be valid. + * This event is only used to notify clients that iTunes is quitting, + * clients cannot prevent this from happening. + */ + public void onQuittingEvent(); + + /** + * The ITEventAboutToPromptUserToQuit event is fired when iTunes is about + * prompt the user to quit. + * This event gives clients the opportunity to prevent the warning dialog + * prompt from occurring. + * If the user attempts to quit iTunes while a client still has outstanding + * iTunes COM objects instantiated, iTunes will display a warning dialog. + * This event is fired just before the warning dialog is shown. iTunes will + * then wait up to 5 seconds for clients to release any outstanding iTunes + * COM objects. If all objects are released during this time, the warning + * dialog will not be shown and iTunes will quit immediately. + * Otherwise, the warning dialog will be shown. If the user chooses to quit + * iTunes anyway, the ITEventQuitting event is fired. See + * iTunesEventsInterface.onQuittingEvent() for more details. + */ + public void onAboutToPromptUserToQuitEvent(); + + /** + * The ITEventSoundVolumeChanged event is fired when the sound output volume + * has changed. + * @param newVolume The new sound output volume (0 = minimum, 100 = maximum). + */ + public void onSoundVolumeChangedEvent(int newVolume); + +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXComponent.java b/vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXComponent.java new file mode 100644 index 0000000..4d0096b --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXComponent.java @@ -0,0 +1,479 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.activeX; + +import com.jacob.com.Dispatch; +import com.jacob.com.JacobObject; +import com.jacob.com.Variant; + +/** + * This class provides a higher level, more object like, wrapper for top of the + * Dispatch object. The Dispatch class's method essentially directly map to + * Microsoft C API including the first parameter that is almost always the + * target of the message. ActiveXComponent assumes the target of every message + * is the MS COM object behind the ActiveXComponent. This removes the need to + * pass the Dispatch object into every method. + *

    + * It is really up to the developer as to whether they want to use the Dispatch + * interface or the ActiveXComponent interface. + *

    + * This class simulates com.ms.activeX.ActiveXComponent only in the sense that + * it is used for creating Dispatch objects + */ +public class ActiveXComponent extends Dispatch { + + /** + * Normally used to create a new connection to a microsoft application. The + * passed in parameter is the name of the program as registered in the + * registry. It can also be the object name. + *

    + * This constructor causes a new Windows object of the requested type to be + * created. The windows CoCreate() function gets called to create the + * underlying windows object. + * + *

    +	 * new ActiveXComponent("ScriptControl");
    +	 * 
    + * + * @param programId + */ + public ActiveXComponent(String programId) { + super(programId); + } + + /** + * Creates an active X component that is built on top of the COM pointers + * held in the passed in dispatch. This widens the Dispatch object to pick + * up the ActiveXComponent API + * + * @param dispatchToBeWrapped + */ + public ActiveXComponent(Dispatch dispatchToBeWrapped) { + super(dispatchToBeWrapped); + } + + /** + * only used by the factories + * + */ + private ActiveXComponent() { + super(); + } + + /** + * Probably was a cover for something else in the past. Should be + * deprecated. + * + * @return Now it actually returns this exact same object. + */ + public Dispatch getObject() { + return this; + } + + /** + * Most code should use the standard ActiveXComponent(String) contructor and + * not this factory method. This method exists for applications that need + * special behavior. Experimental in release 1.9.2. + *

    + * Factory that returns a Dispatch object wrapped around the result of a + * CoCreate() call. This differs from the standard constructor in that it + * throws no exceptions and returns null on failure. + *

    + * This will fail for any prog id with a ":" in it. + * + * @param pRequestedProgramId + * @return Dispatch pointer to the COM object or null if couldn't create + */ + public static ActiveXComponent createNewInstance(String pRequestedProgramId) { + ActiveXComponent mCreatedDispatch = null; + try { + mCreatedDispatch = new ActiveXComponent(); + mCreatedDispatch.coCreateInstance(pRequestedProgramId); + } catch (Exception e) { + mCreatedDispatch = null; + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("Unable to co-create instance of " + + pRequestedProgramId); + } + } + return mCreatedDispatch; + } + + /** + * Most code should use the standard ActiveXComponent(String) constructor + * and not this factory method. This method exists for applications that + * need special behavior. Experimental in release 1.9.2. + *

    + * Factory that returns a Dispatch wrapped around the result of a + * getActiveObject() call. This differs from the standard constructor in + * that it throws no exceptions and returns null on failure. + *

    + * This will fail for any prog id with a ":" in it + * + * @param pRequestedProgramId + * @return Dispatch pointer to a COM object or null if wasn't already + * running + */ + public static ActiveXComponent connectToActiveInstance( + String pRequestedProgramId) { + ActiveXComponent mCreatedDispatch = null; + try { + mCreatedDispatch = new ActiveXComponent(); + mCreatedDispatch.getActiveInstance(pRequestedProgramId); + } catch (Exception e) { + mCreatedDispatch = null; + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("Unable to attach to running instance of " + + pRequestedProgramId); + } + } + return mCreatedDispatch; + } + + /** + * @see com.jacob.com.Dispatch#finalize() + */ + @Override + protected void finalize() { + super.finalize(); + } + + /* + * ============================================================ + * + * start of instance based calls to the COM layer + * =========================================================== + */ + + /** + * retrieves a property and returns it as a Variant + * + * @param propertyName + * @return variant value of property + */ + public Variant getProperty(String propertyName) { + return Dispatch.get(this, propertyName); + } + + /** + * retrieves a property and returns it as an ActiveX component + * + * @param propertyName + * @return Dispatch representing the object under the property name + */ + public ActiveXComponent getPropertyAsComponent(String propertyName) { + return new ActiveXComponent(Dispatch.get(this, propertyName) + .toDispatch()); + + } + + /** + * retrieves a property and returns it as a Boolean + * + * @param propertyName + * property we are looking up + * @return boolean value of property + */ + public boolean getPropertyAsBoolean(String propertyName) { + return Dispatch.get(this, propertyName).getBoolean(); + } + + /** + * retrieves a property and returns it as a byte + * + * @param propertyName + * property we are looking up + * @return byte value of property + */ + public byte getPropertyAsByte(String propertyName) { + return Dispatch.get(this, propertyName).getByte(); + } + + /** + * retrieves a property and returns it as a String + * + * @param propertyName + * @return String value of property + */ + public String getPropertyAsString(String propertyName) { + return Dispatch.get(this, propertyName).getString(); + + } + + /** + * retrieves a property and returns it as a int + * + * @param propertyName + * @return the property value as an int + */ + public int getPropertyAsInt(String propertyName) { + return Dispatch.get(this, propertyName).getInt(); + } + + /** + * sets a property on this object + * + * @param propertyName + * property name + * @param arg + * variant value to be set + */ + public void setProperty(String propertyName, Variant arg) { + Dispatch.put(this, propertyName, arg); + } + + /** + * sets a property on this object + * + * @param propertyName + * property name + * @param arg + * variant value to be set + */ + public void setProperty(String propertyName, Dispatch arg) { + Dispatch.put(this, propertyName, arg); + } + + /** + * sets a property to be the value of the string + * + * @param propertyName + * @param propertyValue + */ + public void setProperty(String propertyName, String propertyValue) { + this.setProperty(propertyName, new Variant(propertyValue)); + } + + /** + * sets a property as a boolean value + * + * @param propertyName + * @param propValue + * the boolean value we want the prop set to + */ + public void setProperty(String propertyName, boolean propValue) { + this.setProperty(propertyName, new Variant(propValue)); + } + + /** + * sets a property as a boolean value + * + * @param propertyName + * @param propValue + * the boolean value we want the prop set to + */ + public void setProperty(String propertyName, byte propValue) { + this.setProperty(propertyName, new Variant(propValue)); + } + + /** + * sets the property as an int value + * + * @param propertyName + * @param propValue + * the int value we want the prop to be set to. + */ + public void setProperty(String propertyName, int propValue) { + this.setProperty(propertyName, new Variant(propValue)); + } + + /*------------------------------------------------------- + * Listener logging helpers + *------------------------------------------------------- + */ + + /** + * This boolean determines if callback events should be logged + */ + public static boolean shouldLogEvents = false; + + /** + * used by the doc and application listeners to get intelligent logging + * + * @param description + * event description + * @param args + * args passed in (variants) + * + */ + public void logCallbackEvent(String description, Variant[] args) { + String argString = ""; + if (args != null && ActiveXComponent.shouldLogEvents) { + if (args.length > 0) { + argString += " args: "; + } + for (int i = 0; i < args.length; i++) { + short argType = args[i].getvt(); + argString += ",[" + i + "]"; + // break out the byref bits if they are on this + if ((argType & Variant.VariantByref) == Variant.VariantByref) { + // show the type and the fact that its byref + argString += "(" + + (args[i].getvt() & ~Variant.VariantByref) + "/" + + Variant.VariantByref + ")"; + } else { + // show the type + argString += "(" + argType + ")"; + } + argString += "="; + if (argType == Variant.VariantDispatch) { + Dispatch foo = (args[i].getDispatch()); + argString += foo; + } else if ((argType & Variant.VariantBoolean) == Variant.VariantBoolean) { + // do the boolean thing + if ((argType & Variant.VariantByref) == Variant.VariantByref) { + // boolean by ref + argString += args[i].getBooleanRef(); + } else { + // boolean by value + argString += args[i].getBoolean(); + } + } else if ((argType & Variant.VariantString) == Variant.VariantString) { + // do the string thing + if ((argType & Variant.VariantByref) == Variant.VariantByref) { + // string by ref + argString += args[i].getStringRef(); + } else { + // string by value + argString += args[i].getString(); + } + } else { + argString += args[i].toString(); + } + } + System.out.println(description + argString); + } + } + + /* + * ============================================================== + * + * covers for dispatch call methods + * ============================================================= + */ + + /** + * makes a dispatch call for the passed in action and no parameter + * + * @param callAction + * @return ActiveXComponent representing the results of the call + */ + public ActiveXComponent invokeGetComponent(String callAction) { + return new ActiveXComponent(invoke(callAction).toDispatch()); + } + + /** + * makes a dispatch call for the passed in action and single parameter + * + * @param callAction + * @param parameters + * @return ActiveXComponent representing the results of the call + */ + public ActiveXComponent invokeGetComponent(String callAction, + Variant... parameters) { + return new ActiveXComponent(invoke(callAction, parameters).toDispatch()); + } + + /** + * invokes a single parameter call on this dispatch that returns no value + * + * @param actionCommand + * @param parameter + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String actionCommand, String parameter) { + return Dispatch.call(this, actionCommand, parameter); + } + + /** + * makes a dispatch call to the passed in action with a single boolean + * parameter + * + * @param actionCommand + * @param parameter + * @return Variant result + */ + public Variant invoke(String actionCommand, boolean parameter) { + return Dispatch.call(this, actionCommand, new Variant(parameter)); + } + + /** + * makes a dispatch call to the passed in action with a single int parameter + * + * @param actionCommand + * @param parameter + * @return Variant result of the invoke (Dispatch.call) + */ + public Variant invoke(String actionCommand, int parameter) { + return Dispatch.call(this, actionCommand, new Variant(parameter)); + } + + /** + * makes a dispatch call to the passed in action with a string and integer + * parameter (this was put in for some application) + * + * @param actionCommand + * @param parameter1 + * @param parameter2 + * @return Variant result + */ + public Variant invoke(String actionCommand, String parameter1, + int parameter2) { + return Dispatch.call(this, actionCommand, parameter1, new Variant( + parameter2)); + } + + /** + * makes a dispatch call to the passed in action with two integer parameters + * (this was put in for some application) + * + * @param actionCommand + * @param parameter1 + * @param parameter2 + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String actionCommand, int parameter1, int parameter2) { + return Dispatch.call(this, actionCommand, new Variant(parameter1), + new Variant(parameter2)); + } + + /** + * makes a dispatch call for the passed in action and no parameter + * + * @param callAction + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String callAction) { + return Dispatch.call(this, callAction); + } + + /** + * This is really a cover for call(String,Variant[]) that should be + * eliminated call with a variable number of args mainly used for quit. + * + * @param name + * @param args + * @return Variant returned by the invoke (Dispatch.callN) + */ + public Variant invoke(String name, Variant... args) { + return Dispatch.callN(this, name, args); + } + +} \ No newline at end of file diff --git a/vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXDispatchEvents.java b/vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXDispatchEvents.java new file mode 100644 index 0000000..16bb649 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXDispatchEvents.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.activeX; + +import com.jacob.com.Dispatch; +import com.jacob.com.DispatchEvents; +import com.jacob.com.InvocationProxy; + +/** + * RELEASE 1.12 EXPERIMENTAL. + *

    + * Use this exactly like the DispatchEvents class. This class plugs in an + * ActiveXInvocationProxy instead of an InvocationProxy. It is the + * ActiveXInvocationProxy that implements the reflection calls and invoke the + * found java event callbacks. See ActiveXInvocationProxy for details. + * + * + */ +public class ActiveXDispatchEvents extends DispatchEvents { + + /** + * This is the most commonly used constructor. + *

    + * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + */ + public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink) { + super(sourceOfEvent, eventSink, null); + } + + /** + * None of the samples use this constructor. + *

    + * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + * @param progId + * ??? + */ + public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink, + String progId) { + super(sourceOfEvent, eventSink, progId, null); + } + + /** + * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + * + *

    +	 * >ActiveXDispatchEvents de = 
    +	 * 			new ActiveXDispatchEvents(someDispatch,someEventHAndler,
    +	 * 				"Excel.Application",
    +	 * 				"C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE");
    +	 * 
    +	 * @param sourceOfEvent Dispatch object who's MS app will generate callbacks
    +	 * @param eventSink Java object that wants to receive the events
    +	 * @param progId , mandatory if the typelib is specified
    +	 * @param typeLib The location of the typelib to use
    +	 * 
    +	 */
    +	public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink,
    +			String progId, String typeLib) {
    +		super(sourceOfEvent, eventSink, progId, typeLib);
    +	}
    +
    +	/*
    +	 * (non-Javadoc)
    +	 * 
    +	 * @see com.jacob.com.DispatchEvents#getInvocationProxy(java.lang.Object)
    +	 */
    +	protected InvocationProxy getInvocationProxy(Object pTargetObject) {
    +		InvocationProxy newProxy = new ActiveXInvocationProxy();
    +		newProxy.setTarget(pTargetObject);
    +		return newProxy;
    +	}
    +
    +}
    diff --git a/vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXInvocationProxy.java b/vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXInvocationProxy.java
    new file mode 100644
    index 0000000..94c4f31
    --- /dev/null
    +++ b/vendor/jacob/1.15-M4/java/com/jacob/activeX/ActiveXInvocationProxy.java
    @@ -0,0 +1,183 @@
    +/*
    + * Copyright (c) 1999-2004 Sourceforge JACOB Project.
    + * All rights reserved. Originator: Dan Adler (http://danadler.com).
    + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
    + *
    + * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
    + */
    +package com.jacob.activeX;
    +
    +import java.lang.reflect.InvocationTargetException;
    +import java.lang.reflect.Method;
    +
    +import com.jacob.com.InvocationProxy;
    +import com.jacob.com.NotImplementedException;
    +import com.jacob.com.Variant;
    +
    +/**
    + * RELEASE 1.12 EXPERIMENTAL.
    + * 

    + * This class that lets event handlers receive events with all java objects as + * parameters. The standard Jacob event methods all accept an array of Variant + * objects. When using this class, you can set up your event methods as regular + * java methods with the correct number of parameters of the correct java type. + * This does NOT work for any event that wishes to accept a call back and modify + * the calling parameters to tell windows what to do. An example is when an + * event lets the receiver cancel the action by setting a boolean flag to false. + * The java objects cannot be modified and their values will not be passed back + * into the originating Variants even if they could be modified. + *

    + * This class acts as a proxy between the windows event callback mechanism and + * the Java classes that are looking for events. It assumes that all of the Java + * classes that are looking for events implement methods with the same names as + * the windows events and that the implemented methods native java objects of + * the type and order that match the windows documentation. The methods can + * return void or a Variant that will be returned to the calling layer. All + * Event methods that will be recognized by InvocationProxyAllEvents have the + * signature + * + * void eventMethodName(Object,Object...) or + * Object eventMethodName(Object,Object...) + */ +public class ActiveXInvocationProxy extends InvocationProxy { + + /* + * (non-Javadoc) + * + * @see com.jacob.com.InvocationProxy#invoke(java.lang.String, + * com.jacob.com.Variant[]) + */ + @SuppressWarnings("unchecked") + public Variant invoke(String methodName, Variant targetParameters[]) { + Variant mVariantToBeReturned = null; + if (mTargetObject == null) { + // structured programming guidlines say this return should not be up + // here + return null; + } + Class targetClass = mTargetObject.getClass(); + if (methodName == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing method name"); + } + if (targetParameters == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing Variant parameters"); + } + try { + Method targetMethod; + Object parametersAsJavaObjects[] = getParametersAsJavaObjects(targetParameters); + Class parametersAsJavaClasses[] = getParametersAsJavaClasses(parametersAsJavaObjects); + targetMethod = targetClass.getMethod(methodName, + parametersAsJavaClasses); + if (targetMethod != null) { + // protected classes can't be invoked against even if they + // let you grab the method. you could do + // targetMethod.setAccessible(true); + // but that should be stopped by the security manager + Object mReturnedByInvocation = null; + mReturnedByInvocation = targetMethod.invoke(mTargetObject, + parametersAsJavaObjects); + if (mReturnedByInvocation == null) { + mVariantToBeReturned = null; + } else if (!(mReturnedByInvocation instanceof Variant)) { + mVariantToBeReturned = new Variant(mReturnedByInvocation); + } else { + mVariantToBeReturned = (Variant) mReturnedByInvocation; + } + } + } catch (SecurityException e) { + // what causes this exception? + e.printStackTrace(); + } catch (NoSuchMethodException e) { + // this happens whenever the listener doesn't implement all the + // methods + } catch (IllegalArgumentException e) { + // we can throw these inside the catch block so need to re-throw it + Exception oneWeShouldToss = new IllegalArgumentException( + "Unable to map parameters for method " + methodName + ": " + + e.toString()); + oneWeShouldToss.printStackTrace(); + } catch (IllegalAccessException e) { + // can't access the method on the target instance for some reason + e.printStackTrace(); + } catch (InvocationTargetException e) { + // invocation of target method failed + e.printStackTrace(); + } + return mVariantToBeReturned; + + } + + /** + * creates a method signature compatible array of classes from an array of + * parameters + * + * @param parametersAsJavaObjects + * @return + */ + @SuppressWarnings("unchecked") + private Class[] getParametersAsJavaClasses(Object[] parametersAsJavaObjects) { + if (parametersAsJavaObjects == null) { + throw new IllegalArgumentException( + "This only works with an array of parameters"); + } + int numParameters = parametersAsJavaObjects.length; + Class parametersAsJavaClasses[] = new Class[numParameters]; + for (int parameterIndex = 0; parameterIndex < numParameters; parameterIndex++) { + Object oneParameterObject = parametersAsJavaObjects[parameterIndex]; + if (oneParameterObject == null) { + parametersAsJavaClasses[parameterIndex] = null; + } else { + Class oneParameterClass = oneParameterObject.getClass(); + parametersAsJavaClasses[parameterIndex] = oneParameterClass; + } + } + return parametersAsJavaClasses; + } + + /** + * converts an array of Variants to their associated Java types + * + * @param targetParameters + * @return + */ + private Object[] getParametersAsJavaObjects(Variant[] targetParameters) { + if (targetParameters == null) { + throw new IllegalArgumentException( + "This only works with an array of parameters"); + } + int numParameters = targetParameters.length; + Object parametersAsJavaObjects[] = new Object[numParameters]; + for (int parameterIndex = 0; parameterIndex < numParameters; parameterIndex++) { + Variant oneParameterObject = targetParameters[parameterIndex]; + if (oneParameterObject == null) { + parametersAsJavaObjects[parameterIndex] = null; + } else { + try { + parametersAsJavaObjects[parameterIndex] = oneParameterObject + .toJavaObject(); + } catch (NotImplementedException nie) { + throw new IllegalArgumentException( + "Can't convert parameter " + parameterIndex + + " type " + oneParameterObject.getvt() + + " to java object: " + nie.getMessage()); + } + } + } + return parametersAsJavaObjects; + } + +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/ComException.java b/vendor/jacob/1.15-M4/java/com/jacob/com/ComException.java new file mode 100644 index 0000000..8632577 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/ComException.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * Standard exception thrown by com jni code when there is a problem + */ +public abstract class ComException extends JacobException { + + /** + * COM code initializes this filed with an appropriate return code that was + * returned by the underlying com code + */ + protected int hr; + /** + * No documentation is available at this time. Someone should document this + * field + */ + protected int m_helpContext; + /** + * No documentation is available at this time. Someone should document this + * field + */ + protected String m_helpFile; + /** + * No documentation is available at this time. Someone should document this + * field + */ + protected String m_source; + + /** + * constructor + * + */ + public ComException() { + super(); + } + + /** + * constructor with error code? + * + * @param newHr ?? + */ + public ComException(int newHr) { + super(); + this.hr = newHr; + } + + /** + * @param newHr + * @param description + */ + public ComException(int newHr, String description) { + super(description); + this.hr = newHr; + } + + /** + * @param newHr + * @param source + * @param helpFile + * @param helpContext + */ + public ComException(int newHr, String source, String helpFile, + int helpContext) { + super(); + this.hr = newHr; + m_source = source; + m_helpFile = helpFile; + m_helpContext = helpContext; + } + + /** + * @param newHr + * @param description + * @param source + * @param helpFile + * @param helpContext + */ + public ComException(int newHr, String description, String source, + String helpFile, int helpContext) { + super(description); + this.hr = newHr; + m_source = source; + m_helpFile = helpFile; + m_helpContext = helpContext; + } + + /** + * @param description + */ + public ComException(String description) { + super(description); + } + + /** + * @return int representation of the help context + */ + // Methods + public int getHelpContext() { + return m_helpContext; + } + + /** + * @return String ??? help file + */ + public String getHelpFile() { + return m_helpFile; + } + + /** + * @return int hr result ?? + */ + public int getHResult() { + return hr; + } + + /** + * @return String source ?? + */ + public String getSource() { + return m_source; + } +} \ No newline at end of file diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/ComFailException.java b/vendor/jacob/1.15-M4/java/com/jacob/com/ComFailException.java new file mode 100644 index 0000000..20ce1a8 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/ComFailException.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * COM Fail Exception class raised when there is a problem + */ +public class ComFailException extends ComException { + /** + * eclipse generated to get rid of a wanring + */ + private static final long serialVersionUID = -266047261992987700L; + + /** + * Constructor + * + * @param hrNew + */ + public ComFailException(int hrNew) { + super(hrNew); + } + + /** + * Constructor + * + * @param hrNew + * @param message + */ + public ComFailException(int hrNew, String message) { + super(hrNew, message); + } + + /** + * @param hrNew + * @param source + * @param helpFile + * @param helpContext + */ + public ComFailException(int hrNew, String source, String helpFile, + int helpContext) { + super(hrNew, source, helpFile, helpContext); + } + + /** + * Constructor + * + * @param hrNew + * @param description + * @param source + * @param helpFile + * @param helpContext + */ + public ComFailException(int hrNew, String description, String source, + String helpFile, int helpContext) { + super(hrNew, description, source, helpFile, helpContext); + } + + /** + * No argument Constructor + */ + public ComFailException() { + super(); + } + + /** + * @param message + */ + public ComFailException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/ComThread.java b/vendor/jacob/1.15-M4/java/com/jacob/com/ComThread.java new file mode 100644 index 0000000..aeee598 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/ComThread.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * Represents a COM level thread This is an abstract class because all the + * methods are static and no instances are ever created. + */ +public abstract class ComThread { + private static final int MTA = 0x0; + + private static final int STA = 0x2; + + /** + * Comment for haveSTA + */ + public static boolean haveSTA = false; + + /** + * Comment for mainSTA + */ + public static MainSTA mainSTA = null; + + /** + * Initialize the current java thread to be part of the Multi-threaded COM + * Apartment + */ + public static synchronized void InitMTA() { + InitMTA(false); + } + + /** + * Initialize the current java thread to be an STA + */ + public static synchronized void InitSTA() { + InitSTA(false); + } + + /** + * Initialize the current java thread to be part of the Multi-threaded COM + * Apartment, if createMainSTA is true, create a separate MainSTA thread + * that will house all Apartment Threaded components + * + * @param createMainSTA + */ + public static synchronized void InitMTA(boolean createMainSTA) { + Init(createMainSTA, MTA); + } + + /** + * Initialize the current java thread to be an STA COM Apartment, if + * createMainSTA is true, create a separate MainSTA thread that will house + * all Apartment Threaded components + * + * @param createMainSTA + */ + public static synchronized void InitSTA(boolean createMainSTA) { + Init(createMainSTA, STA); + } + + /** + * + */ + public static synchronized void startMainSTA() { + mainSTA = new MainSTA(); + haveSTA = true; + } + + /** + * + */ + public static synchronized void quitMainSTA() { + if (mainSTA != null) + mainSTA.quit(); + } + + /** + * Initialize the current java thread to be part of the MTA/STA COM + * Apartment + * + * @param createMainSTA + * @param mode + */ + public static synchronized void Init(boolean createMainSTA, int mode) { + if (createMainSTA && !haveSTA) { + // if the current thread is going to be in the MTA and there + // is no STA thread yet, then create a main STA thread + // to avoid COM creating its own + startMainSTA(); + } + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: before Init: " + mode); + } + doCoInitialize(mode); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: after Init: " + mode); + } + ROT.addThread(); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: after ROT.addThread: " + mode); + } + } + + /** + * Call CoUninitialize to release this java thread from COM + */ + public static synchronized void Release() { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: before clearObjects"); + } + ROT.clearObjects(); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: before UnInit"); + } + doCoUninitialize(); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: after UnInit"); + } + } + + /** + * @deprecated the java model leave the responsibility of clearing up + * objects to the Garbage Collector. Our programming model + * should not require that the user specifically remove object + * from the thread. + * + * This will remove an object from the ROT + * @param o + */ + @Deprecated + public static synchronized void RemoveObject(JacobObject o) { + ROT.removeObject(o); + } + + /** + * @param threadModel + */ + public static native void doCoInitialize(int threadModel); + + /** + * + */ + public static native void doCoUninitialize(); + + /** + * load the Jacob DLL. We do this in case COMThread is called before any + * other reference to one of the JacboObject subclasses is made. + */ + static { + LibraryLoader.loadJacobLibrary(); + } +} \ No newline at end of file diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/Currency.java b/vendor/jacob/1.15-M4/java/com/jacob/com/Currency.java new file mode 100644 index 0000000..749506c --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/Currency.java @@ -0,0 +1,91 @@ +package com.jacob.com; + +/** + * Most COM bridges use java.lang.Long as their Java data type for COM Currency + * data. This is because COM currency is a 64 bit number where the last 4 digits + * represent the milli-cents. We wanted to support 64 bit Long values for x64 + * platforms so that meant we wanted to map Java.LONG to COM.LONG even though it + * only works for 64 bit platforms. The end result was we needed a new + * representation for Money so we have this. + *

    + * In the future, this should convert to and from BigDecimal or Double + */ +public class Currency { + Long embeddedValue = null; + + /** + * constructor that takes a long already in COM representation + * + * @param newValue + */ + public Currency(long newValue) { + embeddedValue = new Long(newValue); + } + + /** + * constructor that takes a String already in COM representation + * + * @param newValue + */ + public Currency(String newValue) { + embeddedValue = new Long(newValue); + } + + /** + * + * @return the currency as a primitive long + */ + public long longValue() { + return embeddedValue.longValue(); + } + + /** + * getter to the inner storage so that cmpareTo can work + * + * @return the embedded long value + */ + protected Long getLongValue() { + return embeddedValue; + } + + /** + * compares the values of two currencies + * + * @param anotherCurrency + * @return the usual compareTo results + */ + public int compareTo(Currency anotherCurrency) { + return embeddedValue.compareTo(anotherCurrency.getLongValue()); + } + + /** + * standard comparison + * + * @param o + * must be Currency or Long + * @return the usual compareTo results + */ + public int compareTo(Object o) { + if (o instanceof Currency) { + return compareTo((Currency) o); + } else if (o instanceof Long) { + return embeddedValue.compareTo((Long) o); + } else + throw new IllegalArgumentException( + "Can only compare to Long and Currency not " + + o.getClass().getName()); + } + + /** + * {@inheritDoc} + */ + public boolean equals(Object o) { + if (o == null) { + return false; + } else if (compareTo(o) == 0) { + return true; + } else { + return false; + } + } +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/DateUtilities.java b/vendor/jacob/1.15-M4/java/com/jacob/com/DateUtilities.java new file mode 100644 index 0000000..195ba33 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/DateUtilities.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +import java.util.Calendar; +import java.util.Date; + +/** + * java / windows date conversion utilities + * + * @author joe + * + */ +public class DateUtilities { + + /** + * converts a windows time to a Java Date Object + * + * @param comTime + * @return Date object representing the windows time as specified in comTime + */ + static public Date convertWindowsTimeToDate(double comTime) { + return new Date(convertWindowsTimeToMilliseconds(comTime)); + } + + /** + * Convert a COM time from functions Date(), Time(), Now() to a Java time + * (milliseconds). Visual Basic time values are based to 30.12.1899, Java + * time values are based to 1.1.1970 (= 0 milliseconds). The difference is + * added to the Visual Basic value to get the corresponding Java value. The + * Visual Basic double value reads: .<1 + * day percentage fraction>, e.g. "38100.6453" means: 38100 days since + * 30.12.1899 plus (24 hours * 0.6453). Example usage: + * Date javaDate = new Date(toMilliseconds (vbDate));. + * + * @param comTime + * COM time. + * @return Java time. + */ + static public long convertWindowsTimeToMilliseconds(double comTime) { + long result = 0; + + // code from jacobgen: + comTime = comTime - 25569D; + Calendar cal = Calendar.getInstance(); + result = Math.round(86400000L * comTime) + - cal.get(Calendar.ZONE_OFFSET); + cal.setTime(new Date(result)); + result -= cal.get(Calendar.DST_OFFSET); + + return result; + }// convertWindowsTimeToMilliseconds() + + /** + * converts a java date to a windows time object (is this timezone safe?) + * + * @param javaDate + * the java date to be converted to windows time + * @return the double representing the date in a form windows understands + */ + static public double convertDateToWindowsTime(Date javaDate) { + if (javaDate == null) { + throw new IllegalArgumentException( + "cannot convert null to windows time"); + } + return convertMillisecondsToWindowsTime(javaDate.getTime()); + } + + /** + * Convert a Java time to a COM time. + * + * @param milliseconds + * Java time. + * @return COM time. + */ + static public double convertMillisecondsToWindowsTime(long milliseconds) { + double result = 0.0; + + // code from jacobgen: + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(milliseconds); + milliseconds += (cal.get(Calendar.ZONE_OFFSET) + cal + .get(Calendar.DST_OFFSET)); // add GMT offset + result = (milliseconds / 86400000D) + 25569D; + + return result; + }// convertMillisecondsToWindowsTime() +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/Dispatch.java b/vendor/jacob/1.15-M4/java/com/jacob/com/Dispatch.java new file mode 100644 index 0000000..4902c46 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/Dispatch.java @@ -0,0 +1,872 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. All rights reserved. Originator: Dan Adler + * (http://danadler.com). Get more information about JACOB at + * http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +package com.jacob.com; + +/** + * Object represents MS level dispatch object. Each instance of this points at + * some data structure on the MS windows side. + * + * + *

    + * You're going to live here a lot + */ +public class Dispatch extends JacobObject { + + /** + * Used to set the locale in a call. The user locale is another option + */ + public static final int LOCALE_SYSTEM_DEFAULT = 2048; + /** used by callN() and callSubN() */ + public static final int Method = 1; + /** used by callN() and callSubN() */ + public static final int Get = 2; + /** used by put() */ + public static final int Put = 4; + /** not used, probably intended for putRef() */ + public static final int PutRef = 8; + /** + * One of legal values for GetDispId. Not used in this layer and probably + * not needed. + */ + public static final int fdexNameCaseSensitive = 1; + + /** + * This is public because Dispatch.cpp knows its name and accesses it + * directly to get the dispatch id. You really can't rename it or make it + * private + */ + public int m_pDispatch; + + /** program Id passed in by ActiveX components in their constructor */ + private String programId = null; + + private static int NOT_ATTACHED = 0; + + /** + * Dummy empty array used one doesn't have to be created on every invocation + */ + private final static Object[] NO_OBJECT_ARGS = new Object[0]; + /** + * Dummy empty array used one doesn't have to be created on every invocation + */ + private final static Variant[] NO_VARIANT_ARGS = new Variant[0]; + /** + * Dummy empty array used one doesn't have to be created on every invocation + */ + private final static int[] NO_INT_ARGS = new int[0]; + + /** + * zero argument constructor that sets the dispatch pointer to 0 This is the + * only way to create a Dispatch without a value in the pointer field. + */ + public Dispatch() { + m_pDispatch = NOT_ATTACHED; + } + + /** + * This constructor calls createInstance with progid. This is the + * constructor used by the ActiveXComponent or by programs that don't like + * the activeX interface but wish to create new connections to windows + * programs. + *

    + * This constructor always creates a new windows/program object because it + * is based on the CoCreate() windows function. + *

    + * + * @param requestedProgramId + * @throws IllegalArgumentException + * if null is passed in as the program id + *

    + */ + public Dispatch(String requestedProgramId) { + programId = requestedProgramId; + if (programId != null && !"".equals(programId)) { + createInstanceNative(requestedProgramId); + } else { + throw new IllegalArgumentException( + "Dispatch(String) does not accept null or an empty string as a parameter"); + } + } + + /** + * native call createInstance only used by the constructor with the same + * parm type. This probably should be private. It is the wrapper for the + * Windows CoCreate() call + *

    + * This ends up calling CoCreate down in the JNI layer + *

    + * The behavior is different if a ":" character exists in the progId. In + * that case CoGetObject and CreateInstance (someone needs to describe this + * better) + * + * @param progid + */ + private native void createInstanceNative(String progid); + + /** + * native call getActiveInstance only used by the constructor with the same + * parm type. This probably should be private. It is the wrapper for the + * Windows GetActiveObject() call + *

    + * This ends up calling GetActiveObject down in the JNI layer + *

    + * This does not have the special behavior for program ids with ":" in them + * that createInstance has. + * + * @param progid + */ + private native void getActiveInstanceNative(String progid); + + /** + * Wrapper around the native method + * + * @param pProgramIdentifier + * name of the program you wish to connect to + */ + protected void getActiveInstance(String pProgramIdentifier) { + if (pProgramIdentifier == null || "".equals(pProgramIdentifier)) { + throw new IllegalArgumentException("program id is required"); + } + this.programId = pProgramIdentifier; + getActiveInstanceNative(pProgramIdentifier); + } + + /** + * native call coCreateInstance only used by the constructor with the same + * parm type. This probably should be private. It is the wrapper for the + * Windows CoCreate() call + *

    + * This ends up calling CoCreate down in the JNI layer + *

    + * This does not have the special behavior for program ids with ":" in them + * that createInstance has. + * + * @param progid + */ + private native void coCreateInstanceNative(String progid); + + /** + * Wrapper around the native method + * + * @param pProgramIdentifier + */ + protected void coCreateInstance(String pProgramIdentifier) { + if (pProgramIdentifier == null || "".equals(pProgramIdentifier)) { + throw new IllegalArgumentException("program id is required"); + } + this.programId = pProgramIdentifier; + coCreateInstanceNative(pProgramIdentifier); + } + + /** + * Return a different interface by IID string. + *

    + * Once you have a Dispatch object, you can navigate to the other interfaces + * of a COM object by calling QueryInterafce. The argument is an IID string + * in the format: "{9BF24410-B2E0-11D4-A695-00104BFF3241}". You typically + * get this string from the idl file (it's called uuid in there). Any + * interface you try to use must be derived from IDispatch. T The atl + * example uses this. + *

    + * The Dispatch instance resulting from this query is instanciated in the + * JNI code. + * + * @param iid + * @return Dispatch a disptach that matches ?? + */ + public native Dispatch QueryInterface(String iid); + + /** + * Constructor that only gets called from JNI QueryInterface calls JNI code + * that looks up the object for the key passed in. The JNI CODE then creates + * a new dispatch object using this constructor + * + * @param pDisp + */ + protected Dispatch(int pDisp) { + m_pDispatch = pDisp; + } + + /** + * Constructor to be used by subclass that want to swap themselves in for + * the default Dispatch class. Usually you will have a class like + * WordDocument that is a subclass of Dispatch and it will have a + * constructor public WordDocument(Dispatch). That constructor should just + * call this constructor as super(Dispatch) + * + * @param dispatchToBeDisplaced + */ + public Dispatch(Dispatch dispatchToBeDisplaced) { + // TAKE OVER THE IDispatch POINTER + this.m_pDispatch = dispatchToBeDisplaced.m_pDispatch; + // NULL OUT THE INPUT POINTER + dispatchToBeDisplaced.m_pDispatch = NOT_ATTACHED; + } + + /** + * returns the program id if an activeX component created this otherwise it + * returns null. This was added to aid in debugging + * + * @return the program id an activeX component was created against + */ + public String getProgramId() { + return programId; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + @Override + protected void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + @Override + public void safeRelease() { + super.safeRelease(); + if (isAttached()) { + release(); + m_pDispatch = NOT_ATTACHED; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } + + /** + * + * @return true if there is an underlying windows dispatch object + */ + protected boolean isAttached() { + if (m_pDispatch == NOT_ATTACHED) { + return false; + } else { + return true; + } + } + + /** + * @param theOneInQuestion + * dispatch being tested + * @throws IllegalStateException + * if this dispatch isn't hooked up + * @throws IllegalArgumentException + * if null the dispatch under test is null + */ + private static void throwIfUnattachedDispatch(Dispatch theOneInQuestion) { + if (theOneInQuestion == null) { + throw new IllegalArgumentException( + "Can't pass in null Dispatch object"); + } else if (theOneInQuestion.isAttached()) { + return; + } else { + throw new IllegalStateException( + "Dispatch not hooked to windows memory"); + } + } + + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /** + * not implemented yet + * + * @param dispatchTarget + * @param name + * @param val + * @throws com.jacob.com.NotImplementedException + */ + public static void put_Casesensitive(Dispatch dispatchTarget, String name, + Object val) { + throw new NotImplementedException("not implemented yet"); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + // eliminate _Guid arg + /** + * @param dispatchTarget + * @param name + * @param dispID + * @param lcid + * @param wFlags + * @param vArg + * @param uArgErr + */ + public static void invokeSubv(Dispatch dispatchTarget, String name, + int dispID, int lcid, int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokev(dispatchTarget, name, dispID, lcid, wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param vArg + * @param uArgErr + */ + public static void invokeSubv(Dispatch dispatchTarget, String name, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param dispID + * @param wFlags + * @param vArg + * @param uArgErr + */ + public static void invokeSubv(Dispatch dispatchTarget, int dispID, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokev(dispatchTarget, null, dispID, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * not implemented yet + * + * @param dispatchTarget + * @param name + * @param values + * @return never returns anything because + * @throws com.jacob.com.NotImplementedException + */ + public static Variant callN_CaseSensitive(Dispatch dispatchTarget, + String name, Object[] values) { + throw new NotImplementedException("not implemented yet"); + } + + /** + * @param dispatchTarget + * @param name + * @param args + * an array of argument objects + */ + public static void callSubN(Dispatch dispatchTarget, String name, + Object... args) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSubv(dispatchTarget, name, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), new int[args.length]); + } + + /** + * @param dispatchTarget + * @param dispID + * @param args + * an array of argument objects + */ + public static void callSubN(Dispatch dispatchTarget, int dispID, + Object... args) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSubv(dispatchTarget, dispID, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), new int[args.length]); + } + + /* + * ============================================================ start of the + * getIdsOfNames section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @return int id for the passed in name + */ + public static int getIDOfName(Dispatch dispatchTarget, String name) { + int ids[] = getIDsOfNames(dispatchTarget, + Dispatch.LOCALE_SYSTEM_DEFAULT, new String[] { name }); + return ids[0]; + } + + /** + * @param dispatchTarget + * @param lcid + * @param names + * @return int[] in id array for passed in names + */ + // eliminated _Guid argument + public static native int[] getIDsOfNames(Dispatch dispatchTarget, int lcid, + String[] names); + + /** + * @param dispatchTarget + * @param names + * @return int[] int id array for passed in names + */ + // eliminated _Guid argument + public static int[] getIDsOfNames(Dispatch dispatchTarget, String[] names) { + return getIDsOfNames(dispatchTarget, Dispatch.LOCALE_SYSTEM_DEFAULT, + names); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @param args + * @return Variant returned by call + */ + public static Variant callN(Dispatch dispatchTarget, String name, + Object... args) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), new int[args.length]); + } + + /** + * @param dispatchTarget + * @param dispID + * @param args + * @return Variant returned by call + */ + public static Variant callN(Dispatch dispatchTarget, int dispID, + Object... args) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, dispID, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), new int[args.length]); + } + + /** + * @param dispatchTarget + * @param name + * @param dispID + * @param lcid + * @param wFlags + * @param oArg + * @param uArgErr + * @return Variant returned by invoke + */ + public static Variant invoke(Dispatch dispatchTarget, String name, + int dispID, int lcid, int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, dispID, lcid, wFlags, + VariantUtilities.objectsToVariants(oArg), uArgErr); + } + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param oArg + * @param uArgErr + * @return Variant returned by invoke + */ + public static Variant invoke(Dispatch dispatchTarget, String name, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, wFlags, VariantUtilities + .objectsToVariants(oArg), uArgErr); + } + + /** + * @param dispatchTarget + * @param dispID + * @param wFlags + * @param oArg + * @param uArgErr + * @return Variant returned by invoke + */ + public static Variant invoke(Dispatch dispatchTarget, int dispID, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, dispID, wFlags, VariantUtilities + .objectsToVariants(oArg), uArgErr); + } + + /* + * ============================================================ start of the + * callN section =========================================================== + */ + + /** + * @param dispatchTarget + * @param name + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, NO_VARIANT_ARGS); + } + + /** + * @param dispatchTarget + * @param name + * @param attributes + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name, + Object... attributes) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, attributes); + } + + /** + * @param dispatchTarget + * @param dispid + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, NO_VARIANT_ARGS); + } + + /** + * @param dispatchTarget + * @param dispid + * @param attributes + * var arg list of attributes that will be passed to the + * underlying function + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid, + Object... attributes) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, attributes); + } + + /* + * ============================================================ start of the + * invoke section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @param val + */ + public static void put(Dispatch dispatchTarget, String name, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, name, Dispatch.Put, new Object[] { val }, + new int[1]); + } + + /** + * @param dispatchTarget + * @param dispid + * @param val + */ + public static void put(Dispatch dispatchTarget, int dispid, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, dispid, Dispatch.Put, new Object[] { val }, + new int[1]); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + // removed _Guid argument + /** + * @param dispatchTarget + * @param name + * @param dispID + * @param lcid + * @param wFlags + * @param vArg + * @param uArgErr + * @return Variant returned by underlying invokev + */ + public static native Variant invokev(Dispatch dispatchTarget, String name, + int dispID, int lcid, int wFlags, Variant[] vArg, int[] uArgErr); + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param vArg + * @param uArgErr + * @return Variant returned by underlying invokev + */ + public static Variant invokev(Dispatch dispatchTarget, String name, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param vArg + * @param uArgErr + * @param wFlagsEx + * @return Variant returned by underlying invokev + */ + public static Variant invokev(Dispatch dispatchTarget, String name, + int wFlags, Variant[] vArg, int[] uArgErr, int wFlagsEx) { + throwIfUnattachedDispatch(dispatchTarget); + // do not implement IDispatchEx for now + return invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param dispID + * @param wFlags + * @param vArg + * @param uArgErr + * @return Variant returned by underlying invokev + */ + public static Variant invokev(Dispatch dispatchTarget, int dispID, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, null, dispID, + Dispatch.LOCALE_SYSTEM_DEFAULT, wFlags, vArg, uArgErr); + } + + /* + * ============================================================ start of the + * invokeSubv section + * =========================================================== + */ + + // removed _Guid argument + /** + * @param dispatchTarget + * @param name + * @param dispid + * @param lcid + * @param wFlags + * @param oArg + * @param uArgErr + */ + public static void invokeSub(Dispatch dispatchTarget, String name, + int dispid, int lcid, int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSubv(dispatchTarget, name, dispid, lcid, wFlags, VariantUtilities + .objectsToVariants(oArg), uArgErr); + } + + /* + * ============================================================ start of the + * invokeSub section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param oArg + * @param uArgErr + */ + public static void invokeSub(Dispatch dispatchTarget, String name, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSub(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, oArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param dispid + * @param wFlags + * @param oArg + * @param uArgErr + */ + public static void invokeSub(Dispatch dispatchTarget, int dispid, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSub(dispatchTarget, null, dispid, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, oArg, uArgErr); + } + + /* + * ============================================================ start of the + * callSubN section + * =========================================================== + */ + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + */ + public static void callSub(Dispatch dispatchTarget, String name) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, NO_OBJECT_ARGS); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + * @param attributes + * var args list of attributes to be passed to underlying + * functions + */ + public static void callSub(Dispatch dispatchTarget, String name, + Object... attributes) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, attributes); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + */ + public static void callSub(Dispatch dispatchTarget, int dispid) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, NO_OBJECT_ARGS); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + * @param attributes + * var args list of attributes to be passed to underlying + * function + */ + public static void callSub(Dispatch dispatchTarget, int dispid, + Object... attributes) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, attributes); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + /** + * Cover for call to underlying invokev() + * + * @param dispatchTarget + * @param name + * @return Variant returned by the request for retrieval of parameter + */ + public static Variant get(Dispatch dispatchTarget, String name) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, Dispatch.Get, NO_VARIANT_ARGS, + NO_INT_ARGS); + } + + /** + * Cover for call to underlying invokev() + * + * @param dispatchTarget + * @param dispid + * @return Variant returned by the request for retrieval of parameter + */ + public static Variant get(Dispatch dispatchTarget, int dispid) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, dispid, Dispatch.Get, NO_VARIANT_ARGS, + NO_INT_ARGS); + } + + /* + * ============================================================ start of the + * invoke section + * =========================================================== + */ + /** + * cover for underlying call to invoke + * + * @param dispatchTarget + * @param name + * @param val + */ + public static void putRef(Dispatch dispatchTarget, String name, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, name, Dispatch.PutRef, new Object[] { val }, + new int[1]); + } + + /** + * cover for underlying call to invoke + * + * @param dispatchTarget + * @param dispid + * @param val + */ + public static void putRef(Dispatch dispatchTarget, int dispid, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, dispid, Dispatch.PutRef, new Object[] { val }, + new int[1]); + } + + /** + * not implemented yet + * + * @param dispatchTarget + * @param name + * @return Variant never returned + * @throws com.jacob.com.NotImplementedException + */ + public static Variant get_CaseSensitive(Dispatch dispatchTarget, String name) { + throw new NotImplementedException("not implemented yet"); + } + + /** + * Cover for native method + * + * @param disp + * @param dispid + * @param lcid + * @return 0 if the dispatch is still active and 1 if it has exited + */ + public static native int hasExited(Dispatch disp, int dispid, int lcid); + + /** + * The method is used to poll until it returns 1, indicating that the COM + * server in gone. + *

    + * Sourceforge feature request 2927058 + * + * @param dispatchTarget + * @return 0 if the dispatch is still active and 1 if it has exited + */ + public static int hasExited(Dispatch dispatchTarget) { + throwIfUnattachedDispatch(dispatchTarget); + return hasExited(dispatchTarget, 0, LOCALE_SYSTEM_DEFAULT); + } + +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/DispatchEvents.java b/vendor/jacob/1.15-M4/java/com/jacob/com/DispatchEvents.java new file mode 100644 index 0000000..a9ca0a1 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/DispatchEvents.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * This class creates the scaffolding for event callbacks. Every instance of tis + * acts as a wrapper around some java object that wants callbacks from the + * microsoft side. It represents the connection between Java and COM for + * callbacks. + *

    + * The callback mechanism will take any event that it receives and try and find + * a java method with the same name that accepts the Variant... as a parameter. + * It will then wrap the call back data in the Variant array and call the java + * method of the object that this DispatchEvents object was initialized with. + *

    + * Instances of this class are created with "sink object" that will receive the + * event messages. The sink object is wrapped in an Invocation handler that + * actually receives the messages and then forwards them on to the "sink + * object". The constructors recognize when an instance of InvocationProxy is + * passed in and do not create a new InvocationProxy as a wrapper. They instead + * use the passed in InvocationProxy. + * + */ +public class DispatchEvents extends JacobObject { + + /** + * pointer to an MS data struct. The COM layer knows the name of this + * variable and puts the windows memory pointer here. + */ + int m_pConnPtProxy = 0; + + /** + * the wrapper for the event sink. This object is the one that will be sent + * a message when an event occurs in the MS layer. Normally, the + * InvocationProxy will forward the messages to a wrapped object that it + * contains. + */ + InvocationProxy mInvocationProxy = null; + + /** + * This is the most commonly used constructor. + *

    + * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + *

    + * Can be used on any object that implements IProvideClassInfo. + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + */ + public DispatchEvents(Dispatch sourceOfEvent, Object eventSink) { + this(sourceOfEvent, eventSink, null); + } + + /** + * None of the samples use this constructor. + *

    + * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + *

    + * Used when the program doesn't implement IProvideClassInfo. It provides a + * way to find the TypeLib in the registry based on the programId. The + * TypeLib is looked up in the registry on the path + * HKEY_LOCAL_MACHINE/SOFTWARE/Classes/CLSID/(CLID drived from + * progid)/ProgID/Typelib + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + * @param progId + * program id in the registry that has a TypeLib subkey. The + * progrId is mapped to a CLSID that is they used to look up the + * key to the Typelib + */ + public DispatchEvents(Dispatch sourceOfEvent, Object eventSink, + String progId) { + this(sourceOfEvent, eventSink, progId, null); + } + + /** + * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + *

    + * This method was added because Excel doesn't implement IProvideClassInfo + * and the registry entry for Excel.Application doesn't include a typelib + * key. + * + *

    +	 * DispatchEvents de = new DispatchEvents(someDispatch, someEventHAndler,
    +	 * 		"Excel.Application",
    +	 * 		"C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE");
    +	 * 
    + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + * @param progId , + * mandatory if the typelib is specified + * @param typeLib + * The location of the typelib to use + */ + public DispatchEvents(Dispatch sourceOfEvent, Object eventSink, + String progId, String typeLib) { + if (JacobObject.isDebugEnabled()) { + System.out.println("DispatchEvents: Registering " + eventSink + + "for events "); + } + if (eventSink instanceof InvocationProxy) { + mInvocationProxy = (InvocationProxy) eventSink; + } else { + mInvocationProxy = getInvocationProxy(eventSink); + } + if (mInvocationProxy != null) { + init3(sourceOfEvent, mInvocationProxy, progId, typeLib); + } else { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("Cannot register null event sink for events"); + } + throw new IllegalArgumentException( + "Cannot register null event sink for events"); + } + } + + /** + * Returns an instance of the proxy configured with pTargetObject as its + * target + * + * @param pTargetObject + * @return InvocationProxy an instance of the proxy this DispatchEvents will + * send to the COM layer + */ + protected InvocationProxy getInvocationProxy(Object pTargetObject) { + InvocationProxy newProxy = new InvocationProxyAllVariants(); + newProxy.setTarget(pTargetObject); + return newProxy; + } + + /** + * hooks up a connection point proxy by progId event methods on the sink + * object will be called by name with a signature of (Variant[] args) + * + * You must specify the location of the typeLib. + * + * @param src + * dispatch that is the source of the messages + * @param sink + * the object that will receive the messages + * @param progId + * optional program id. most folks don't need this either + * @param typeLib + * optional parameter for those programs that don't register + * their type libs (like Excel) + */ + private native void init3(Dispatch src, Object sink, String progId, + String typeLib); + + /** + * now private so only this object can asccess was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + protected void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + if (mInvocationProxy != null) { + mInvocationProxy.setTarget(null); + } + mInvocationProxy = null; + super.safeRelease(); + if (m_pConnPtProxy != 0) { + release(); + m_pConnPtProxy = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug("DispatchEvents:" + this.hashCode() + " double release"); + } + } + } + +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/DispatchIdentifier.java b/vendor/jacob/1.15-M4/java/com/jacob/com/DispatchIdentifier.java new file mode 100644 index 0000000..cebd9f8 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/DispatchIdentifier.java @@ -0,0 +1,82 @@ +/** + * + */ +package com.jacob.com; + +/** + * A bunch of DispatchIds that were pulled out of the Dispatch class for version + * 1.14. + */ +public class DispatchIdentifier { + + private DispatchIdentifier() { + // This is utility class so there is no constructor. + } + + public static final int DISPID_UNKNOWN = -1; + public static final int DISPID_VALUE = 0; + public static final int DISPID_PROPERTYPUT = -3; + public static final int DISPID_NEWENUM = -4; + public static final int DISPID_EVALUATE = -5; + public static final int DISPID_CONSTRUCTOR = -6; + public static final int DISPID_DESTRUCTOR = -7; + public static final int DISPID_COLLECT = -8; + public static final int DISPID_AUTOSIZE = -500; + public static final int DISPID_BACKCOLOR = -501; + public static final int DISPID_BACKSTYLE = -502; + public static final int DISPID_BORDERCOLOR = -503; + public static final int DISPID_BORDERSTYLE = -504; + public static final int DISPID_BORDERWIDTH = -505; + public static final int DISPID_DRAWMODE = -507; + public static final int DISPID_DRAWSTYLE = -508; + public static final int DISPID_DRAWWIDTH = -509; + public static final int DISPID_FILLCOLOR = -510; + public static final int DISPID_FILLSTYLE = -511; + public static final int DISPID_FONT = -512; + public static final int DISPID_FORECOLOR = -513; + public static final int DISPID_ENABLED = -514; + public static final int DISPID_HWND = -515; + public static final int DISPID_TABSTOP = -516; + public static final int DISPID_TEXT = -517; + public static final int DISPID_CAPTION = -518; + public static final int DISPID_BORDERVISIBLE = -519; + public static final int DISPID_APPEARANCE = -520; + public static final int DISPID_MOUSEPOINTER = -521; + public static final int DISPID_MOUSEICON = -522; + public static final int DISPID_PICTURE = -523; + public static final int DISPID_VALID = -524; + public static final int DISPID_READYSTATE = -525; + public static final int DISPID_REFRESH = -550; + public static final int DISPID_DOCLICK = -551; + public static final int DISPID_ABOUTBOX = -552; + public static final int DISPID_CLICK = -600; + public static final int DISPID_DBLCLICK = -601; + public static final int DISPID_KEYDOWN = -602; + public static final int DISPID_KEYPRESS = -603; + public static final int DISPID_KEYUP = -604; + public static final int DISPID_MOUSEDOWN = -605; + public static final int DISPID_MOUSEMOVE = -606; + public static final int DISPID_MOUSEUP = -607; + public static final int DISPID_ERROREVENT = -608; + public static final int DISPID_READYSTATECHANGE = -609; + public static final int DISPID_AMBIENT_BACKCOLOR = -701; + public static final int DISPID_AMBIENT_DISPLAYNAME = -702; + public static final int DISPID_AMBIENT_FONT = -703; + public static final int DISPID_AMBIENT_FORECOLOR = -704; + public static final int DISPID_AMBIENT_LOCALEID = -705; + public static final int DISPID_AMBIENT_MESSAGEREFLECT = -706; + public static final int DISPID_AMBIENT_SCALEUNITS = -707; + public static final int DISPID_AMBIENT_TEXTALIGN = -708; + public static final int DISPID_AMBIENT_USERMODE = -709; + public static final int DISPID_AMBIENT_UIDEAD = -710; + public static final int DISPID_AMBIENT_SHOWGRABHANDLES = -711; + public static final int DISPID_AMBIENT_SHOWHATCHING = -712; + public static final int DISPID_AMBIENT_DISPLAYASDEFAULT = -713; + public static final int DISPID_AMBIENT_SUPPORTSMNEMONICS = -714; + public static final int DISPID_AMBIENT_AUTOCLIP = -715; + public static final int DISPID_AMBIENT_APPEARANCE = -716; + public static final int DISPID_AMBIENT_CODEPAGE = -725; + public static final int DISPID_AMBIENT_PALETTE = -726; + public static final int DISPID_AMBIENT_CHARSET = -727; + public static final int DISPID_AMBIENT_TRANSFERPRIORITY = -728; +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/DispatchProxy.java b/vendor/jacob/1.15-M4/java/com/jacob/com/DispatchProxy.java new file mode 100644 index 0000000..c8f08cf --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/DispatchProxy.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * If you need to pass a COM Dispatch object between STA threads, you have to + * marshall the interface. This class is used as follows: the STA that creates + * the Dispatch object must construct an instance of this class. Another thread + * can then call toDispatch() on that instance and get a Dispatch pointer which + * has been marshalled. WARNING: You can only call toDispatch() once! If you + * need to call it multiple times (or from multiple threads) you need to + * construct a separate DispatchProxy instance for each such case! + */ +public class DispatchProxy extends JacobObject { + /** + * Comment for m_pStream + */ + public int m_pStream; + + /** + * Marshals the passed in dispatch into the stream + * + * @param localDispatch + */ + public DispatchProxy(Dispatch localDispatch) { + MarshalIntoStream(localDispatch); + } + + /** + * + * @return Dispatch the dispatch retrieved from the stream + */ + public Dispatch toDispatch() { + return MarshalFromStream(); + } + + private native void MarshalIntoStream(Dispatch d); + + private native Dispatch MarshalFromStream(); + + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + public void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + super.safeRelease(); + if (m_pStream != 0) { + release(); + m_pStream = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } +} \ No newline at end of file diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/EnumVariant.java b/vendor/jacob/1.15-M4/java/com/jacob/com/EnumVariant.java new file mode 100644 index 0000000..8ff298f --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/EnumVariant.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * An implementation of IEnumVariant based on code submitted by Thomas Hallgren + * (mailto:Thomas.Hallgren@eoncompany.com) + */ +public class EnumVariant extends JacobObject implements + java.util.Enumeration { + private int m_pIEnumVARIANT; + + private final Variant[] m_recBuf = new Variant[1]; + + // this only gets called from JNI + // + protected EnumVariant(int pIEnumVARIANT) { + m_pIEnumVARIANT = pIEnumVARIANT; + } + + /** + * @param disp + */ + public EnumVariant(Dispatch disp) { + int[] hres = new int[1]; + Variant evv = Dispatch.invokev(disp, DispatchIdentifier.DISPID_NEWENUM, + Dispatch.Get, new Variant[0], hres); + if (evv.getvt() != Variant.VariantObject) + // + // The DISPID_NEWENUM did not result in a valid object + // + throw new ComFailException("Can't obtain EnumVARIANT"); + + EnumVariant tmp = evv.toEnumVariant(); + m_pIEnumVARIANT = tmp.m_pIEnumVARIANT; + tmp.m_pIEnumVARIANT = 0; + } + + /** + * Implements java.util.Enumeration + * + * @return boolean true if there are more elements in this enumeration + */ + public boolean hasMoreElements() { + { + if (m_recBuf[0] == null) { + if (this.Next(m_recBuf) <= 0) + return false; + } + return true; + } + } + + /** + * Implements java.util.Enumeration + * + * @return next element in the enumeration + */ + public Variant nextElement() { + Variant last = m_recBuf[0]; + if (last == null) { + if (this.Next(m_recBuf) <= 0) + throw new java.util.NoSuchElementException(); + last = m_recBuf[0]; + } + m_recBuf[0] = null; + return last; + } + + /** + * Get next element in collection or null if at end + * + * @return Variant that is next in the collection + * @deprecated use nextElement() instead + */ + @Deprecated + public Variant Next() { + if (hasMoreElements()) + return nextElement(); + return null; + } + + /** + * This should be private and wrapped to protect JNI layer. + * + * @param receiverArray + * @return Returns the next variant object pointer as an int from windows + * layer + */ + public native int Next(Variant[] receiverArray); + + /** + * This should be private and wrapped to protect JNI layer. + * + * @param count + * number to skip + */ + public native void Skip(int count); + + /** + * This should be private and wrapped to protect JNI layer + */ + public native void Reset(); + + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + protected void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + super.safeRelease(); + if (m_pIEnumVARIANT != 0) { + this.release(); + m_pIEnumVARIANT = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } +} \ No newline at end of file diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/InvocationProxy.java b/vendor/jacob/1.15-M4/java/com/jacob/com/InvocationProxy.java new file mode 100644 index 0000000..7687d84 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/InvocationProxy.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * @version $Id$ + * @author joe + * + * DispatchEvents wraps this class around any event handlers before making the + * JNI call that sets up the link with EventProxy. This means that + * EventProxy.cpp just calls invoke(String,Variant[]) against the instance of + * this class. Then this class does reflection against the event listener to + * call the actual event methods. The event methods can return void or return a + * Variant. Any value returned will be passed back to the calling windows module + * by the Jacob JNI layer. + *

    + * + * The void returning signature is the standard legacy signature. The Variant + * returning signature was added in 1.10 to support event handlers returning + * values. + * + */ +public abstract class InvocationProxy { + + /** + * the object we will try and forward to. + */ + protected Object mTargetObject = null; + + /** + * dummy constructor for subclasses that don't actually wrap anything and + * just want to override the invoke() method + */ + protected InvocationProxy() { + super(); + } + + /** + * The method actually invoked by EventProxy.cpp. The method name is + * calculated by the underlying JNI code from the MS windows Callback + * function name. The method is assumed to take an array of Variant objects. + * The method may return a Variant or be a void. Those are the only two + * options that will not blow up. + *

    + * Subclasses that override this should make sure mTargetObject is not null + * before processing. + * + * @param methodName + * name of method in mTargetObject we will invoke + * @param targetParameters + * Variant[] that is the single parameter to the method + * @return an object that will be returned to the com event caller + */ + public abstract Variant invoke(String methodName, + Variant targetParameters[]); + + /** + * used by EventProxy.cpp to create variant objects in the right thread + * + * @return Variant object that will be used by the COM layer + */ + public Variant getVariant() { + return new VariantViaEvent(); + } + + /** + * Sets the target for this InvocationProxy. + * + * @param pTargetObject + * @throws IllegalArgumentException + * if target is not publicly accessible + */ + public void setTarget(Object pTargetObject) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: setting target " + + pTargetObject); + } + if (pTargetObject != null) { + // JNI code apparently bypasses this check and could operate against + // protected classes. This seems like a security issue... + // maybe it was because JNI code isn't in a package? + if (!java.lang.reflect.Modifier.isPublic(pTargetObject.getClass() + .getModifiers())) { + throw new IllegalArgumentException( + "InvocationProxy only public classes can receive event notifications"); + } + } + mTargetObject = pTargetObject; + } + +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/InvocationProxyAllVariants.java b/vendor/jacob/1.15-M4/java/com/jacob/com/InvocationProxyAllVariants.java new file mode 100644 index 0000000..3a5d846 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/InvocationProxyAllVariants.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * This class acts as a proxy between the windows event callback mechanism and + * the Java classes that are looking for events. It assumes that all of the Java + * classes that are looking for events implement methods with the same names as + * the windows events and that the implemented methods accept an array of + * variant objects. The methods can return void or a Variant that will be + * returned to the calling layer. All Event methods that will be recognized by + * InvocationProxyAllEvents have the signature + * + * void eventMethodName(Variant[]) or + * Variant eventMethodName(Variant[]) + */ +public class InvocationProxyAllVariants extends InvocationProxy { + + /* + * (non-Javadoc) + * + * @see com.jacob.com.InvocationProxy#invoke(java.lang.String, + * com.jacob.com.Variant[]) + */ + @SuppressWarnings("unchecked") + public Variant invoke(String methodName, Variant targetParameters[]) { + Variant mVariantToBeReturned = null; + if (mTargetObject == null) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: received notification (" + + methodName + ") with no target set"); + } + // structured programming guidlines say this return should not be up + // here + return null; + } + Class targetClass = mTargetObject.getClass(); + if (methodName == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing method name"); + } + if (targetParameters == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing Variant parameters"); + } + try { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: trying to invoke " + + methodName + " on " + mTargetObject); + } + Method targetMethod; + targetMethod = targetClass.getMethod(methodName, + new Class[] { Variant[].class }); + if (targetMethod != null) { + // protected classes can't be invoked against even if they + // let you grab the method. you could do + // targetMethod.setAccessible(true); + // but that should be stopped by the security manager + Object mReturnedByInvocation = null; + mReturnedByInvocation = targetMethod.invoke(mTargetObject, + new Object[] { targetParameters }); + if (mReturnedByInvocation == null) { + mVariantToBeReturned = null; + } else if (!(mReturnedByInvocation instanceof Variant)) { + // could try and convert to Variant here. + throw new IllegalArgumentException( + "InvocationProxy: invokation of target method returned " + + "non-null non-variant object: " + + mReturnedByInvocation); + } else { + mVariantToBeReturned = (Variant) mReturnedByInvocation; + } + } + } catch (SecurityException e) { + // what causes this exception? + e.printStackTrace(); + } catch (NoSuchMethodException e) { + // this happens whenever the listener doesn't implement all the + // methods + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: listener (" + mTargetObject + + ") doesn't implement " + methodName); + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + // we can throw these inside the catch block so need to re-throw it + throw e; + } catch (IllegalAccessException e) { + // can't access the method on the target instance for some reason + if (JacobObject.isDebugEnabled()) { + JacobObject + .debug("InvocationProxy: probably tried to access public method on non public class" + + methodName); + } + e.printStackTrace(); + } catch (InvocationTargetException e) { + // invocation of target method failed + e.printStackTrace(); + } + return mVariantToBeReturned; + + } +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/JacobException.java b/vendor/jacob/1.15-M4/java/com/jacob/com/JacobException.java new file mode 100644 index 0000000..6e2e926 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/JacobException.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * The parent class of all Jacob exceptions. They all used to be based off of + * RuntimeException or ComException but it was decided to base them all off of + * one owned by this project. + */ +public class JacobException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = -1637125318746002715L; + + /** + * Default constructor. Calls super with a "No Message Provided" string + */ + public JacobException() { + super("No Message Provided"); + } + + /** + * standard constructor + * + * @param message + */ + public JacobException(String message) { + super(message); + } +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/JacobObject.java b/vendor/jacob/1.15-M4/java/com/jacob/com/JacobObject.java new file mode 100644 index 0000000..acd346c --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/JacobObject.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * The superclass of all Jacob objects. It is used to create a standard API + * framework and to facilitate memory management for Java and COM memory + * elements. + *

    + * All instances of this class and subclasses are automatically managed by the + * ROT. This means the ROT cannot be a subclass of JacobObject. + *

    + * All COM object created by JACOB extend this class so that we can + * automatically release them when the thread is detached from COM - if we leave + * it to the finalizer it will call the release from another thread, which may + * result in a segmentation violation. + */ +public class JacobObject { + + /** + * Standard constructor that adds this JacobObject to the memory management + * pool. + */ + public JacobObject() { + ROT.addObject(this); + } + + /** + * Finalizers call this method. This method should release any COM data + * structures in a way that it can be called multiple times. This can happen + * if someone manually calls this and then a finalizer calls it. + */ + public void safeRelease() { + // currently does nothing - subclasses may do something + if (isDebugEnabled()) { + // this used to do a toString() but that is bad for SafeArray + debug("SafeRelease: " + this.getClass().getName()); + } + } + + /** + * When things go wrong, it is useful to be able to debug the ROT. + */ + private static final boolean DEBUG = + // true; + "true".equalsIgnoreCase(System.getProperty("com.jacob.debug")); + + protected static boolean isDebugEnabled() { + return DEBUG; + } + + /** + * Loads JacobVersion.Properties and returns the value of version in it + * + * @deprecated use JacobReleaseInfo.getBuildDate() instead. + * @return String value of version in JacobVersion.Properties or "" if none + */ + @Deprecated + public static String getBuildDate() { + return JacobReleaseInfo.getBuildDate(); + } + + /** + * Loads JacobVersion.Properties and returns the value of version in it + * + * @deprecated use JacobReleaseInfo.getBuildVersion() instead. + * @return String value of version in JacobVersion.Properties or "" if none + */ + @Deprecated + public static String getBuildVersion() { + return JacobReleaseInfo.getBuildVersion(); + } + + /** + * Very basic debugging function. + * + * @param istrMessage + */ + protected static void debug(String istrMessage) { + if (isDebugEnabled()) { + System.out.println(Thread.currentThread().getName() + ": " + + istrMessage); + } + } + + /** + * force the jacob DLL to be loaded whenever this class is referenced + */ + static { + LibraryLoader.loadJacobLibrary(); + } + +} \ No newline at end of file diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/JacobReleaseInfo.java b/vendor/jacob/1.15-M4/java/com/jacob/com/JacobReleaseInfo.java new file mode 100644 index 0000000..a41b239 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/JacobReleaseInfo.java @@ -0,0 +1,96 @@ +package com.jacob.com; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * An interface to the version properties file. This code was removed from + * JacobObject because it doesn't belong there. + * + */ +public class JacobReleaseInfo { + + /** + * holds the build version as retrieved from the version properties file + * that exists in the JAR. This can be retrieved by calling the static + * method getBuildVersion() + * + * @see #getBuildVersion() + */ + private static String buildVersion = ""; + /** + * holds the build date as retrieved from the version properties file that + * exists in the JAR This can be retrieved by calling the static method + * getBuildDate() + * + * @see #getBuildDate() + */ + private static String buildDate = ""; + /** the name of the jacob version properties file */ + private static final String PROPERTY_FILE_NAME = "META-INF/JacobVersion.properties"; + + /** + * Loads version information from PROPERTY_FILE_NAME that was built as part + * of this release. + * + * @throws IllegalStateException + * when it can't find the version properties file + */ + private static void loadVersionProperties() { + Properties versionProps = new Properties(); + // can't use system class loader cause won't work in JavaWebStart + InputStream stream = JacobReleaseInfo.class.getClassLoader() + .getResourceAsStream(PROPERTY_FILE_NAME); + // This should never happen. This is an attempt to make something work + // for WebSphere. They may be using some kind of Servlet loader that + // needs an absolute path based search + if (stream == null) { + stream = JacobReleaseInfo.class.getClassLoader() + .getResourceAsStream("/" + PROPERTY_FILE_NAME); + } + // A report came in that WebSphere had trouble finding the file + // so lets trap it. Plus, it's a good idea anyway. + if (stream == null) { + throw new IllegalStateException( + "Can't find " + + PROPERTY_FILE_NAME + + " using JacobReleaseInfo.class.getClassLoader().getResourceAsStream()"); + } else { + try { + versionProps.load(stream); + stream.close(); + buildVersion = (String) versionProps.get("version"); + buildDate = (String) versionProps.get("build.date"); + } catch (IOException ioe) { + ioe.printStackTrace(); + System.err.println("Warning! Couldn't load props " + ioe); + } + } + } + + /** + * loads PROPERT_FILE_NAME and returns the value of version in it + * + * @return String value of version in PROPERT_FILE_NAME or "" if none + */ + public static String getBuildDate() { + if (buildDate.equals("")) { + loadVersionProperties(); + } + return buildDate; + } + + /** + * loads PROPERT_FILE_NAME and returns the value of version in it + * + * @return String value of version in PROPERT_FILE_NAME or "" if none + */ + public static String getBuildVersion() { + if (buildVersion.equals("")) { + loadVersionProperties(); + } + return buildVersion; + } + +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/LibraryLoader.java b/vendor/jacob/1.15-M4/java/com/jacob/com/LibraryLoader.java new file mode 100644 index 0000000..4fd2740 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/LibraryLoader.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 1999-2007 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.Set; + +/** + * Utility class to centralize the way in which the jacob JNI library is loaded. + *

    + * + * This supports defining the path or library name using system properties or a + * custom resource file. If desired, jacob can auto-detect the correct version + * of the DLL for 32 or 64 bit windows, as long as you have named them + * differently. + * + *

      + *
    1. If system property {@link #JACOB_DLL_PATH} is defined, the file located + * there will be loaded as the jacob dll using System.load().
    2. + * + *
    3. If system property {@link #JACOB_DLL_NAME} is defined, the file located + * there will be loaded as the jacob dll.
    4. + *
    5. If system property {@link #JACOB_DLL_NAME_X86} and + * {@link #JACOB_DLL_NAME_X64} are defined, the file located there will be + * loaded as the jacob dll, depending on the version of Windows.
    6. + * + *
    7. If {@link #JACOB_DLL_NAME} is defined in the + * {@code com.jacob.com.JacobLibraryLoader} resource file, the specified dll + * will be loaded from the {@code java.library.path}.
    8. + *
    9. If {@link #JACOB_DLL_NAME_X86} and {@link #JACOB_DLL_NAME_X64} are + * defined in the {@code com.jacob.com.JacobLibraryLoader} resource file, the + * specified dll will be loaded from the {@code java.library.path}, depending + * on the version of Windows.
    10. + * + *
    11. If none of the above are true, the default is to load the library named + * "jacob-<version>-<arch>" (or + * "jacob-<version>-<arch&rt;.dll") from the {@code java.library.path}. + *
    12. + *
    + * + * The standard behavior for most applications is that {@code LoadLibrary()} + * will be called to load the dll. {@code LoadLibary()} searches directories + * specified in the variable {@code java.library.path}. This is why most test + * cases specify -Djava.library.path in their command line arguments. + *

    + * JACOB_DLL_PATH submitted sourceforge ticket 1493647 Added 1.11
    + * JACOB_DLL_NAME, JACOB_DLL_NAME_32, JACOB_DLL_NAME_64 submitted sourceforge + * ticket 1845039 Added 1.14M7 + * + * @author Scott Dickerson (sjd78) + * @author Jason Smith + */ +public final class LibraryLoader { + /** + * Name of system property (currently jacob.dll.path) that may + * contain an absolute path to the JNI library. + */ + public static final String JACOB_DLL_PATH = "jacob.dll.path"; + + /** + * Name of system property (currently jacob.dll.name) that may + * contain an alternate name for the JNI library (default is 'jacob'). + */ + public static final String JACOB_DLL_NAME = "jacob.dll.name"; + + /** + * Name of system property (currently jacob.dll.name) that may + * contain an alternate name for the JNI library (default is 'jacob'), 32 + * bit windows. + */ + public static final String JACOB_DLL_NAME_X86 = "jacob.dll.name.x86"; + + /** + * Name of system property (currently jacob.dll.name) that may + * contain an alternate name for the JNI library (default is 'jacob'), 64 + * bit windows. + */ + public static final String JACOB_DLL_NAME_X64 = "jacob.dll.name.x64"; + + /** + * Appended to "jacob" when building DLL name This string must EXACTLY match + * the string in the build.xml file + */ + public static final String DLL_NAME_MODIFIER_32_BIT = "x86"; + /** + * Appended to "jacob" when building DLL name This string must EXACTLY match + * the string in the build.xml file + */ + public static final String DLL_NAME_MODIFIER_64_BIT = "x64"; + + /** + * Load the jacob dll either from an absolute path or by a library name, + * both of which may be defined in various ways. + * + * @throws UnsatisfiedLinkError + * if the library does not exist. + */ + public static void loadJacobLibrary() { + // In some cases, a library that uses Jacob won't be able to set system + // properties + // prior to Jacob being loaded. The resource bundle provides an + // alternate way to + // override DLL name or path that will be loaded with Jacob regardless + // of other + // initialization order. + ResourceBundle resources = null; + Set keys = new HashSet(); + try { + resources = ResourceBundle.getBundle(LibraryLoader.class.getName(), + Locale.getDefault(), LibraryLoader.class.getClassLoader()); + for (Enumeration i = resources.getKeys(); i + .hasMoreElements();) { + String key = i.nextElement(); + keys.add(key); + } + } catch (MissingResourceException e) { + // Do nothing. Expected. + } + + // First, check for a defined PATH. System property overrides resource + // bundle. + String path = System.getProperty(JACOB_DLL_PATH); + if (path == null && resources != null && keys.contains(JACOB_DLL_PATH)) { + path = (String) resources.getObject(JACOB_DLL_PATH); + } + + if (path != null) { + JacobObject.debug("Loading library " + path + + " using System.loadLibrary "); + System.load(path); + } else { + // Path was not defined, so use the OS mechanism for loading + // libraries. + // Check for a defined NAME. System property overrides resource + // bundle. + String name = null; + + if (System.getProperty(JACOB_DLL_NAME) != null) { + name = System.getProperty(JACOB_DLL_NAME); + } else if (System.getProperty(JACOB_DLL_NAME_X86) != null + && shouldLoad32Bit()) { + name = System.getProperty(JACOB_DLL_NAME_X86); + } else if (System.getProperty(JACOB_DLL_NAME_X64) != null + && !shouldLoad32Bit()) { + name = System.getProperty(JACOB_DLL_NAME_X64); + } else if (resources != null && keys.contains(JACOB_DLL_NAME)) { + name = resources.getString(JACOB_DLL_NAME); + } else if (resources != null && keys.contains(JACOB_DLL_NAME_X86) + && shouldLoad32Bit()) { + name = resources.getString(JACOB_DLL_NAME_X86); + } else if (resources != null && keys.contains(JACOB_DLL_NAME_X64) + && !shouldLoad32Bit()) { + name = resources.getString(JACOB_DLL_NAME_X64); + } else { + // No alternate NAME or PATH was defined, so use the default. + // We will almost always end up here. + name = getPreferredDLLName(); + } + + JacobObject.debug("Loading library " + name + + " using System.loadLibrary "); + // System.out.println("Loading " + name); + System.loadLibrary(name); + } + } + + /** + * Developer note: This method MUST be synchronized with the DLL names + * created as part of the build process in build.xml + *

    + * The DLL name is "jacob\.release" + * + * @return the preferred name of the DLL adjusted for this platform and + * version without the ".dll" extension + */ + public static String getPreferredDLLName() { + if (shouldLoad32Bit()) { + return "jacob" + "-" + JacobReleaseInfo.getBuildVersion() + "-" + + DLL_NAME_MODIFIER_32_BIT; + } else { + return "jacob" + "-" + JacobReleaseInfo.getBuildVersion() + "-" + + DLL_NAME_MODIFIER_64_BIT; + } + } + + /** + * Detects whether this is a 32-bit JVM. + * + * @return {@code true} if this is a 32-bit JVM. + */ + protected static boolean shouldLoad32Bit() { + // This guesses whether we are running 32 or 64 bit Java. + // This works for Sun and IBM JVMs version 5.0 or later. + // May need to be adjusted for non-Sun JVMs. + + String bits = System.getProperty("sun.arch.data.model", "?"); + if (bits.equals("32")) + return true; + else if (bits.equals("64")) + return false; + + // this works for jRocket + String arch = System.getProperty("java.vm.name", "?"); + if (arch.toLowerCase().indexOf("64-bit") >= 0) + return false; + + return true; + } +} // LibraryLoader diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/MainSTA.java b/vendor/jacob/1.15-M4/java/com/jacob/com/MainSTA.java new file mode 100644 index 0000000..a87e3c4 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/MainSTA.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * We provide our own main sta thread to avoid COM tagging a random thread as + * the main STA - this is the thread in which all Apartment threaded components + * will be created if the client chooses an MTA threading model for the java + * side of the app. + */ +public class MainSTA extends STA { +} \ No newline at end of file diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/NotImplementedException.java b/vendor/jacob/1.15-M4/java/com/jacob/com/NotImplementedException.java new file mode 100644 index 0000000..c5773b5 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/NotImplementedException.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * Thrown by java APIs that are not implemented either because they were never + * implemented or because they are being deprecated This is a subclass of + * ComException so callers can still just catch ComException. + */ +public class NotImplementedException extends JacobException { + + /** + * + */ + private static final long serialVersionUID = -9169900832852356445L; + + /** + * @param description + */ + public NotImplementedException(String description) { + super(description); + } + +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/ROT.java b/vendor/jacob/1.15-M4/java/com/jacob/com/ROT.java new file mode 100644 index 0000000..7b50fd3 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/ROT.java @@ -0,0 +1,279 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.WeakHashMap; + +/** + * The Running Object Table (ROT) maps each thread to a collection of all the + * JacobObjects that were created in that thread. It always operates on the + * current thread so all the methods are static and they implicitly get the + * current thread. + *

    + * The clearObjects method is used to release all the COM objects created by + * Jacob in the current thread prior to uninitializing COM for that thread. + *

    + * Prior to 1.9, manual garbage collection was the only option in Jacob, but + * from 1.9 onward, setting the com.jacob.autogc system property allows the + * objects referenced by the ROT to be automatically GCed. Automatic GC may be + * preferable in systems with heavy event callbacks. + *

    + * Is [ 1116101 ] jacob-msg 0284 relevant??? + */ +public abstract class ROT { + /** + * Manual garbage collection was the only option pre 1.9 Can staticly cache + * the results because only one value and we don't let it change during a + * run + */ + protected static final boolean USE_AUTOMATIC_GARBAGE_COLLECTION = "true" + .equalsIgnoreCase(System.getProperty("com.jacob.autogc")); + + /** + * If the code is ran from an applet that is called from javascript the Java + * Plugin does not give full permissions to the code and thus System + * properties cannot be accessed. They can be accessed at class + * initialization time. + * + * The default behavior is to include all classes in the ROT, setting a + * boolean here to indicate this prevents a call to System.getProperty as + * part of the general call flow. + */ + protected static final Boolean INCLUDE_ALL_CLASSES_IN_ROT = Boolean + .valueOf(System.getProperty("com.jacob.includeAllClassesInROT", + "true")); + + /** + * Suffix added to class name to make up property name that determines if + * this object should be stored in the ROT. This 1.13 "feature" makes it + * possible to cause VariantViaEvent objects to not be added to the ROT in + * event callbacks. + *

    + * We don't have a static for the actual property because there is a + * different property for each class that may make use of this feature. + */ + protected static String PUT_IN_ROT_SUFFIX = ".PutInROT"; + + /** + * A hash table where each element is another HashMap that represents a + * thread. Each thread HashMap contains the com objects created in that + * thread + */ + private static HashMap> rot = new HashMap>(); + + /** + * adds a new thread storage area to rot + * + * @return Map corresponding to the thread that this call was made in + */ + protected synchronized static Map addThread() { + // should use the id here instead of the name because the name can be + // changed + String t_name = Thread.currentThread().getName(); + if (rot.containsKey(t_name)) { + // nothing to do + } else { + Map tab = null; + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: Automatic GC flag == " + + USE_AUTOMATIC_GARBAGE_COLLECTION); + } + if (!USE_AUTOMATIC_GARBAGE_COLLECTION) { + tab = new HashMap(); + } else { + tab = new WeakHashMap(); + } + rot.put(t_name, tab); + } + return getThreadObjects(false); + } + + /** + * Returns the pool for this thread if it exists. can create a new one if + * you wish by passing in TRUE + * + * @param createIfDoesNotExist + * @return Map the collection that holds the objects created in the current + * thread + */ + protected synchronized static Map getThreadObjects( + boolean createIfDoesNotExist) { + String t_name = Thread.currentThread().getName(); + if (!rot.containsKey(t_name) && createIfDoesNotExist) { + addThread(); + } + return rot.get(t_name); + } + + /** + * Iterates across all of the entries in the Hashmap in the rot that + * corresponds to this thread. This calls safeRelease() on each entry and + * then clears the map when done and removes it from the rot. All traces of + * this thread's objects will disappear. This is called by COMThread in the + * tear down and provides a synchronous way of releasing memory + */ + protected static void clearObjects() { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: " + rot.keySet().size() + + " thread tables exist"); + } + + Map tab = getThreadObjects(false); + if (tab != null) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: " + tab.keySet().size() + + " objects to clear in this thread's ROT "); + } + // walk the values + Iterator it = tab.keySet().iterator(); + while (it.hasNext()) { + JacobObject o = it.next(); + if (o != null + // can't use this cause creates a Variant if calling SafeAray + // and we get an exception modifying the collection while + // iterating + // && o.toString() != null + ) { + if (JacobObject.isDebugEnabled()) { + if (o instanceof SafeArray) { + // SafeArray create more objects when calling + // toString() + // which causes a concurrent modification exception + // in HashMap + JacobObject.debug("ROT: removing " + + o.getClass().getName()); + } else { + // Variant toString() is probably always bad in here + JacobObject.debug("ROT: removing " + o.hashCode() + + "->" + o.getClass().getName()); + } + } + o.safeRelease(); + } + } + // empty the collection + tab.clear(); + // remove the collection from rot + ROT.removeThread(); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: thread table cleared and removed"); + } + } else { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: nothing to clear!"); + } + } + } + + /** + * Removes the map from the rot that is associated with the current thread. + */ + private synchronized static void removeThread() { + // should this see if it exists first? + rot.remove(Thread.currentThread().getName()); + } + + /** + * @deprecated the java model leave the responsibility of clearing up + * objects to the Garbage Collector. Our programming model + * should not require that the user specifically remove object + * from the thread.
    + * This will remove an object from the ROT
    + * This does not need to be synchronized because only the rot + * modification related methods need to synchronized. Each + * individual map is only modified in a single thread. + * @param o + */ + @Deprecated + protected static void removeObject(JacobObject o) { + Map tab = ROT.getThreadObjects(false); + if (tab != null) { + tab.remove(o); + } + o.safeRelease(); + } + + /** + * Adds an object to the HashMap for the current thread.
    + *

    + * This method does not need to be threaded because the only concurrent + * modification risk is on the hash map that contains all of the thread + * related hash maps. The individual thread related maps are only used on a + * per thread basis so there isn't a locking issue. + *

    + * In addition, this method cannot be threaded because it calls + * ComThread.InitMTA. The ComThread object has some methods that call ROT so + * we could end up deadlocked. This method should be safe without the + * synchronization because the ROT works on per thread basis and the methods + * that add threads and remove thread related entries are all synchronized + * + * + * @param o + */ + protected static void addObject(JacobObject o) { + String shouldIncludeClassInROT = "true"; + // only call System.getProperty if we are not including all classes in + // the ROT. This lets us run with standard Jacob behavior in Applets + // without the security exception raised by System.getProperty in the + // flow + if (!ROT.INCLUDE_ALL_CLASSES_IN_ROT) { + shouldIncludeClassInROT = System.getProperty(o.getClass().getName() + + PUT_IN_ROT_SUFFIX, "true"); + } + if (shouldIncludeClassInROT.equalsIgnoreCase("false")) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("JacobObject: New instance of " + + o.getClass().getName() + " not added to ROT"); + } + } else { + // first see if we have a table for this thread + Map tab = getThreadObjects(false); + if (tab == null) { + // this thread has not been initialized as a COM thread + // so make it part of MTA for backwards compatibility + ComThread.InitMTA(false); + // don't really need the "true" because the InitMTA will have + // called back to the ROT to create a table for this thread + tab = getThreadObjects(true); + } + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: adding " + o + "->" + + o.getClass().getName() + + " table size prior to addition:" + tab.size()); + } + // add the object to the table that is specific to this thread + if (tab != null) { + tab.put(o, null); + } + } + } + + /** + * ROT can't be a subclass of JacobObject because of the way ROT pools are + * managed so we force a DLL load here by referencing JacobObject + */ + static { + LibraryLoader.loadJacobLibrary(); + } + +} diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/STA.java b/vendor/jacob/1.15-M4/java/com/jacob/com/STA.java new file mode 100644 index 0000000..837e2d3 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/STA.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * A class that implements a Single Threaded Apartment. Users will subclass this + * and override OnInit() and OnQuit() where they will create and destroy a COM + * component that wants to run in an STA other than the main STA. + */ +public class STA extends Thread { + /** + * referenced by STA.cpp + */ + public int threadID; + + /** + * constructor for STA + */ + public STA() { + start(); // start the thread + } + + /* + * (non-Javadoc) + * + * @see java.lang.Thread#run() + */ + public void run() { + // init COM + ComThread.InitSTA(); + if (OnInit()) { + // this call blocks in the win32 message loop + // until quitMessagePump is called + doMessagePump(); + } + OnQuit(); + // uninit COM + ComThread.Release(); + } + + /** + * Override this method to create and initialize any COM component that you + * want to run in this thread. If anything fails, return false to terminate + * the thread. + * + * @return always returns true + */ + public boolean OnInit() { + return true; + } + + /** + * Override this method to destroy any resource before the thread exits and + * COM in uninitialized + */ + public void OnQuit() { + // there is nothing to see here + } + + /** + * calls quitMessagePump + */ + public void quit() { + quitMessagePump(); + } + + /** + * run a message pump for the main STA + */ + public native void doMessagePump(); + + /** + * quit message pump for the main STA + */ + public native void quitMessagePump(); + + /** + * STA isn't a subclass of JacobObject so a reference to it doesn't load the + * DLL without this + */ + static { + LibraryLoader.loadJacobLibrary(); + } +} \ No newline at end of file diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/SafeArray.java b/vendor/jacob/1.15-M4/java/com/jacob/com/SafeArray.java new file mode 100644 index 0000000..f250d81 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/SafeArray.java @@ -0,0 +1,1172 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * This creates an array wrapper around Variant objects(?). This supports 1, 2 + * and n-dimensional arrays. It exists in this form because n-dimensional arrays + * were a later addition. + */ +public class SafeArray extends JacobObject { + /** The super secret int that is actually the pointer to windows memory */ + int m_pV = 0; + + /** + * Constructor. Why does this exist? Yeah, someone will post on sourceforge + * about this comment. + * + */ + public SafeArray() { + } + + /** + * Constructor. + * + * @param vt + * type of array + */ + public SafeArray(int vt) { + init(vt, new int[] { 0 }, new int[] { -1 }); + } + + /** + * Constructor for a single dimensional array whose lower bounds is 0 and + * whose upper bound is specified as a parameter + * + * @param vt + * type of the array + * @param celems + * length of the array + */ + public SafeArray(int vt, int celems) { + init(vt, new int[] { 0 }, new int[] { celems }); + } + + /** + * Creates a two dimensional SafeArray whose base indexes are 0. + * + * @param vt + * Type of the array + * @param celems1 + * length of the array in first dimension + * @param celems2 + * length of the array in second dimension + */ + public SafeArray(int vt, int celems1, int celems2) { + init(vt, new int[] { 0, 0 }, new int[] { celems1, celems2 }); + } + + /** + * Constructor with support for N-dimensional array support + *

    + * You create an N-D SafeArray by: SafeArray sa = new + * SafeArray(Variant.VariantVariant, new int[] {0,0,0,0}, new int[] + * {4,4,4,4}); Where the 1st array is lower bounds and 2nd has the lengths + * of each dimension * + * + * @param vt + * @param lbounds + * @param celems + */ + public SafeArray(int vt, int lbounds[], int celems[]) { + init(vt, lbounds, celems); + } + + /** + * convert a string to a VT_UI1 array + * + * @param s + * source string + */ + public SafeArray(String s) { + char[] ca = s.toCharArray(); + init(Variant.VariantByte, new int[] { 0 }, new int[] { ca.length }); + fromCharArray(ca); + } + + /** + * convert a VT_UI1 array to string + * + * @return variant byte as a string + */ + public String asString() { + if (getvt() != Variant.VariantByte) { + return null; + } + char ja[] = toCharArray(); + return new String(ja); + } + + public native Object clone(); + + /** + * now private so only this object can access. Was: call this to explicitly + * release the com object before gc + * + */ + private native void destroy(); + + /** + * {@inheritDoc} + */ + protected void finalize() { + safeRelease(); + } + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromBooleanArray(boolean ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromByteArray(byte ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromCharArray(char ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromDoubleArray(double ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromFloatArray(float ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromIntArray(int ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromLongArray(long ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromShortArray(short ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromStringArray(String ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromVariantArray(Variant ja[]); + + /** + * boolean access + * + * @param sa_idx + * @return boolean representation + */ + public native boolean getBoolean(int sa_idx); + + /** + * get boolean value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native boolean getBoolean(int indices[]); + + /** + * boolean access + * + * @param sa_idx1 + * @param sa_idx2 + * @return boolean representation + */ + public native boolean getBoolean(int sa_idx1, int sa_idx2); + + /** + * boolean access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getBooleans(int sa_idx, int nelems, boolean ja[], + int ja_start); + + /** + * byte access + * + * @param sa_idx + * @return byte representaton + */ + public native byte getByte(int sa_idx); + + /** + * get byte value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native byte getByte(int indices[]); + + /** + * byte access + * + * @param sa_idx1 + * @param sa_idx2 + * @return byte representation + */ + public native byte getByte(int sa_idx1, int sa_idx2); + + /** + * Fills byte array from contents of this array + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getBytes(int sa_idx, int nelems, byte ja[], int ja_start); + + /** + * char access + * + * @param sa_idx + * @return single character rpeesentation + */ + public native char getChar(int sa_idx); + + /** + * get char value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native char getChar(int indices[]); + + /** + * char access + * + * @param sa_idx1 + * @param sa_idx2 + * @return single character representation + */ + public native char getChar(int sa_idx1, int sa_idx2); + + /** + * char access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getChars(int sa_idx, int nelems, char ja[], int ja_start); + + /** + * double access + * + * @param sa_idx + * @return double stored in array + */ + public native double getDouble(int sa_idx); + + /** + * get double value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native double getDouble(int indices[]); + + /** + * double access + * + * @param sa_idx1 + * @param sa_idx2 + * @return double stored in array + */ + public native double getDouble(int sa_idx1, int sa_idx2); + + /** + * double access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getDoubles(int sa_idx, int nelems, double ja[], + int ja_start); + + /** + * @return the size of each element? + */ + public native int getElemSize(); + + /** + * @return The ??features of the array? + */ + public native int getFeatures(); + + /** + * float access + * + * @param sa_idx + * @return float held in array at location + */ + public native float getFloat(int sa_idx); + + /** + * get float value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native float getFloat(int indices[]); + + /** + * float access + * + * @param sa_idx1 + * @param sa_idx2 + * @return float held in array at location + */ + public native float getFloat(int sa_idx1, int sa_idx2); + + /** + * float access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getFloats(int sa_idx, int nelems, float ja[], + int ja_start); + + /** + * get int from an single dimensional array + * + * @param sa_idx + * array index + * @return int stored in array + */ + public native int getInt(int sa_idx); + + /** + * get int value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native int getInt(int indices[]); + + /** + * get int from 2 dimensional array + * + * @param sa_idx1 + * array index first dimension + * @param sa_idx2 + * array index of second dimension + * @return int stored in array + */ + public native int getInt(int sa_idx1, int sa_idx2); + + /** + * retrieves a group of ints from a single dimensional array + * + * @param sa_idx + * the index in the array to start the get + * @param nelems + * number of elements to retrieve + * @param ja + * the structure to be filled with the ints + * @param ja_start + * the start point in the java int array to start filling + */ + public native void getInts(int sa_idx, int nelems, int ja[], int ja_start); + + /** + * get int from an single dimensional array + * + * @param sa_idx + * array index + * @return long stored in array + */ + public native long getLong(int sa_idx); + + /** + * get long value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native long getLong(int indices[]); + + /** + * get long from 2 dimensional array + * + * @param sa_idx1 + * array index first dimension + * @param sa_idx2 + * array index of second dimension + * @return long stored in array + */ + public native long getLong(int sa_idx1, int sa_idx2); + + /** + * retrieves a group of longs from a single dimensional array + * + * @param sa_idx + * the index in the array to start the get + * @param nelems + * number of elements to retrieve + * @param ja + * the structure to be filled with the longs + * @param ja_start + * the start point in the java longs array to start filling + */ + public native void getLongs(int sa_idx, int nelems, long ja[], int ja_start); + + /** + * @return The lower bounds of the array? + */ + public native int getLBound(); + + /** + * @param dim + * the dimension we are checking in a multidimensional array + * @return The lower bounds of the array? + */ + public native int getLBound(int dim); + + /** + * @return The number of dimensions in this array + */ + public native int getNumDim(); + + /** + * not implemented. + * + * @return 0 + */ + public int getNumLocks() { + return 0; + } + + /** + * short access + * + * @param sa_idx + * @return short stored in array + */ + public native short getShort(int sa_idx); + + /** + * get short value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native short getShort(int indices[]); + + /** + * short access + * + * @param sa_idx1 + * @param sa_idx2 + * @return short stored in array + */ + public native short getShort(int sa_idx1, int sa_idx2); + + /** + * short access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getShorts(int sa_idx, int nelems, short ja[], + int ja_start); + + /** + * string access + * + * @param sa_idx + * @return String stored in array + * + */ + public native String getString(int sa_idx); + + /** + * get String value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native String getString(int indices[]); + + /** + * string access + * + * @param sa_idx1 + * @param sa_idx2 + * @return String stored in array + */ + public native String getString(int sa_idx1, int sa_idx2); + + /** + * string access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getStrings(int sa_idx, int nelems, String ja[], + int ja_start); + + /** + * @return The upper bounds of the array? + */ + public native int getUBound(); + + /** + * @param dim + * the dimension we are checking in a multidimensional array + * @return The upper bounds of the array? + */ + public native int getUBound(int dim); + + /** + * variant access + * + * @param sa_idx + * @return Variant held in location in the array? + */ + public native Variant getVariant(int sa_idx); + + /** + * get Variant value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native Variant getVariant(int indices[]); + + /** + * variant access + * + * @param sa_idx1 + * @param sa_idx2 + * @return Variant held in a location in the array? + */ + public native Variant getVariant(int sa_idx1, int sa_idx2); + + /** + * variant access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getVariants(int sa_idx, int nelems, Variant ja[], + int ja_start); + + /** + * @return the Variant type + */ + public native int getvt(); + + protected native void init(int vt, int lbounds[], int celems[]); + + /** + * Does anyone want to document this? + * + * @param sa + */ + public native void reinit(SafeArray sa); + + /** + * Does anyone want to document this? + * + * @param vt + * the variant type? + */ + public native void reinterpretType(int vt); + + /** + * {@inheritDoc} + */ + public void safeRelease() { + super.safeRelease(); + if (m_pV != 0) { + destroy(); + m_pV = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } + + /** + * boolean access + * + * @param sa_idx + * @param c + */ + public native void setBoolean(int sa_idx, boolean c); + + /** + * set boolean value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setBoolean(int indices[], boolean c); + + /** + * boolean access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setBoolean(int sa_idx1, int sa_idx2, boolean c); + + /** + * boolean access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setBooleans(int sa_idx, int nelems, boolean ja[], + int ja_start); + + /** + * byte access + * + * @param sa_idx + * @param c + */ + public native void setByte(int sa_idx, byte c); + + /** + * set byte value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setByte(int indices[], byte c); + + /** + * byte access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setByte(int sa_idx1, int sa_idx2, byte c); + + /** + * fills array with passed in bytes + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setBytes(int sa_idx, int nelems, byte ja[], int ja_start); + + /** + * char access + * + * @param sa_idx + * @param c + */ + public native void setChar(int sa_idx, char c); + + /** + * set char value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setChar(int indices[], char c); + + /** + * char access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setChar(int sa_idx1, int sa_idx2, char c); + + /** + * char access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setChars(int sa_idx, int nelems, char ja[], int ja_start); + + /** + * double access + * + * @param sa_idx + * @param c + */ + public native void setDouble(int sa_idx, double c); + + /** + * set double value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setDouble(int indices[], double c); + + /** + * double access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setDouble(int sa_idx1, int sa_idx2, double c); + + /** + * double access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setDoubles(int sa_idx, int nelems, double ja[], + int ja_start); + + /** + * float access + * + * @param sa_idx + * @param c + */ + public native void setFloat(int sa_idx, float c); + + /** + * set float value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setFloat(int indices[], float c); + + /** + * float access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setFloat(int sa_idx1, int sa_idx2, float c); + + /** + * float access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setFloats(int sa_idx, int nelems, float ja[], + int ja_start); + + /** + * sets the int value of an element in a single dimensional array + * + * @param sa_idx + * index into the array + * @param c + * the value to be set + */ + public native void setInt(int sa_idx, int c); + + /** + * set int value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setInt(int indices[], int c); + + /** + * sets the int value of a 2 dimensional array + * + * @param sa_idx1 + * index on the first dimension + * @param sa_idx2 + * index on the second dimension + * @param c + * the value to be set + */ + public native void setInt(int sa_idx1, int sa_idx2, int c); + + /** + * sets a group of ints into a single dimensional array + * + * @param sa_idx + * the index of the start of the array to put into + * @param nelems + * number of elements to be copied + * @param ja + * the new int values to be put into the array + * @param ja_start + * the start index in the array that we are copying into + * SafeArray + */ + public native void setInts(int sa_idx, int nelems, int ja[], int ja_start); + + /** + * sets the long value of an element in a single dimensional array + * + * @param sa_idx + * index into the array + * @param c + * the value to be set + */ + public native void setLong(int sa_idx, long c); + + /** + * set long value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setLong(int indices[], long c); + + /** + * sets the long value of a 2 dimensional array + * + * @param sa_idx1 + * index on the first dimension + * @param sa_idx2 + * index on the second dimension + * @param c + * the value to be set + */ + public native void setLong(int sa_idx1, int sa_idx2, long c); + + /** + * sets a group of longs into a single dimensional array + * + * @param sa_idx + * the index of the start of the array to put into + * @param nelems + * number of elements to be copied + * @param ja + * the new long values to be put into the array + * @param ja_start + * the start index in the array that we are copying into + * SafeArray + */ + public native void setLongs(int sa_idx, int nelems, long ja[], int ja_start); + + /** + * short access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setShort(int sa_idx1, int sa_idx2, short c); + + /** + * short access + * + * @param sa_idx + * @param c + */ + public native void setShort(int sa_idx, short c); + + /** + * set short value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setShort(int indices[], short c); + + /** + * short access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setShorts(int sa_idx, int nelems, short ja[], + int ja_start); + + /** + * puts a string into an element in a two dimensional array. + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setString(int sa_idx1, int sa_idx2, String c); + + /* + * ================================================================ The + * beginning of N-dimensional array support + * ================================================================ + */ + + /** + * puts a string into an element in a single dimensional safe array + * + * @param sa_idx + * @param c + */ + public native void setString(int sa_idx, String c); + + /** + * set Stringvalue in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setString(int indices[], String c); + + /** + * string access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setStrings(int sa_idx, int nelems, String ja[], + int ja_start); + + /** + * variant access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setVariant(int sa_idx1, int sa_idx2, Variant c); + + /** + * variant access + * + * @param sa_idx + * @param c + */ + public native void setVariant(int sa_idx, Variant c); + + /** + * set Variant value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param v + */ + public native void setVariant(int indices[], Variant v); + + /** + * variant access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setVariants(int sa_idx, int nelems, Variant ja[], + int ja_start); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return boolean[] array of booleans contained in this collection + */ + public native boolean[] toBooleanArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return byte[] byte array contained in this collection + */ + public native byte[] toByteArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return char[] character array contained in this collection + */ + public native char[] toCharArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return double[] double array contained in this collection + */ + public native double[] toDoubleArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return float[] array of float contained in this collection + */ + public native float[] toFloatArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return int[] int array contained in this collection + */ + public native int[] toIntArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return long[] long array contained in this collection + */ + public native long[] toLongArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return short[] short array contained in this collection + */ + public native short[] toShortArray(); + + /** + * Standard toString() Warning, this creates new Variant objects! + * + * @return String contents of variant + */ + public String toString() { + String s = ""; + int ndim = getNumDim(); + if (ndim == 1) { + int ldim = getLBound(); + int udim = getUBound(); + for (int i = ldim; i <= udim; i++) { + Variant v = getVariant(i); + + if (((v.getvt() & Variant.VariantTypeMask) | Variant.VariantArray) == v + .getvt()) { + return s + "[" + v.toSafeArray().toString() + "]"; + } else { + s += " " + v.toString(); + } + } + } else if (ndim == 2) { + int ldim1 = getLBound(1); + int udim1 = getUBound(1); + + int ldim2 = getLBound(2); + int udim2 = getUBound(2); + + for (int i = ldim1; i <= udim1; i++) { + for (int j = ldim2; j <= udim2; j++) { + Variant v = getVariant(i, j); + s += " " + v.toString(); + } + s += "\n"; + } + } + return s; + } + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return String[] String array contained in this collection + */ + public native String[] toStringArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return Variant[] array of variants contained in this collection + */ + public native Variant[] toVariantArray(); + +} \ No newline at end of file diff --git a/vendor/jacob/1.15-M4/java/com/jacob/com/Variant.java b/vendor/jacob/1.15-M4/java/com/jacob/com/Variant.java new file mode 100644 index 0000000..91ae210 --- /dev/null +++ b/vendor/jacob/1.15-M4/java/com/jacob/com/Variant.java @@ -0,0 +1,2235 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Date; + +/** + * The multi-format data type used for all call backs and most communications + * between Java and COM. It provides a single class that can handle all data + * types. + *

    + * Just loading this class creates 3 variants that get added to the ROT + *

    + * PROPVARIANT introduces new types so eventually Variant will need to be + * upgraded to support PropVariant types. + * http://blogs.msdn.com/benkaras/archive/2006/09/13/749962.aspx + *

    + * This object no longer implements Serializable because serialization is broken + * (and has been since 2000/xp). The underlying marshalling/unmarshalling code + * is broken in the JNI layer. + */ +public class Variant extends JacobObject { + + /** + * Use this constant for optional parameters + */ + public final static com.jacob.com.Variant DEFAULT; + + /** + * Same than {@link #DEFAULT} + */ + public final static com.jacob.com.Variant VT_MISSING; + + /** + * Use for true/false variant parameters + */ + public final static com.jacob.com.Variant VT_TRUE = new com.jacob.com.Variant( + true); + + /** + * Use for true/false variant parameters + */ + public final static com.jacob.com.Variant VT_FALSE = new com.jacob.com.Variant( + false); + + /** variant's type is empty : equivalent to VB Nothing and VT_EMPTY */ + public static final short VariantEmpty = 0; + + /** variant's type is null : equivalent to VB Null and VT_NULL */ + public static final short VariantNull = 1; + + /** variant's type is short VT_I2 */ + public static final short VariantShort = 2; + + /** variant's type is int VT_I4, a Long in VC */ + public static final short VariantInt = 3; + + /** variant's type is float VT_R4 */ + public static final short VariantFloat = 4; + + /** variant's type is double VT_R8 */ + public static final short VariantDouble = 5; + + /** variant's type is currency VT_CY */ + public static final short VariantCurrency = 6; + + /** variant's type is date VT_DATE */ + public static final short VariantDate = 7; + + /** variant's type is string also known as VT_BSTR */ + public static final short VariantString = 8; + + /** variant's type is dispatch VT_DISPATCH */ + public static final short VariantDispatch = 9; + + /** variant's type is error VT_ERROR */ + public static final short VariantError = 10; + + /** variant's type is boolean VT_BOOL */ + public static final short VariantBoolean = 11; + + /** variant's type is variant it encapsulate another variant VT_VARIANT */ + public static final short VariantVariant = 12; + + /** variant's type is object VT_UNKNOWN */ + public static final short VariantObject = 13; + + /** variant's type is object VT_DECIMAL */ + public static final short VariantDecimal = 14; + + // VT_I1 = 16 + + /** variant's type is byte VT_UI1 */ + public static final short VariantByte = 17; + + // VT_UI2 = 18 + // VT_UI4 = 19 + + /** + * variant's type is 64 bit long integer VT_I8 - not yet implemented in + * Jacob because we have to decide what to do with Currency and because its + * only supported on XP and later. No win2k, NT or 2003 server. + */ + public static final short VariantLongInt = 20; + + // VT_UI8 = 21 + // VT_INT = 22 + // VT_UNIT = 23 + // VT_VOID = 24 + // VT_HRESULT = 25 + + /** + * This value is for reference only and is not to be used by any callers + */ + public static final short VariantPointer = 26; + + // VT_SAFEARRAY = 27 + // VT_CARRARY = 28 + // VT_USERDEFINED = 29 + + /** what is this? VT_TYPEMASK && VT_BSTR_BLOB 0xfff */ + public static final short VariantTypeMask = 4095; + + /** variant's type is array VT_ARRAY 0x2000 */ + public static final short VariantArray = 8192; + + /** variant's type is a reference (to IDispatch?) VT_BYREF 0x4000 */ + public static final short VariantByref = 16384; + + /* + * Do the run time definition of DEFAULT and MISSING. Have to use static + * block because of the way the initialization is done via two calls instead + * of just a constructor for this type. + */ + static { + com.jacob.com.Variant vtMissing = new com.jacob.com.Variant(); + vtMissing.putVariantNoParam(); + DEFAULT = vtMissing; + VT_MISSING = vtMissing; + } + + /** + * Pointer to MS struct. + */ + int m_pVariant = 0; + + /** + * public constructor, initializes and sets type to VariantEmpty + */ + public Variant() { + this(null, false); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(boolean in) { + this(new Boolean(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(byte in) { + this(new Byte(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(double in) { + this(new Double(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(float in) { + this(new Float(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(int in) { + this(new Integer(in)); + }; + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(long in) { + this(new Long(in)); + } + + /** + * Convenience constructor that calls the main one with a byRef value of + * false + * + * @param in + * object to be made into variant + */ + public Variant(Object in) { + this(in, false); + } + + /** + * Constructor that accepts the data object and information about whether + * this is by reference or not. It calls the JavaVariantConverter to + * actually push the data into the newly created Variant. + * + * @param pValueObject + * The value object that will pushed down into windows memory. A + * null object sets this to "empty" + * @param fByRef + */ + public Variant(Object pValueObject, boolean fByRef) { + init(); + VariantUtilities.populateVariant(this, pValueObject, fByRef); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(short in) { + this(new Short(in)); + } + + /** + * Cover for native method so we can cover it. + *

    + * This cannot convert an object to a byRef. It can convert from byref to + * not byref + * + * @param in + * type to convert this variant too + * @return Variant returns this same object so folks can change when + * replacing calls toXXX() with changeType().getXXX() + */ + public Variant changeType(short in) { + changeVariantType(in); + return this; + } + + /** + * Converts variant to the passed in type by converting the underlying + * windows variant structure. private so folks use public java method + * + * @param in + * the desired resulting type + */ + private native void changeVariantType(short in); + + /** + * this returns null + * + * @return ?? comment says null? + */ + @Override + public native Object clone(); + + /** + * @deprecated No longer used + * @return null ! + */ + @Deprecated + public native Variant cloneIndirect(); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + @Override + protected void finalize() { + safeRelease(); + } + + /** + * + * @return returns the value as a boolean, throws an exception if its not. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public boolean getBoolean() { + if (this.getvt() == VariantBoolean) { + return getVariantBoolean(); + } else { + throw new IllegalStateException( + "getBoolean() only legal on Variants of type VariantBoolean, not " + + this.getvt()); + } + } + + /** + * public cover for native method + * + * @return the boolean from a booleanRef + * @throws IllegalStateException + * if variant is not of the requested type + */ + public boolean getBooleanRef() { + if ((this.getvt() & VariantTypeMask) == VariantBoolean + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantBooleanRef(); + } else { + throw new IllegalStateException( + "getBooleanRef() only legal on byRef Variants of type VariantBoolean, not " + + this.getvt()); + } + } + + /** + * + * @return returns the value as a boolean, throws an exception if its not. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public byte getByte() { + if (this.getvt() == VariantByte) { + return getVariantByte(); + } else { + throw new IllegalStateException( + "getByte() only legal on Variants of type VariantByte, not " + + this.getvt()); + } + } + + /** + * public cover for native method + * + * @return the byte from a booleanRef + * @throws IllegalStateException + * if variant is not of the requested type + */ + public byte getByteRef() { + if ((this.getvt() & VariantTypeMask) == VariantByte + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantByteRef(); + } else { + throw new IllegalStateException( + "getByteRef() only legal on byRef Variants of type VariantByte, not " + + this.getvt()); + } + } + + /** + * MS Currency objects are 64 bit fixed point numbers with 15 digits to the + * left and 4 to the right of the decimal place. + * + * @return returns the currency value as a long, throws exception if not a + * currency type.. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Currency getCurrency() { + if (this.getvt() == VariantCurrency) { + return new Currency(getVariantCurrency()); + } else { + throw new IllegalStateException( + "getCurrency() only legal on Variants of type VariantCurrency, not " + + this.getvt()); + } + } + + /** + * MS Currency objects are 64 bit fixed point numbers with 15 digits to the + * left and 4 to the right of the decimal place. + * + * @return returns the currency value as a long, throws exception if not a + * currency type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Currency getCurrencyRef() { + if ((this.getvt() & VariantTypeMask) == VariantCurrency + && (this.getvt() & VariantByref) == VariantByref) { + return new Currency(getVariantCurrencyRef()); + } else { + throw new IllegalStateException( + "getCurrencyRef() only legal on byRef Variants of type VariantCurrency, not " + + this.getvt()); + } + } + + /** + * @return double return the date (as a double) value held in this variant + * (fails on other types?) + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDate() { + if (this.getvt() == VariantDate) { + return getVariantDate(); + } else { + throw new IllegalStateException( + "getDate() only legal on Variants of type VariantDate, not " + + this.getvt()); + } + } + + /** + * + * @return returns the date value as a double, throws exception if not a + * date type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDateRef() { + if ((this.getvt() & VariantTypeMask) == VariantDate + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantDateRef(); + } else { + throw new IllegalStateException( + "getDateRef() only legal on byRef Variants of type VariantDate, not " + + this.getvt()); + } + } + + /** + * return the BigDecimal value held in this variant (fails on other types) + * + * @return BigDecimal + * @throws IllegalStateException + * if variant is not of the requested type + */ + public BigDecimal getDecimal() { + if (this.getvt() == VariantDecimal) { + return (BigDecimal) (getVariantDec()); + } else { + throw new IllegalStateException( + "getDecimal() only legal on Variants of type VariantDecimal, not " + + this.getvt()); + } + } + + /** + * return the BigDecimal value held in this variant (fails on other types) + * + * @return BigDecimal + * @throws IllegalStateException + * if variant is not of the requested type + */ + public BigDecimal getDecimalRef() { + if ((this.getvt() & VariantTypeMask) == VariantDecimal + && (this.getvt() & VariantByref) == VariantByref) { + return (BigDecimal) (getVariantDecRef()); + } else { + throw new IllegalStateException( + "getDecimalRef() only legal on byRef Variants of type VariantDecimal, not " + + this.getvt()); + } + } + + /** + * cover for {@link #toDispatch()} This method now matches other getXXX() + * methods. It throws an IllegalStateException if the object is not of type + * VariantDispatch + * + * @return this object as a dispatch + * @throws IllegalStateException + * if wrong variant type + */ + public Dispatch getDispatch() { + if (this.getvt() == VariantDispatch) { + return toDispatch(); + } else { + throw new IllegalStateException( + "getDispatch() only legal on Variants of type VariantDispatch, not " + + this.getvt()); + } + } + + /** + * Dispatch and dispatchRef are treated the same This is just a cover for + * toDispatch() with a flag check + * + * @return the results of toDispatch() + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Dispatch getDispatchRef() { + if ((this.getvt() & VariantTypeMask) == VariantDispatch + && (this.getvt() & VariantByref) == VariantByref) { + return toDispatch(); + } else { + throw new IllegalStateException( + "getDispatchRef() only legal on byRef Variants of type VariantDispatch, not " + + this.getvt()); + } + } + + /** + * @return double return the double value held in this variant (fails on + * other types?) + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDouble() { + if (this.getvt() == VariantDouble) { + return getVariantDouble(); + } else { + throw new IllegalStateException( + "getDouble() only legal on Variants of type VariantDouble, not " + + this.getvt()); + } + } + + /** + * + * @return returns the double value, throws exception if not a Double type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDoubleRef() { + if ((this.getvt() & VariantTypeMask) == VariantDouble + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantDoubleRef(); + } else { + throw new IllegalStateException( + "getDoubleRef() only legal on byRef Variants of type VariantDouble, not " + + this.getvt()); + } + } + + /** + * Pointless method that was put here so that putEmpty() has a get method. + * This would have returned null if the value was VT_EMPTY or if it wasn't + * so it would have always returned the same value. + * + * @deprecated method never did anything + */ + @Deprecated + public void getEmpty() { + } + + /** + * @return double return the error value held in this variant (fails on + * other types?) + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getError() { + if (this.getvt() == VariantError) { + return getVariantError(); + } else { + throw new IllegalStateException( + "getError() only legal on Variants of type VariantError, not " + + this.getvt()); + } + } + + /** + * + * @return returns the error value as an int, throws exception if not a + * Error type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getErrorRef() { + if ((this.getvt() & VariantTypeMask) == VariantError + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantErrorRef(); + } else { + throw new IllegalStateException( + "getErrorRef() only legal on byRef Variants of type VariantError, not " + + this.getvt()); + } + } + + /** + * @return returns the value as a float if the type is of type float + * @throws IllegalStateException + * if variant is not of the requested type + */ + public float getFloat() { + if (this.getvt() == VariantFloat) { + return getVariantFloat(); + } else { + throw new IllegalStateException( + "getFloat() only legal on Variants of type VariantFloat, not " + + this.getvt()); + } + } + + /** + * + * @return returns the float value, throws exception if not a Float type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public float getFloatRef() { + if ((this.getvt() & VariantTypeMask) == VariantFloat + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantFloatRef(); + } else { + throw new IllegalStateException( + "getFloatRef() only legal on byRef Variants of type VariantFloat, not " + + this.getvt()); + } + } + + /** + * return the int value held in this variant if it is an int or a short. + * Throws for other types. + * + * @return int contents of the windows memory + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getInt() { + if (this.getvt() == VariantInt) { + return getVariantInt(); + } else if (this.getvt() == VariantShort) { + return getVariantShort(); + } else { + throw new IllegalStateException( + "getInt() only legal on Variants of type VariantInt, not " + + this.getvt()); + } + } + + /** + * get the content of this variant as an int + * + * @return int + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getIntRef() { + if ((this.getvt() & VariantTypeMask) == VariantInt + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantIntRef(); + } else { + throw new IllegalStateException( + "getIntRef() only legal on byRef Variants of type VariantInt, not " + + this.getvt()); + } + } + + /** + * returns the windows time contained in this Variant to a Java Date. should + * return null if this is not a date Variant SF 959382 + * + * @return java.util.Date returns the date if this is a VariantDate != 0, + * null if it is a VariantDate == 0 and throws an + * IllegalStateException if this isn't a date. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Date getJavaDate() { + Date returnDate = null; + if (getvt() == VariantDate) { + double windowsDate = getDate(); + if (windowsDate != 0) { + returnDate = DateUtilities.convertWindowsTimeToDate(getDate()); + } + } else { + throw new IllegalStateException( + "getJavaDate() only legal on Variants of type VariantDate, not " + + this.getvt()); + } + return returnDate; + } + + /** + * returns the windows time contained in this Variant to a Java Date should + * return null if this is not a date reference Variant SF 959382 + * + * @return java.util.Date + */ + public Date getJavaDateRef() { + double windowsDate = getDateRef(); + if (windowsDate == 0) { + return null; + } else { + return DateUtilities.convertWindowsTimeToDate(windowsDate); + } + } + + /** + * 64 bit Longs only available on x64. 64 bit long support added 1.14 + * + * @return returns the value as a long, throws exception if not a Long + * type.. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public long getLong() { + if (this.getvt() == VariantLongInt) { + return getVariantLong(); + } else { + throw new IllegalStateException( + "getLong() only legal on Variants of type VariantLongInt, not " + + this.getvt()); + } + } + + /** + * 64 bit Longs only available on x64. 64 bit long support added 1.14 + * + * @return returns the value as a long, throws exception if not a long type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public long getLongRef() { + if ((this.getvt() & VariantTypeMask) == VariantLongInt + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantLongRef(); + } else { + throw new IllegalStateException( + "getLongRef() only legal on byRef Variants of type VariantLongInt, not " + + this.getvt()); + } + } + + /** + * This method would have returned null if the type was VT_NULL. But because + * we return null if the data is not of the right type, this method should + * have always returned null + * + * @deprecated method never did anything + */ + @Deprecated + public void getNull() { + } + + /** + * return the int value held in this variant (fails on other types?) + * + * @return int + * @throws IllegalStateException + * if variant is not of the requested type + */ + public short getShort() { + if (this.getvt() == VariantShort) { + return getVariantShort(); + } else { + throw new IllegalStateException( + "getShort() only legal on Variants of type VariantShort, not " + + this.getvt()); + } + } + + /** + * get the content of this variant as an int + * + * @return int + * @throws IllegalStateException + * if variant is not of the requested type + */ + public short getShortRef() { + if ((this.getvt() & VariantTypeMask) == VariantShort + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantShortRef(); + } else { + throw new IllegalStateException( + "getShortRef() only legal on byRef Variants of type VariantShort, not " + + this.getvt()); + } + } + + /** + * + * @return string contents of the variant. + * @throws IllegalStateException + * if this variant is not of type String + */ + public String getString() { + if (getvt() == Variant.VariantString) { + return getVariantString(); + } else { + throw new IllegalStateException( + "getString() only legal on Variants of type VariantString, not " + + this.getvt()); + } + } + + /** + * gets the content of the variant as a string ref + * + * @return String retrieved from the COM area. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public String getStringRef() { + if ((this.getvt() & VariantTypeMask) == VariantString + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantStringRef(); + } else { + throw new IllegalStateException( + "getStringRef() only legal on byRef Variants of type VariantString, not " + + this.getvt()); + } + } + + /** + * Used to get the value from a windows type of VT_VARIANT or a jacob + * Variant type of VariantVariant. Added 1.12 pre 6 - VT_VARIANT support is + * at an alpha level + * + * @return Object a java Object that represents the content of the enclosed + * Variant + */ + public Object getVariant() { + if ((this.getvt() & VariantTypeMask) == VariantVariant + && (this.getvt() & VariantByref) == VariantByref) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("About to call getVariantVariant()"); + } + Variant enclosedVariant = new Variant(); + int enclosedVariantMemory = getVariantVariant(); + enclosedVariant.m_pVariant = enclosedVariantMemory; + Object enclosedVariantAsJava = enclosedVariant.toJavaObject(); + // zero out the reference to the underlying windows memory so that + // it is still only owned in one place by one java object + // (this object of type VariantVariant) + // enclosedVariant.putEmpty(); // don't know if this would have had + // side effects + if (JacobObject.isDebugEnabled()) { + JacobObject + .debug("Zeroing out enclosed Variant's ref to windows memory"); + } + enclosedVariant.m_pVariant = 0; + return enclosedVariantAsJava; + } else { + throw new IllegalStateException( + "getVariant() only legal on Variants of type VariantVariant, not " + + this.getvt()); + } + } + + /** + * @deprecated superseded by SafeArray + * @return never returns anything + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Variant[] getVariantArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * @return the Variant Array that represents the data in the Variant + * @deprecated superseded by SafeArray + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Variant[] getVariantArrayRef() { + throw new NotImplementedException("Not implemented"); + } + + /** + * + * @return the value in this Variant as a boolean, null if not a boolean + */ + private native boolean getVariantBoolean(); + + private native boolean getVariantBooleanRef(); + + /** + * @return the value in this Variant as a byte, null if not a byte + */ + private native byte getVariantByte(); + + /** + * @return the value in this Variant as a byte, null if not a byte + */ + private native byte getVariantByteRef(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantCurrency(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantCurrencyRef(); + + /** + * @return double return the date (as a double) value held in this variant + * (fails on other types?) + */ + private native double getVariantDate(); + + /** + * get the content of this variant as a double representing a date + * + * @return double + */ + private native double getVariantDateRef(); + + /** + * @return the value in this Variant as a decimal, null if not a decimal + */ + private native Object getVariantDec(); + + /** + * @return the value in this Variant (byref) as a decimal, null if not a + * decimal + */ + private native Object getVariantDecRef(); + + /** + * @return double get the content of this variant as a double + */ + private native double getVariantDouble(); + + /** + * @return double get the content of this variant as a double + */ + private native double getVariantDoubleRef(); + + private native int getVariantError(); + + private native int getVariantErrorRef(); + + /** + * @return returns the value as a float if the type is of type float + */ + private native float getVariantFloat(); + + /** + * @return returns the value as a float if the type is of type float + */ + private native float getVariantFloatRef(); + + /** + * @return the int value held in this variant (fails on other types?) + */ + private native int getVariantInt(); + + /** + * @return the int value held in this variant (fails on other types?) + */ + private native int getVariantIntRef(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantLong(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantLongRef(); + + /** + * get the content of this variant as a short + * + * @return short + */ + private native short getVariantShort(); + + /** + * @return short the content of this variant as a short + */ + private native short getVariantShortRef(); + + /** + * Native method that actually extracts a string value from the variant + * + * @return + */ + private native String getVariantString(); + + /** + * @return String the content of this variant as a string + */ + private native String getVariantStringRef(); + + /** + * Returns the variant type via a native method call + * + * @return short one of the VT_xx types + */ + private native short getVariantType(); + + /** + * Returns the variant type via a native method call. Added 1.12 pre 6 - + * VT_VARIANT support is at an alpha level + * + * @return Variant one of the VT_Variant types + */ + private native int getVariantVariant(); + + /** + * Reports the type of the underlying Variant object + * + * @return returns the variant type as a short, one of the Variantxxx values + * defined as statics in this class. returns VariantNull if not + * initialized + * @throws IllegalStateException + * if there is no underlying windows data structure + */ + public short getvt() { + if (m_pVariant != 0) { + return getVariantType(); + } else { + throw new IllegalStateException("uninitialized Variant"); + } + } + + /** + * initializes the COM Variant and puts its reference in this instance + */ + protected native void init(); + + /** + * + * @return returns true if the variant is considered null + * @throws IllegalStateException + * if there is no underlying windows memory + */ + public boolean isNull() { + getvt(); + return isVariantConsideredNull(); + } + + /** + * is the variant null or empty or error or null dispatch + * + * @return true if it is null or false if not + */ + private native boolean isVariantConsideredNull(); + + /** + * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND + * + * @deprecated replaced by putNoParam() + */ + @Deprecated + public void noParam() { + putNoParam(); + } + + /** + * returns true if the passed in Variant is a constant that should not be + * freed + * + * @param pVariant + * @return boolean that is true if Variant is a type of constant, VT_FALSE, + * VT_TRUE, VT_MISSING, DEFAULT + */ + protected boolean objectIsAConstant(Variant pVariant) { + if (pVariant == VT_FALSE || pVariant == VT_TRUE + || pVariant == VT_MISSING || pVariant == DEFAULT) { + return true; + } else { + return false; + } + + } + + /** + * puts a boolean into the variant and sets it's type + * + * @param in + * the new value + */ + public void putBoolean(boolean in) { + // verify we aren't released yet + getvt(); + putVariantBoolean(in); + } + + /** + * pushes a boolean into the variant by ref and sets the type of the variant + * to boolean + * + * @param in + */ + public void putBooleanRef(boolean in) { + // verify we aren't released yet + getvt(); + putVariantBooleanRef(in); + } + + /** + * pushes a byte into the varaint and sets the type + * + * @param in + */ + public void putByte(byte in) { + // verify we aren't released yet + getvt(); + putVariantByte(in); + }; + + /** + * @deprecated superseded by SafeArray + * @param in + * doesn't matter because this method does nothing + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putByteArray(Object in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * pushes a byte into the variant by ref and sets the type + * + * @param in + */ + public void putByteRef(byte in) { + // verify we aren't released yet + getvt(); + putVariantByteRef(in); + } + + /** + * @param in + * the object that would be wrapped by the Variant if this method + * was implemented + * @deprecated superseded by SafeArray + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putCharArray(Object in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * Puts a value in as a currency and sets the variant type. MS Currency + * objects are 64 bit fixed point numbers with 15 digits to the left and 4 + * to the right of the decimal place. + * + * @param in + * the long that will be put into the 64 bit currency object. + */ + public void putCurrency(Currency in) { + // verify we aren't released yet + getvt(); + putVariantCurrency(in.longValue()); + } + + /** + * Pushes a long into the variant as currency and sets the type. MS Currency + * objects are 64 bit fixed point numbers with 15 digits to the left and 4 + * to the right of the decimal place. + * + * @param in + * the long that will be put into the 64 bit currency object + */ + public void putCurrencyRef(Currency in) { + // verify we aren't released yet + getvt(); + putVariantCurrencyRef(in.longValue()); + } + + /** + * converts a java date to a windows time and calls putDate(double) SF + * 959382 + * + * @param inDate + * a Java date to be converted + * @throws IllegalArgumentException + * if inDate = null + */ + public void putDate(Date inDate) { + if (inDate == null) { + throw new IllegalArgumentException( + "Cannot put null in as windows date"); + // do nothing + } else { + putDate(DateUtilities.convertDateToWindowsTime(inDate)); + } + } + + /** + * puts a windows date double into the variant and sets the type + * + * @param in + */ + public void putDate(double in) { + // verify we aren't released yet + getvt(); + putVariantDate(in); + } + + /** + * converts a java date to a windows time and calls putDateRef(double) SF + * 959382 + * + * @param inDate + * a Java date to be converted + * @throws IllegalArgumentException + * if inDate = null + */ + public void putDateRef(Date inDate) { + if (inDate == null) { + throw new IllegalArgumentException( + "Cannot put null in as windows date"); + // do nothing + } else { + putDateRef(DateUtilities.convertDateToWindowsTime(inDate)); + } + } + + /** + * set the content of this variant to a date (VT_DATE|VT_BYREF) + * + * @param in + */ + public void putDateRef(double in) { + // verify we aren't released + getvt(); + putVariantDateRef(in); + } + + /** + * This actual does all the validating and massaging of the BigDecimalValues + * when converting them to MS Decimal types + * + * @param in + * number to be made into VT_DECIMAL + * @param byRef + * store by reference or not + * @param roundingBehavior + * one of the BigDecimal ROUND_xxx methods. Any method other than + * ROUND_UNECESSARY means that the value will be rounded to fit + */ + private void putDecimal(BigDecimal in, boolean byRef) { + // verify we aren't released + getvt(); + // first validate the min and max + VariantUtilities.validateDecimalMinMax(in); + BigInteger allWordBigInt; + allWordBigInt = in.unscaledValue(); + // Assume any required rounding has been done. + VariantUtilities.validateDecimalScaleAndBits(in); + // finally we can do what we actually came here to do + int sign = in.signum(); + // VT_DECIMAL always has positive value with just the sign + // flipped + if (in.signum() < 0) { + in = in.negate(); + } + // ugh, reusing allWordBigInt but now should always be positive + // and any round is applied + allWordBigInt = in.unscaledValue(); + byte scale = (byte) in.scale(); + int lowWord = allWordBigInt.intValue(); + BigInteger middleWordBigInt = allWordBigInt.shiftRight(32); + int middleWord = middleWordBigInt.intValue(); + BigInteger highWordBigInt = allWordBigInt.shiftRight(64); + int highWord = highWordBigInt.intValue(); + if (byRef) { + putVariantDecRef(sign, scale, lowWord, middleWord, highWord); + } else { + putVariantDec(sign, scale, lowWord, middleWord, highWord); + } + } + + /** + * EXPERIMENTAL 1.14 feature to support rounded decimals. + *

    + * Set the value of this variant and set the type. This may throw exceptions + * more often than the caller expects because most callers don't manage the + * scale of their BigDecimal objects. + *

    + * This default set method throws exceptions if precision or size is out of + * bounds + *

    + * There are 12 bytes available for the integer number. + *

    + * There is 1 byte for the scale. + * + * @param in + * the BigDecimal that will be converted to VT_DECIMAL + * @throws IllegalArgumentException + * if the scale is > 28, the maximum for VT_DECIMAL or if there + * are more than 12 bytes worth the digits + */ + public void putDecimal(BigDecimal in) { + putDecimal(in, false); + } + + /** + * Set the value of this variant and set the type. This may throw exceptions + * more often than the caller expects because most callers don't manage the + * scale of their BigDecimal objects. + *

    + * This default set method throws exceptions if precision or size is out of + * bounds + *

    + * There are 12 bytes available for the integer number. + *

    + * There is 1 byte for the scale. + * + * @param in + * the BigDecimal that will be converted to VT_DECIMAL + * @throws IllegalArgumentException + * if the scale is > 28, the maximum for VT_DECIMAL or if there + * are more than 12 bytes worth the digits + */ + public void putDecimalRef(BigDecimal in) { + putDecimal(in, true); + } + + /** + * This acts a cover for putVariant Dispatch. + * + * @param in + * the Dispatch we're putting down in the COM variant space. + */ + public void putDispatch(Dispatch in) { + putVariantDispatch(in); + } + + /** + * Dispatch and dispatchRef are treated the same This is a cover for + * putVariantDispatch(). putDispatch and putDispatchRef are treated the same + * because no one has written the COM code for putDispatchRef. + * + * @param in + * the Dispatch we're putting down in the COM variant space. + */ + public void putDispatchRef(Dispatch in) { + putVariantDispatch(in); + } + + /** + * wraps this Variant around the passed in double. + * + * @param in + */ + public void putDouble(double in) { + // verify we aren't released yet + getvt(); + putVariantDouble(in); + } + + /** + * set the content of this variant to a double (VT_R8|VT_BYREF) + * + * @param in + */ + public void putDoubleRef(double in) { + // verify we aren't released + getvt(); + putVariantDoubleRef(in); + } + + /** + * sets the type to VariantEmpty + * + */ + public void putEmpty() { + // verify we aren't released yet + getvt(); + putVariantEmpty(); + } + + /** + * puts an error code (I think) into the variant and sets the type + * + * @param in + */ + public void putError(int in) { + // verify we aren't released yet + getvt(); + putVariantError(in); + } + + /** + * pushes an error code into the variant by ref and sets the type + * + * @param in + */ + public void putErrorRef(int in) { + // verify we aren't released yet + getvt(); + putVariantErrorRef(in); + } + + /** + * fills the Variant with a float and sets the type to float + * + * @param in + */ + public void putFloat(float in) { + // verify we haven't been released yet + getvt(); + putVariantFloat(in); + } + + /** + * pushes a float into the variant and sets the type + * + * @param in + */ + public void putFloatRef(float in) { + // verify we aren't released yet + getvt(); + putVariantFloatRef(in); + } + + /** + * set the value of this variant and set the type + * + * @param in + */ + public void putInt(int in) { + // verify we aren't released yet + getvt(); + putVariantInt(in); + } + + /** + * set the content of this variant to an int (VT_I4|VT_BYREF) + * + * @param in + */ + public void putIntRef(int in) { + // verify we aren't released + getvt(); + putVariantIntRef(in); + } + + /** + * Puts a 64 bit Java Long into a 64 bit Variant Long. Only works on x64 + * systems otherwise throws an error. 64 bit long support added 1.14 + * + * @param in + * the long that will be put into the 64 bit Long object. + */ + public void putLong(long in) { + // verify we aren't released yet + getvt(); + putVariantLong(in); + } + + /** + * Puts a 64 bit Java Long into a 64 bit Variant Long. Only works on x64 + * systems otherwise throws an error. 64 bit long support added 1.14 + * + * @param in + * the long that will be put into the 64 bit Long object. + */ + public void putLongRef(long in) { + // verify we aren't released yet + getvt(); + putVariantLongRef(in); + } + + /** + * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND + */ + public void putNoParam() { + // verify we aren't released yet + getvt(); + putVariantNoParam(); + } + + /** + * Sets the type to VariantDispatch and sets the value to null Equivalent to + * VB's nothing + */ + public void putNothing() { + // verify we aren't released yet + getvt(); + putVariantNothing(); + } + + /** + * Set this Variant's type to VT_NULL (the VB equivalent of NULL) + */ + public void putNull() { + // verify we aren't released yet + getvt(); + putVariantNull(); + } + + /** + * Puts an object into the Variant -- converts to Dispatch. Acts as a cover + * for putVariantDispatch(); This primarily exists to support jacobgen. This + * should be deprecated. + * + * @param in + * the object we are putting into the Variant, assumes a + * @see Variant#putDispatch(Dispatch) + * @deprecated should use putDispatch() + */ + @Deprecated + public void putObject(Object in) { + // this should verify in instanceof Dispatch + putVariantDispatch(in); + } + + /** + * Just a cover for putObject(). We shouldn't accept any old random object. + * This has been left in to support jacobgen. This should be deprecated. + * + * @param in + * @deprecated + */ + @Deprecated + public void putObjectRef(Object in) { + putObject(in); + } + + /** + * have no idea... + * + * @param in + */ + public void putSafeArray(SafeArray in) { + // verify we haven't been released yet + getvt(); + putVariantSafeArray(in); + } + + /** + * have no idea... + * + * @param in + */ + public void putSafeArrayRef(SafeArray in) { + // verify we haven't been released yet + getvt(); + putVariantSafeArrayRef(in); + } + + /** + * set the content of this variant to a short (VT_I2) + * + * @param in + */ + public void putShort(short in) { + // verify we aren't released + getvt(); + putVariantShort(in); + } + + /** + * set the content of this variant to a short (VT_I2|VT_BYREF) + * + * @param in + */ + public void putShortRef(short in) { + // verify we aren't released + getvt(); + putVariantShortRef(in); + } + + /** + * put a string into the variant and set its type + * + * @param in + */ + public void putString(String in) { + // verify we aren't released yet + getvt(); + putVariantString(in); + } + + /** + * set the content of this variant to a string (VT_BSTR|VT_BYREF) + * + * @param in + */ + public void putStringRef(String in) { + // verify we aren't released + getvt(); + putVariantStringRef(in); + } + + /** + * Puts a variant into this variant making it type VT_VARIANT. Added 1.12 + * pre 6 + * + * @param objectToBeWrapped + * A object that is to be referenced by this variant. If + * objectToBeWrapped is already of type Variant, then it is used. + * If objectToBeWrapped is not Variant then + * new Variant(objectToBeWrapped) is called and the + * result is passed into the com layer + * @throws IllegalArgumentException + * if inVariant = null or if inVariant is a Varint + */ + public void putVariant(Object objectToBeWrapped) { + if (objectToBeWrapped == null) { + throw new IllegalArgumentException( + "Cannot put null in as a variant"); + } else if (objectToBeWrapped instanceof Variant) { + throw new IllegalArgumentException( + "Cannot putVariant() only accepts non jacob objects."); + } else { + Variant inVariant = new Variant(objectToBeWrapped); + putVariantVariant(inVariant); + // This could be done in Variant.cpp + if (JacobObject.isDebugEnabled()) { + JacobObject + .debug("Zeroing out enclosed Variant's ref to windows memory"); + } + inVariant.m_pVariant = 0; + } + } + + /** + * @deprecated superseded by SafeArray + * @param in + * doesn't matter because this method does nothing + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putVariantArray(Variant[] in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * @param in + * the thing that would be come an array if this method was + * implemented + * @deprecated superseded by SafeArray + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putVariantArrayRef(Variant[] in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * puts a boolean into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantBoolean(boolean in); + + /** + * puts a boolean into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantBooleanRef(boolean in); + + /** + * puts a byte into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantByte(byte in); + + /** + * puts a byte into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantByteRef(byte in); + + /** + * puts a Currency into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantCurrency(long in); + + /** + * puts a Currency into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantCurrencyRef(long in); + + /** + * set the value of this variant + * + * @param in + */ + private native void putVariantDate(double in); + + /** + * set the content of this variant to a date (VT_DATE|VT_BYREF) + * + * @param in + */ + private native void putVariantDateRef(double in); + + /** + * private JNI method called by putDecimal + * + * @param signum + * sign + * @param scale + * BigDecimal's scale + * @param lo + * low 32 bits + * @param mid + * middle 32 bits + * @param hi + * high 32 bits + */ + private native void putVariantDec(int signum, byte scale, int lo, int mid, + int hi); + + /** + * private JNI method called by putDecimalRef + * + * @param signum + * sign + * @param scale + * BigDecimal's scale + * @param lo + * low 32 bits + * @param mid + * middle 32 bits + * @param hi + * high 32 bits + */ + private native void putVariantDecRef(int signum, byte scale, int lo, + int mid, int hi); + + /** + * the JNI implementation for putDispatch() so that we can screen the + * incoming dispatches in putDispatch() before this is invoked + * + * @param in + * should be a dispatch object + */ + private native void putVariantDispatch(Object in); + + private native void putVariantDouble(double in); + + /** + * set the content of this variant to a double (VT_R8|VT_BYREF) + * + * @param in + */ + private native void putVariantDoubleRef(double in); + + /** + * Sets the type to VariantEmpty. No values needed + */ + private native void putVariantEmpty(); + + private native void putVariantError(int in); + + private native void putVariantErrorRef(int in); + + /** + * fills the Variant with a float and sets the type to float + * + * @param in + */ + private native void putVariantFloat(float in); + + private native void putVariantFloatRef(float in); + + /** + * set the value of this variant and set the type + * + * @param in + */ + private native void putVariantInt(int in); + + /** + * set the content of this variant to an int (VT_I4|VT_BYREF) + * + * @param in + */ + private native void putVariantIntRef(int in); + + private native void putVariantLong(long in); + + private native void putVariantLongRef(long in); + + /** + * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND + */ + private native void putVariantNoParam(); + + /** + * Sets the type to VariantDispatch and sets the value to null Equivalent to + * VB's nothing + */ + private native void putVariantNothing(); + + /** + * Set this Variant's type to VT_NULL (the VB equivalent of NULL) + */ + private native void putVariantNull(); + + private native void putVariantSafeArray(SafeArray in); + + private native void putVariantSafeArrayRef(SafeArray in); + + /** + * set the content of this variant to a short (VT_I2) + * + * @param in + */ + private native void putVariantShort(short in); + + /** + * set the content of this variant to a short (VT_I2|VT_BYREF) + * + * @param in + */ + private native void putVariantShortRef(short in); + + private native void putVariantString(String in); + + /** + * set the content of this variant to a string (VT_BSTR|VT_BYREF) + * + * @param in + */ + private native void putVariantStringRef(String in); + + /** + * All VariantVariant type variants are BYREF. + * + * Set the content of this variant to a string (VT_VARIANT|VT_BYREF). + * + * Added 1.12 pre 6 - VT_VARIANT support is at an alpha level + * + * @param in + * variant to be wrapped + * + */ + private native void putVariantVariant(Variant in); + + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /** + * This will release the "C" memory for the Variant unless this Variant is + * one of the constants in which case we don't want to release the memory. + *

    + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + @Override + public void safeRelease() { + // The well known constants should not be released. + // Unfortunately this doesn't fix any other classes that are + // keeping constants around in their static ivars. + // those will still be busted. + // + // The only inconsistency here is that we leak + // when this class is unloaded because we won't + // free the memory even if the constants are being + // finalized. this is not a big deal at all. + // another way around this would be to create the constants + // in their own thread so that they would never be released + if (!objectIsAConstant(this)) { + super.safeRelease(); + if (m_pVariant != 0) { + release(); + m_pVariant = 0; + } else { + // looks like a double release + // this should almost always happen due to gc + // after someone has called ComThread.Release + if (isDebugEnabled()) { + debug("Variant: " + this.hashCode() + " double release"); + // Throwable x = new Throwable(); + // x.printStackTrace(); + } + } + } else { + if (isDebugEnabled()) { + debug("Variant: " + this.hashCode() + + " don't want to release a constant"); + } + } + } + + /** + * this is supposed to cause the underlying variant object struct to be + * rebuilt from a previously serialized byte array. + * + * @param ba + */ + protected native void SerializationReadFromBytes(byte[] ba); + + /** + * this is supposed to create a byte array that represents the underlying + * variant object structure + */ + protected native byte[] SerializationWriteToBytes(); + + /** + * @deprecated should be replaced by changeType() followed by getBoolean() + * @return the value of this variant as boolean (after possible conversion) + */ + @Deprecated + public boolean toBoolean() { + changeType(Variant.VariantBoolean); + return getBoolean(); + } + + /** + * attempts to return the content of this variant as a double (after + * possible conversion) + * + * @deprecated should be replaced by changeType() followed by getByte() + * @return byte + */ + @Deprecated + public byte toByte() { + changeType(Variant.VariantByte); + return getByte(); + } + + /** + * @deprecated superseded by SafeArray + * @return nothing because this method is not implemented + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Object toByteArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * @deprecated superseded by SafeArray + * @return never returns anything + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Object toCharArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * @deprecated should be replaced by changeType() followed by getCurrency + * @return the content of this variant as a long representing a monetary + * amount + */ + @Deprecated + public Currency toCurrency() { + changeType(Variant.VariantCurrency); + return getCurrency(); + } + + /** + * @deprecated should use changeType() followed by getDate() + * @return the value of this variant as a date (after possible conversion) + */ + @Deprecated + public double toDate() { + changeType(VariantDate); + return getDate(); + } + + /** + * @return the content of this variant as a Dispatch object (after possible + * conversion) + */ + public Dispatch toDispatch() { + // now make the native call + return toVariantDispatch(); + } + + /** + * @deprecated should call changeType() then getDouble() + * @return the content of this variant as a double (after possible + * conversion) + */ + @Deprecated + public double toDouble() { + changeType(Variant.VariantDouble); + return getDouble(); + } + + /** @return the value of this variant as an enumeration (java style) */ + public native EnumVariant toEnumVariant(); + + /** + * converts to an error type and returns the error + * + * @deprecated should use changeType() followed by getError() + * @return the error as an int (after conversion) + */ + @Deprecated + public int toError() { + changeType(Variant.VariantError); + return getError(); + } + + /** + * attempts to return the contents of this variant as a float (after + * possible conversion) + * + * @deprecated should use changeType() and getFloat() instead + * @return float + */ + @Deprecated + public float toFloat() { + changeType(Variant.VariantFloat); + return getFloat(); + } + + /** + * @deprecated should use changeType() followed by getInt() + * @return the value of this variant as an int (after possible conversion) + */ + @Deprecated + public int toInt() { + changeType(VariantInt); + return getInt(); + } + + /** + * Returns the windows time contained in this Variant as a Java Date + * converts to a date like many of the other toXXX() methods SF 959382. + *

    + * This method added 12/2005 for possible use by jacobgen instead of its + * conversion code + *

    + * This does not convert the data + * + * @deprecated callers should use getDate() + * @return java.util.Date version of this variant if it is a date, otherwise + * null + * + */ + @Deprecated + public Date toJavaDate() { + changeType(Variant.VariantDate); + return getJavaDate(); + } + + /** + * Convert a JACOB Variant value to a Java object (type conversions). + * provided in Sourceforge feature request 959381. See + * JavaVariantConverter..convertVariantTJavaObject(Variant) for more + * information. + * + * @return Corresponding Java object of the type matching the Variant type. + * @throws IllegalStateException + * if no underlying windows data structure + * @throws NotImplementedException + * if unsupported conversion is requested + * @throws JacobException + * if the calculated result was a JacobObject usually as a + * result of error + */ + public Object toJavaObject() throws JacobException { + return VariantUtilities.variantToObject(this); + } + + /** + * Acts a a cover for toDispatch. This primarily exists to support jacobgen. + * + * @deprecated this is a cover for toDispatch(); + * @return Object returned by toDispatch() + * @see Variant#toDispatch() instead + */ + @Deprecated + public Object toObject() { + return toDispatch(); + } + + /** + * By default toSafeArray makes a deep copy due to the fact that this + * Variant owns the embedded SafeArray and will destroy it when it gc's + * calls toSafeArray(true). + * + * @return the object converted to a SafeArray + */ + public SafeArray toSafeArray() { + // verify we haven't been released yet + getvt(); + return toSafeArray(true); + } + + /** + * This lets folk turn into a safe array without a deep copy. Should this + * API be public? + * + * @param deepCopy + * @return SafeArray constructed + */ + public SafeArray toSafeArray(boolean deepCopy) { + // verify we haven't been released yet + getvt(); + return toVariantSafeArray(deepCopy); + } + + /** + * I don't know what this is. Is it some legacy (pre 1.8) thing? + * + * @deprecated + * @return this object as a dispatch object by calling toDispatch() + */ + @Deprecated + public Object toScriptObject() { + return toDispatch(); + } + + /** + * attempts to return the contents of this Variant as a short (after + * possible conversion) + * + * @deprecated callers should use changeType() followed by getShort() + * @return short + */ + @Deprecated + public short toShort() { + this.changeType(Variant.VariantShort); + return getShort(); + } + + /** + * This method now correctly implements java toString() semantics Attempts + * to return the content of this variant as a string + *