From b1dbd7a76c64622d545fe29f24547107287870ca Mon Sep 17 00:00:00 2001 From: liujt Date: Tue, 12 Mar 2019 16:51:39 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E6=B5=B7=E6=8A=A5scaleType=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/cn/ctyun/player/activity/DemoActivity.java | 1 + .../src/main/res/layout/dkplayer_layout_standard_controller.xml | 2 +- player/src/main/res/layout/layout_ad_controller.xml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java b/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java index 72ab85f..8888fc5 100644 --- a/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java +++ b/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java @@ -16,6 +16,7 @@ import java.util.List; import cn.ctyun.player.R; import cn.ctyun.videoplayer.bean.FloatingComment; import cn.ctyun.videoplayer.bean.VideoModel; +import cn.ctyun.videoplayer.interf.AdControllerListener; import cn.ctyun.videoplayer.player.PlayerConfig; import cn.ctyun.videoplayer.util.Constants; import cn.ctyun.videoplayer.util.MemoryLeakUtil; diff --git a/player/src/main/res/layout/dkplayer_layout_standard_controller.xml b/player/src/main/res/layout/dkplayer_layout_standard_controller.xml index 330457c..77e8dab 100644 --- a/player/src/main/res/layout/dkplayer_layout_standard_controller.xml +++ b/player/src/main/res/layout/dkplayer_layout_standard_controller.xml @@ -201,7 +201,7 @@ android:id="@+id/thumb" android:layout_width="match_parent" android:layout_height="match_parent" - android:scaleType="centerCrop" /> + android:scaleType="fitXY" /> + android:scaleType="fitXY" /> Date: Tue, 12 Mar 2019 17:35:06 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=9B=E6=8A=95=E5=B1=8F=E6=9C=AA=E5=90=AF?= =?UTF-8?q?=E7=94=A8=EF=BC=8C=E5=B1=8F=E8=94=BD=E6=8A=95=E5=B1=8F=E6=8C=89?= =?UTF-8?q?=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clinglibrary/.gitignore | 1 - clinglibrary/build.gradle | 31 - clinglibrary/proguard-rules.pro | 25 - .../clinglibrary/ExampleInstrumentedTest.java | 26 - clinglibrary/src/main/AndroidManifest.xml | 13 - .../DefaultUpnpServiceConfiguration.java | 374 ------ .../main/java/org/fourthline/cling/Main.java | 106 -- .../fourthline/cling/ManagedUpnpService.java | 237 ---- .../ManagedUpnpServiceConfiguration.java | 260 ---- .../org/fourthline/cling/UpnpService.java | 65 - .../cling/UpnpServiceConfiguration.java | 256 ---- .../org/fourthline/cling/UpnpServiceImpl.java | 177 --- .../android/AndroidNetworkAddressFactory.java | 113 -- .../cling/android/AndroidRouter.java | 320 ----- .../cling/android/AndroidUpnpService.java | 94 -- .../AndroidUpnpServiceConfiguration.java | 143 --- .../cling/android/AndroidUpnpServiceImpl.java | 122 -- .../cling/android/FixedAndroidLogHandler.java | 145 --- .../cling/android/NetworkUtils.java | 80 -- .../cling/binding/AllowedValueProvider.java | 25 - .../binding/AllowedValueRangeProvider.java | 27 - .../cling/binding/LocalServiceBinder.java | 50 - .../binding/LocalServiceBindingException.java | 32 - .../annotations/AnnotationActionBinder.java | 338 ----- .../AnnotationLocalServiceBinder.java | 293 ----- .../AnnotationStateVariableBinder.java | 316 ----- .../cling/binding/annotations/UpnpAction.java | 30 - .../annotations/UpnpInputArgument.java | 31 - .../annotations/UpnpOutputArgument.java | 32 - .../binding/annotations/UpnpService.java | 35 - .../binding/annotations/UpnpServiceId.java | 31 - .../binding/annotations/UpnpServiceType.java | 32 - .../annotations/UpnpStateVariable.java | 50 - .../annotations/UpnpStateVariables.java | 33 - .../cling/binding/staging/MutableAction.java | 45 - .../staging/MutableActionArgument.java | 34 - .../staging/MutableAllowedValueRange.java | 29 - .../cling/binding/staging/MutableDevice.java | 120 -- .../cling/binding/staging/MutableIcon.java | 36 - .../cling/binding/staging/MutableService.java | 71 -- .../binding/staging/MutableStateVariable.java | 58 - .../binding/staging/MutableUDAVersion.java | 24 - .../cling/binding/xml/Descriptor.java | 105 -- .../xml/DescriptorBindingException.java | 33 - .../binding/xml/DeviceDescriptorBinder.java | 41 - ...veringUDA10DeviceDescriptorBinderImpl.java | 249 ---- .../binding/xml/ServiceDescriptorBinder.java | 38 - .../xml/UDA10DeviceDescriptorBinderImpl.java | 626 ---------- .../UDA10DeviceDescriptorBinderSAXImpl.java | 470 ------- .../xml/UDA10ServiceDescriptorBinderImpl.java | 504 -------- .../UDA10ServiceDescriptorBinderSAXImpl.java | 448 ------- .../cling/controlpoint/ActionCallback.java | 202 --- .../cling/controlpoint/ControlPoint.java | 43 - .../cling/controlpoint/ControlPointImpl.java | 115 -- .../controlpoint/SubscriptionCallback.java | 374 ------ .../controlpoint/event/ExecuteAction.java | 34 - .../cling/controlpoint/event/Search.java | 53 - .../cling/mock/MockProtocolFactory.java | 101 -- .../org/fourthline/cling/mock/MockRouter.java | 173 --- .../cling/mock/MockUpnpService.java | 173 --- .../mock/MockUpnpServiceConfiguration.java | 135 -- .../org/fourthline/cling/model/Command.java | 26 - .../org/fourthline/cling/model/Constants.java | 69 -- .../cling/model/DefaultServiceManager.java | 268 ---- .../cling/model/DiscoveryOptions.java | 70 -- .../cling/model/ExpirationDetails.java | 84 -- .../org/fourthline/cling/model/Location.java | 89 -- .../org/fourthline/cling/model/ModelUtil.java | 250 ---- .../org/fourthline/cling/model/Namespace.java | 221 ---- .../cling/model/NetworkAddress.java | 75 -- .../cling/model/ServerClientTokens.java | 169 --- .../cling/model/ServiceManager.java | 136 --- .../cling/model/ServiceReference.java | 92 -- .../cling/model/UnsupportedDataException.java | 51 - .../fourthline/cling/model/UserConstants.java | 31 - .../fourthline/cling/model/Validatable.java | 31 - .../cling/model/ValidationError.java | 58 - .../cling/model/ValidationException.java | 46 - .../fourthline/cling/model/VariableValue.java | 111 -- .../org/fourthline/cling/model/XMLUtil.java | 220 ---- .../model/action/AbstractActionExecutor.java | 178 --- .../model/action/ActionArgumentValue.java | 41 - .../action/ActionCancelledException.java | 27 - .../cling/model/action/ActionException.java | 58 - .../cling/model/action/ActionExecutor.java | 28 - .../cling/model/action/ActionInvocation.java | 194 --- .../model/action/MethodActionExecutor.java | 191 --- .../action/QueryStateVariableExecutor.java | 81 -- .../model/action/RemoteActionInvocation.java | 54 - .../cling/model/gena/CancelReason.java | 29 - .../cling/model/gena/GENASubscription.java | 96 -- .../model/gena/LocalGENASubscription.java | 251 ---- .../model/gena/RemoteGENASubscription.java | 129 -- .../cling/model/message/Connection.java | 33 - .../message/IncomingDatagramMessage.java | 69 -- .../message/OutgoingDatagramMessage.java | 56 - .../model/message/StreamRequestMessage.java | 88 -- .../model/message/StreamResponseMessage.java | 78 -- .../cling/model/message/UpnpHeaders.java | 197 --- .../cling/model/message/UpnpMessage.java | 217 ---- .../cling/model/message/UpnpOperation.java | 34 - .../cling/model/message/UpnpRequest.java | 108 -- .../cling/model/message/UpnpResponse.java | 100 -- .../model/message/control/ActionMessage.java | 31 - .../message/control/ActionRequestMessage.java | 23 - .../control/ActionResponseMessage.java | 22 - .../control/IncomingActionRequestMessage.java | 69 -- .../IncomingActionResponseMessage.java | 50 - .../control/OutgoingActionRequestMessage.java | 112 -- .../OutgoingActionResponseMessage.java | 77 -- .../IncomingNotificationRequest.java | 100 -- .../discovery/IncomingSearchRequest.java | 55 - .../discovery/IncomingSearchResponse.java | 92 -- .../OutgoingNotificationRequest.java | 60 - ...OutgoingNotificationRequestDeviceType.java | 37 - ...OutgoingNotificationRequestRootDevice.java | 47 - ...utgoingNotificationRequestServiceType.java | 42 - .../OutgoingNotificationRequestUDN.java | 36 - .../discovery/OutgoingSearchRequest.java | 53 - .../discovery/OutgoingSearchResponse.java | 56 - .../OutgoingSearchResponseDeviceType.java | 39 - .../OutgoingSearchResponseRootDevice.java | 38 - .../OutgoingSearchResponseServiceType.java | 41 - .../discovery/OutgoingSearchResponseUDN.java | 37 - .../gena/IncomingEventRequestMessage.java | 90 -- .../gena/IncomingSubscribeRequestMessage.java | 63 - .../IncomingSubscribeResponseMessage.java | 47 - .../IncomingUnsubscribeRequestMessage.java | 53 - .../gena/OutgoingEventRequestMessage.java | 66 - .../gena/OutgoingEventResponseMessage.java | 37 - .../gena/OutgoingRenewalRequestMessage.java | 50 - .../gena/OutgoingSubscribeRequestMessage.java | 66 - .../OutgoingSubscribeResponseMessage.java | 43 - .../OutgoingUnsubscribeRequestMessage.java | 44 - .../message/header/AVClientInfoHeader.java | 41 - .../model/message/header/CallbackHeader.java | 103 -- .../message/header/ContentRangeHeader.java | 52 - .../message/header/ContentTypeHeader.java | 56 - .../message/header/DeviceTypeHeader.java | 49 - .../model/message/header/DeviceUSNHeader.java | 50 - .../cling/model/message/header/EXTHeader.java | 39 - .../message/header/EventSequenceHeader.java | 52 - .../model/message/header/HostHeader.java | 61 - .../message/header/InterfaceMacHeader.java | 54 - .../header/InvalidHeaderException.java | 29 - .../model/message/header/LocationHeader.java | 53 - .../cling/model/message/header/MANHeader.java | 78 -- .../cling/model/message/header/MXHeader.java | 57 - .../model/message/header/MaxAgeHeader.java | 54 - .../model/message/header/NTEventHeader.java | 39 - .../cling/model/message/header/NTSHeader.java | 48 - .../model/message/header/PragmaHeader.java | 50 - .../model/message/header/RangeHeader.java | 50 - .../message/header/RootDeviceHeader.java | 39 - .../model/message/header/STAllHeader.java | 39 - .../model/message/header/ServerHeader.java | 125 -- .../message/header/ServiceTypeHeader.java | 49 - .../message/header/ServiceUSNHeader.java | 50 - .../message/header/SoapActionHeader.java | 58 - .../message/header/SubscriptionIdHeader.java | 42 - .../model/message/header/TimeoutHeader.java | 66 - .../message/header/UDADeviceTypeHeader.java | 48 - .../message/header/UDAServiceTypeHeader.java | 47 - .../cling/model/message/header/UDNHeader.java | 49 - .../message/header/USNRootDeviceHeader.java | 50 - .../model/message/header/UpnpHeader.java | 193 --- .../model/message/header/UserAgentHeader.java | 42 - .../fourthline/cling/model/meta/Action.java | 214 ---- .../cling/model/meta/ActionArgument.java | 164 --- .../fourthline/cling/model/meta/Device.java | 452 ------- .../cling/model/meta/DeviceDetails.java | 218 ---- .../cling/model/meta/DeviceIdentity.java | 95 -- .../org/fourthline/cling/model/meta/Icon.java | 221 ---- .../cling/model/meta/LocalDevice.java | 317 ----- .../cling/model/meta/LocalService.java | 133 -- .../cling/model/meta/ManufacturerDetails.java | 58 - .../cling/model/meta/ModelDetails.java | 79 -- .../model/meta/QueryStateVariableAction.java | 63 - .../cling/model/meta/RemoteDevice.java | 212 ---- .../model/meta/RemoteDeviceIdentity.java | 110 -- .../cling/model/meta/RemoteService.java | 114 -- .../fourthline/cling/model/meta/Service.java | 208 ---- .../cling/model/meta/StateVariable.java | 129 -- .../meta/StateVariableAllowedValueRange.java | 81 -- .../model/meta/StateVariableEventDetails.java | 55 - .../model/meta/StateVariableTypeDetails.java | 136 --- .../cling/model/meta/UDAVersion.java | 73 -- .../cling/model/profile/ClientInfo.java | 55 - .../model/profile/DeviceDetailsProvider.java | 41 - .../profile/HeaderDeviceDetailsProvider.java | 101 -- .../cling/model/profile/RemoteClientInfo.java | 131 -- .../resource/DeviceDescriptorResource.java | 30 - .../cling/model/resource/IconResource.java | 30 - .../cling/model/resource/Resource.java | 115 -- .../resource/ServiceControlResource.java | 30 - .../resource/ServiceDescriptorResource.java | 30 - .../ServiceEventCallbackResource.java | 30 - .../ServiceEventSubscriptionResource.java | 30 - .../state/FieldStateVariableAccessor.java | 53 - .../state/GetterStateVariableAccessor.java | 54 - .../model/state/StateVariableAccessor.java | 59 - .../cling/model/state/StateVariableValue.java | 41 - .../cling/model/types/AbstractDatatype.java | 76 -- .../cling/model/types/Base64Datatype.java | 51 - .../cling/model/types/BinHexDatatype.java | 51 - .../cling/model/types/BooleanDatatype.java | 49 - .../cling/model/types/BytesRange.java | 127 -- .../cling/model/types/CharacterDatatype.java | 36 - .../cling/model/types/CustomDatatype.java | 42 - .../cling/model/types/DLNACaps.java | 70 -- .../fourthline/cling/model/types/DLNADoc.java | 105 -- .../cling/model/types/Datatype.java | 233 ---- .../cling/model/types/DateTimeDatatype.java | 99 -- .../cling/model/types/DeviceType.java | 170 --- .../cling/model/types/DoubleDatatype.java | 40 - .../cling/model/types/ErrorCode.java | 67 - .../cling/model/types/FloatDatatype.java | 40 - .../cling/model/types/HostPort.java | 76 -- .../cling/model/types/IntegerDatatype.java | 89 -- .../model/types/InvalidValueException.java | 32 - .../cling/model/types/NamedDeviceType.java | 83 -- .../cling/model/types/NamedServiceType.java | 83 -- .../model/types/NotificationSubtype.java | 41 - .../cling/model/types/PragmaType.java | 92 -- .../cling/model/types/ServiceId.java | 132 -- .../cling/model/types/ServiceType.java | 192 --- .../cling/model/types/ShortDatatype.java | 42 - .../cling/model/types/SoapActionType.java | 138 --- .../cling/model/types/StringDatatype.java | 31 - .../cling/model/types/UDADeviceType.java | 58 - .../cling/model/types/UDAServiceId.java | 80 -- .../cling/model/types/UDAServiceType.java | 57 - .../org/fourthline/cling/model/types/UDN.java | 148 --- .../cling/model/types/URIDatatype.java | 38 - .../model/types/UnsignedIntegerFourBytes.java | 35 - .../UnsignedIntegerFourBytesDatatype.java | 32 - .../model/types/UnsignedIntegerOneByte.java | 35 - .../types/UnsignedIntegerOneByteDatatype.java | 32 - .../model/types/UnsignedIntegerTwoBytes.java | 35 - .../UnsignedIntegerTwoBytesDatatype.java | 32 - .../model/types/UnsignedVariableInteger.java | 118 -- .../fourthline/cling/model/types/csv/CSV.java | 81 -- .../cling/model/types/csv/CSVBoolean.java | 31 - .../cling/model/types/csv/CSVBytes.java | 31 - .../cling/model/types/csv/CSVCharacter.java | 31 - .../cling/model/types/csv/CSVDate.java | 33 - .../cling/model/types/csv/CSVDouble.java | 31 - .../cling/model/types/csv/CSVFloat.java | 31 - .../cling/model/types/csv/CSVInteger.java | 31 - .../cling/model/types/csv/CSVShort.java | 31 - .../cling/model/types/csv/CSVString.java | 31 - .../cling/model/types/csv/CSVURI.java | 33 - .../csv/CSVUnsignedIntegerFourBytes.java | 32 - .../types/csv/CSVUnsignedIntegerOneByte.java | 32 - .../types/csv/CSVUnsignedIntegerTwoBytes.java | 32 - .../protocol/ProtocolCreationException.java | 32 - .../cling/protocol/ProtocolFactory.java | 119 -- .../cling/protocol/ProtocolFactoryImpl.java | 263 ---- .../cling/protocol/ReceivingAsync.java | 108 -- .../cling/protocol/ReceivingSync.java | 102 -- .../protocol/RetrieveRemoteDescriptors.java | 375 ------ .../cling/protocol/SendingAsync.java | 74 -- .../cling/protocol/SendingSync.java | 64 - .../protocol/async/ReceivingNotification.java | 142 --- .../cling/protocol/async/ReceivingSearch.java | 363 ------ .../async/ReceivingSearchResponse.java | 101 -- .../protocol/async/SendingNotification.java | 182 --- .../async/SendingNotificationAlive.java | 48 - .../async/SendingNotificationByebye.java | 57 - .../cling/protocol/async/SendingSearch.java | 118 -- .../cling/protocol/sync/ReceivingAction.java | 161 --- .../cling/protocol/sync/ReceivingEvent.java | 142 --- .../protocol/sync/ReceivingRetrieval.java | 154 --- .../protocol/sync/ReceivingSubscribe.java | 211 ---- .../protocol/sync/ReceivingUnsubscribe.java | 85 -- .../cling/protocol/sync/SendingAction.java | 189 --- .../cling/protocol/sync/SendingEvent.java | 97 -- .../cling/protocol/sync/SendingRenewal.java | 115 -- .../cling/protocol/sync/SendingSubscribe.java | 158 --- .../protocol/sync/SendingUnsubscribe.java | 90 -- .../registry/DefaultRegistryListener.java | 101 -- .../fourthline/cling/registry/LocalItems.java | 312 ----- .../cling/registry/RegistrationException.java | 47 - .../fourthline/cling/registry/Registry.java | 452 ------- .../cling/registry/RegistryImpl.java | 539 -------- .../cling/registry/RegistryItem.java | 70 -- .../cling/registry/RegistryItems.java | 178 --- .../cling/registry/RegistryListener.java | 143 --- .../cling/registry/RegistryMaintainer.java | 63 - .../cling/registry/RemoteItems.java | 320 ----- .../cling/registry/event/After.java | 33 - .../cling/registry/event/Before.java | 33 - .../cling/registry/event/DeviceDiscovery.java | 36 - .../event/FailedRemoteDeviceDiscovery.java | 35 - .../registry/event/LocalDeviceDiscovery.java | 28 - .../cling/registry/event/Phase.java | 74 -- .../registry/event/RegistryShutdown.java | 22 - .../registry/event/RemoteDeviceDiscovery.java | 28 - .../avtransport/AVTransportErrorCode.java | 65 - .../avtransport/AVTransportException.java | 49 - .../AbstractAVTransportService.java | 383 ------ .../callback/GetCurrentTransportActions.java | 49 - .../callback/GetDeviceCapabilities.java | 50 - .../avtransport/callback/GetMediaInfo.java | 50 - .../avtransport/callback/GetPositionInfo.java | 50 - .../callback/GetTransportInfo.java | 50 - .../support/avtransport/callback/Next.java | 55 - .../support/avtransport/callback/Pause.java | 55 - .../support/avtransport/callback/Play.java | 55 - .../avtransport/callback/Previous.java | 55 - .../support/avtransport/callback/Seek.java | 57 - .../callback/SetAVTransportURI.java | 56 - .../avtransport/callback/SetPlayMode.java | 47 - .../support/avtransport/callback/Stop.java | 46 - .../avtransport/impl/AVTransportService.java | 318 ----- .../impl/AVTransportStateMachine.java | 36 - .../avtransport/impl/state/AbstractState.java | 38 - .../impl/state/NoMediaPresent.java | 61 - .../avtransport/impl/state/PausedPlay.java | 66 - .../avtransport/impl/state/Playing.java | 73 -- .../avtransport/impl/state/Stopped.java | 71 -- .../AVTransportLastChangeParser.java | 55 - .../lastchange/AVTransportVariable.java | 386 ------ ...stractPeeringConnectionManagerService.java | 246 ---- .../ConnectionManagerErrorCode.java | 55 - .../ConnectionManagerException.java | 50 - .../ConnectionManagerService.java | 162 --- .../callback/ConnectionComplete.java | 37 - .../callback/GetCurrentConnectionInfo.java | 70 -- .../callback/GetProtocolInfo.java | 62 - .../callback/PrepareForConnection.java | 61 - .../AbstractContentDirectoryService.java | 290 ----- .../ContentDirectoryErrorCode.java | 51 - .../ContentDirectoryException.java | 51 - .../support/contentdirectory/DIDLParser.java | 1082 ----------------- .../contentdirectory/callback/Browse.java | 149 --- .../callback/GetSystemUpdateID.java | 48 - .../contentdirectory/callback/Search.java | 137 --- .../ui/ContentBrowseActionCallback.java | 166 --- .../ContentBrowseActionCallbackCreator.java | 34 - .../contentdirectory/ui/ContentTree.java | 127 -- .../ui/ContentTreeCellRenderer.java | 88 -- .../ui/ContentTreeExpandListener.java | 67 - .../support/igd/PortMappingListener.java | 194 --- .../support/igd/callback/GetExternalIP.java | 37 - .../support/igd/callback/GetStatusInfo.java | 60 - .../support/igd/callback/PortMappingAdd.java | 53 - .../igd/callback/PortMappingDelete.java | 47 - .../igd/callback/PortMappingEntryGet.java | 33 - .../cling/support/lastchange/Event.java | 94 -- .../support/lastchange/EventedValue.java | 72 -- .../support/lastchange/EventedValueEnum.java | 52 - .../lastchange/EventedValueEnumArray.java | 53 - .../support/lastchange/EventedValueShort.java | 39 - .../lastchange/EventedValueString.java | 40 - .../support/lastchange/EventedValueURI.java | 57 - .../EventedValueUnsignedIntegerFourBytes.java | 40 - .../EventedValueUnsignedIntegerTwoBytes.java | 40 - .../cling/support/lastchange/InstanceID.java | 47 - .../cling/support/lastchange/LastChange.java | 127 -- .../LastChangeAwareServiceManager.java | 107 -- .../lastchange/LastChangeDelegator.java | 40 - .../support/lastchange/LastChangeParser.java | 236 ---- .../cling/support/messagebox/AddMessage.java | 39 - .../support/messagebox/RemoveMessage.java | 39 - .../support/messagebox/model/DateTime.java | 63 - .../messagebox/model/ElementAppender.java | 27 - .../support/messagebox/model/Message.java | 125 -- .../messagebox/model/MessageIncomingCall.java | 62 - .../support/messagebox/model/MessageSMS.java | 71 -- .../model/MessageScheduleReminder.java | 81 -- .../support/messagebox/model/NumberName.java | 45 - .../support/messagebox/parser/MessageDOM.java | 54 - .../messagebox/parser/MessageDOMParser.java | 51 - .../messagebox/parser/MessageElement.java | 64 - .../cling/support/model/AVTransport.java | 98 -- .../cling/support/model/BrowseFlag.java | 46 - .../cling/support/model/BrowseResult.java | 82 -- .../cling/support/model/Channel.java | 35 - .../cling/support/model/Connection.java | 152 --- .../cling/support/model/ConnectionInfo.java | 173 --- .../cling/support/model/DIDLAttribute.java | 55 - .../cling/support/model/DIDLContent.java | 221 ---- .../cling/support/model/DIDLObject.java | 898 -------------- .../cling/support/model/DescMeta.java | 106 -- .../support/model/DeviceCapabilities.java | 73 -- .../cling/support/model/MediaInfo.java | 150 --- .../cling/support/model/Person.java | 54 - .../cling/support/model/PersonWithRole.java | 46 - .../cling/support/model/PlayMode.java | 29 - .../cling/support/model/PortMapping.java | 188 --- .../cling/support/model/PositionInfo.java | 168 --- .../cling/support/model/PresetName.java | 23 - .../cling/support/model/Protocol.java | 56 - .../cling/support/model/ProtocolInfo.java | 112 -- .../cling/support/model/ProtocolInfos.java | 45 - .../model/RecordMediumWriteStatus.java | 38 - .../support/model/RecordQualityMode.java | 69 -- .../fourthline/cling/support/model/Res.java | 196 --- .../cling/support/model/SearchResult.java | 82 -- .../cling/support/model/SeekMode.java | 54 - .../cling/support/model/SortCriterion.java | 75 -- .../cling/support/model/StorageMedium.java | 104 -- .../cling/support/model/TransportAction.java | 50 - .../cling/support/model/TransportInfo.java | 73 -- .../support/model/TransportSettings.java | 45 - .../cling/support/model/TransportState.java | 54 - .../cling/support/model/TransportStatus.java | 49 - .../cling/support/model/VolumeDBRange.java | 38 - .../cling/support/model/WriteStatus.java | 27 - .../cling/support/model/container/Album.java | 154 --- .../support/model/container/Container.java | 162 --- .../model/container/GenreContainer.java | 41 - .../support/model/container/MovieGenre.java | 42 - .../support/model/container/MusicAlbum.java | 160 --- .../support/model/container/MusicArtist.java | 73 -- .../support/model/container/MusicGenre.java | 42 - .../model/container/PersonContainer.java | 52 - .../support/model/container/PhotoAlbum.java | 78 -- .../model/container/PlaylistContainer.java | 180 --- .../model/container/StorageFolder.java | 57 - .../model/container/StorageSystem.java | 102 -- .../model/container/StorageVolume.java | 91 -- .../support/model/dlna/DLNAAttribute.java | 149 --- .../model/dlna/DLNAConversionIndicator.java | 48 - .../DLNAConversionIndicatorAttribute.java | 45 - .../cling/support/model/dlna/DLNAFlags.java | 72 -- .../model/dlna/DLNAFlagsAttribute.java | 67 - .../support/model/dlna/DLNAOperations.java | 53 - .../model/dlna/DLNAOperationsAttribute.java | 67 - .../model/dlna/DLNAPlaySpeedAttribute.java | 74 -- .../model/dlna/DLNAProfileAttribute.java | 41 - .../support/model/dlna/DLNAProfiles.java | 417 ------- .../support/model/dlna/DLNAProtocolInfo.java | 117 -- ...InvalidDLNAProtocolAttributeException.java | 29 - .../model/dlna/message/DLNAHeaders.java | 179 --- .../message/header/AvailableRangeHeader.java | 43 - .../header/AvailableSeekRangeHeader.java | 97 -- .../message/header/BufferBytesHeader.java | 43 - .../dlna/message/header/BufferInfoHeader.java | 43 - .../message/header/ContentFeaturesHeader.java | 58 - .../model/dlna/message/header/DLNAHeader.java | 150 --- .../dlna/message/header/EventTypeHeader.java | 44 - .../message/header/FriendlyNameHeader.java | 45 - .../header/GetAvailableSeekRangeHeader.java | 44 - .../header/GetContentFeaturesHeader.java | 44 - .../dlna/message/header/MaxPrateHeader.java | 42 - .../message/header/PeerManagerHeader.java | 47 - .../dlna/message/header/PlaySpeedHeader.java | 49 - .../dlna/message/header/PragmaHeader.java | 60 - .../message/header/RealTimeInfoHeader.java | 49 - .../model/dlna/message/header/SCIDHeader.java | 41 - .../dlna/message/header/ScmsFlagHeader.java | 45 - .../dlna/message/header/SupportedHeader.java | 48 - .../message/header/TimeSeekRangeHeader.java | 62 - .../message/header/TransferModeHeader.java | 53 - .../model/dlna/message/header/WCTHeader.java | 44 - .../dlna/types/AvailableSeekRangeType.java | 73 -- .../model/dlna/types/BufferInfoType.java | 113 -- .../model/dlna/types/CodedDataBuffer.java | 50 - .../model/dlna/types/NormalPlayTime.java | 125 -- .../model/dlna/types/NormalPlayTimeRange.java | 122 -- .../model/dlna/types/ScmsFlagType.java | 49 - .../model/dlna/types/TimeSeekRangeType.java | 60 - .../cling/support/model/item/AudioBook.java | 114 -- .../support/model/item/AudioBroadcast.java | 86 -- .../cling/support/model/item/AudioItem.java | 150 --- .../cling/support/model/item/ImageItem.java | 133 -- .../cling/support/model/item/Item.java | 74 -- .../cling/support/model/item/Movie.java | 111 -- .../cling/support/model/item/MusicTrack.java | 152 --- .../support/model/item/MusicVideoClip.java | 149 --- .../cling/support/model/item/Photo.java | 59 - .../support/model/item/PlaylistItem.java | 134 -- .../cling/support/model/item/TextItem.java | 196 --- .../support/model/item/VideoBroadcast.java | 75 -- .../cling/support/model/item/VideoItem.java | 194 --- .../AbstractAudioRenderingControl.java | 226 ---- .../RenderingControlErrorCode.java | 50 - .../RenderingControlException.java | 49 - .../renderingcontrol/callback/GetMute.java | 49 - .../renderingcontrol/callback/GetVolume.java | 63 - .../renderingcontrol/callback/SetMute.java | 50 - .../renderingcontrol/callback/SetVolume.java | 51 - .../lastchange/ChannelLoudness.java | 45 - .../lastchange/ChannelMute.java | 45 - .../lastchange/ChannelVolume.java | 45 - .../lastchange/ChannelVolumeDB.java | 45 - .../EventedValueChannelLoudness.java | 76 -- .../lastchange/EventedValueChannelMute.java | 76 -- .../lastchange/EventedValueChannelVolume.java | 81 -- .../EventedValueChannelVolumeDB.java | 81 -- .../RenderingControlLastChangeParser.java | 55 - .../lastchange/RenderingControlVariable.java | 222 ---- .../support/shared/AWTExceptionHandler.java | 30 - .../cling/support/shared/AbstractMap.java | 506 -------- .../cling/support/shared/CenterWindow.java | 34 - .../support/shared/CoreLogCategories.java | 163 --- .../fourthline/cling/support/shared/Main.java | 170 --- .../cling/support/shared/MainController.java | 147 --- .../support/shared/NewPlatformApple.java | 81 -- .../cling/support/shared/PlatformApple.java | 85 -- .../cling/support/shared/ShutdownHandler.java | 24 - .../cling/support/shared/TextExpand.java | 32 - .../support/shared/TextExpandDialog.java | 75 -- .../cling/support/shared/TextExpandEvent.java | 26 - .../fourthline/cling/support/shared/View.java | 29 - .../cling/support/shared/log/LogView.java | 44 - .../support/shared/log/impl/LogPresenter.java | 67 - .../support/shared/log/impl/LogViewImpl.java | 319 ----- ...AbstractMediaReceiverRegistrarService.java | 140 --- .../cling/transport/DisableRouter.java | 22 - .../cling/transport/EnableRouter.java | 22 - .../fourthline/cling/transport/Router.java | 161 --- .../cling/transport/RouterException.java | 47 - .../cling/transport/RouterImpl.java | 525 -------- ...cServletStreamServerConfigurationImpl.java | 89 -- .../impl/AsyncServletStreamServerImpl.java | 203 ---- .../impl/AsyncServletUpnpStream.java | 260 ---- .../impl/DatagramIOConfigurationImpl.java | 56 - .../cling/transport/impl/DatagramIOImpl.java | 168 --- .../transport/impl/DatagramProcessorImpl.java | 163 --- .../impl/FixedSunURLStreamHandler.java | 108 -- .../impl/GENAEventProcessorImpl.java | 220 ---- .../impl/HttpExchangeUpnpStream.java | 185 --- .../MulticastReceiverConfigurationImpl.java | 82 -- .../transport/impl/MulticastReceiverImpl.java | 153 --- .../impl/NetworkAddressFactoryImpl.java | 513 -------- .../impl/PullGENAEventProcessorImpl.java | 96 -- .../impl/PullSOAPActionProcessorImpl.java | 221 ---- .../RecoveringGENAEventProcessorImpl.java | 131 -- .../RecoveringSOAPActionProcessorImpl.java | 135 -- .../impl/SOAPActionProcessorImpl.java | 632 ---------- .../impl/StreamClientConfigurationImpl.java | 50 - .../transport/impl/StreamClientImpl.java | 300 ----- .../impl/StreamServerConfigurationImpl.java | 60 - .../transport/impl/StreamServerImpl.java | 154 --- .../impl/jetty/JettyServletContainer.java | 198 --- .../jetty/StreamClientConfigurationImpl.java | 44 - .../impl/jetty/StreamClientImpl.java | 333 ----- .../transport/spi/AbstractStreamClient.java | 131 -- .../AbstractStreamClientConfiguration.java | 81 -- .../cling/transport/spi/DatagramIO.java | 90 -- .../spi/DatagramIOConfiguration.java | 35 - .../transport/spi/DatagramProcessor.java | 65 - .../transport/spi/GENAEventProcessor.java | 45 - .../spi/InitializationException.java | 37 - .../transport/spi/MulticastReceiver.java | 70 -- .../spi/MulticastReceiverConfiguration.java | 42 - .../transport/spi/NetworkAddressFactory.java | 114 -- .../transport/spi/NoNetworkException.java | 29 - .../transport/spi/SOAPActionProcessor.java | 72 -- .../spi/ServletContainerAdapter.java | 91 -- .../cling/transport/spi/StreamClient.java | 82 -- .../spi/StreamClientConfiguration.java | 55 - .../cling/transport/spi/StreamServer.java | 102 -- .../spi/StreamServerConfiguration.java | 30 - .../cling/transport/spi/UpnpStream.java | 120 -- clinglibrary/src/main/res/values/strings.xml | 3 - .../zane/clinglibrary/ExampleUnitTest.java | 17 - .../dkplayer_dlna_connected_change_device.png | Bin 6824 -> 0 bytes .../dkplayer_dlna_connected_exit.png | Bin 9493 -> 0 bytes .../dkplayer_dlna_connected_tv_bg.png | Bin 170783 -> 0 bytes .../res/drawable-xhdpi/dkplayer_icon_dlna.png | Bin 1157 -> 0 bytes .../dkplayer_dlna_connected_change_device.png | Bin 11201 -> 0 bytes .../dkplayer_dlna_connected_exit.png | Bin 15356 -> 0 bytes other/module-lite.sh | 270 ---- other/test.ffconcat | 7 - .../videoplayer/widget/DanmakuVideoView.java | 4 + .../widget/controller/DanmakuController.java | 3 + 570 files changed, 7 insertions(+), 57227 deletions(-) delete mode 100644 clinglibrary/.gitignore delete mode 100644 clinglibrary/build.gradle delete mode 100644 clinglibrary/proguard-rules.pro delete mode 100644 clinglibrary/src/androidTest/java/com/zane/clinglibrary/ExampleInstrumentedTest.java delete mode 100644 clinglibrary/src/main/AndroidManifest.xml delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/DefaultUpnpServiceConfiguration.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/Main.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/ManagedUpnpService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/ManagedUpnpServiceConfiguration.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/UpnpService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/UpnpServiceConfiguration.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/UpnpServiceImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/android/AndroidNetworkAddressFactory.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/android/AndroidRouter.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpServiceConfiguration.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpServiceImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/android/FixedAndroidLogHandler.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/android/NetworkUtils.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/AllowedValueProvider.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/AllowedValueRangeProvider.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/LocalServiceBinder.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/LocalServiceBindingException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationActionBinder.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationLocalServiceBinder.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationStateVariableBinder.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpAction.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpInputArgument.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpOutputArgument.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpServiceId.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpServiceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpStateVariable.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpStateVariables.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableAction.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableActionArgument.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableAllowedValueRange.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableDevice.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableIcon.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableStateVariable.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableUDAVersion.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/xml/Descriptor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/xml/DescriptorBindingException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/xml/DeviceDescriptorBinder.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/xml/RecoveringUDA10DeviceDescriptorBinderImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/xml/ServiceDescriptorBinder.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10DeviceDescriptorBinderImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10DeviceDescriptorBinderSAXImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10ServiceDescriptorBinderImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10ServiceDescriptorBinderSAXImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ActionCallback.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ControlPoint.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ControlPointImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/controlpoint/SubscriptionCallback.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/controlpoint/event/ExecuteAction.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/controlpoint/event/Search.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/mock/MockProtocolFactory.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/mock/MockRouter.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/mock/MockUpnpService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/mock/MockUpnpServiceConfiguration.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/Command.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/Constants.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/DefaultServiceManager.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/DiscoveryOptions.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/ExpirationDetails.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/Location.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/ModelUtil.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/Namespace.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/NetworkAddress.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/ServerClientTokens.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/ServiceManager.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/ServiceReference.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/UnsupportedDataException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/UserConstants.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/Validatable.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/ValidationError.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/ValidationException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/VariableValue.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/XMLUtil.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/action/AbstractActionExecutor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionArgumentValue.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionCancelledException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionExecutor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionInvocation.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/action/MethodActionExecutor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/action/QueryStateVariableExecutor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/action/RemoteActionInvocation.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/gena/CancelReason.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/gena/GENASubscription.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/gena/LocalGENASubscription.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/gena/RemoteGENASubscription.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/Connection.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/IncomingDatagramMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/OutgoingDatagramMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/StreamRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/StreamResponseMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpHeaders.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpOperation.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpRequest.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpResponse.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionResponseMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/control/IncomingActionRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/control/IncomingActionResponseMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/control/OutgoingActionRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/control/OutgoingActionResponseMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingNotificationRequest.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingSearchRequest.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingSearchResponse.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequest.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestDeviceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestRootDevice.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestServiceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestUDN.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchRequest.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponse.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseDeviceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseRootDevice.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseServiceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseUDN.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingEventRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingSubscribeRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingSubscribeResponseMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingUnsubscribeRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingEventRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingEventResponseMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingRenewalRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingSubscribeRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingSubscribeResponseMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingUnsubscribeRequestMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/AVClientInfoHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/CallbackHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ContentRangeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ContentTypeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/DeviceTypeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/DeviceUSNHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/EXTHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/EventSequenceHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/HostHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/InterfaceMacHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/InvalidHeaderException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/LocationHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MANHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MXHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MaxAgeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/NTEventHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/NTSHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/PragmaHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/RangeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/RootDeviceHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/STAllHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServerHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServiceTypeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServiceUSNHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/SoapActionHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/SubscriptionIdHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/TimeoutHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDADeviceTypeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDAServiceTypeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDNHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/USNRootDeviceHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UpnpHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UserAgentHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/Action.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/ActionArgument.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/Device.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/DeviceDetails.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/DeviceIdentity.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/Icon.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/LocalDevice.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/LocalService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/ManufacturerDetails.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/ModelDetails.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/QueryStateVariableAction.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteDevice.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteDeviceIdentity.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/Service.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariable.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableAllowedValueRange.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableEventDetails.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableTypeDetails.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/meta/UDAVersion.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/profile/ClientInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/profile/DeviceDetailsProvider.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/profile/HeaderDeviceDetailsProvider.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/profile/RemoteClientInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/resource/DeviceDescriptorResource.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/resource/IconResource.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/resource/Resource.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceControlResource.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceDescriptorResource.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceEventCallbackResource.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceEventSubscriptionResource.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/state/FieldStateVariableAccessor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/state/GetterStateVariableAccessor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/state/StateVariableAccessor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/state/StateVariableValue.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/AbstractDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/Base64Datatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/BinHexDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/BooleanDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/BytesRange.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/CharacterDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/CustomDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/DLNACaps.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/DLNADoc.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/Datatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/DateTimeDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/DeviceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/DoubleDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/ErrorCode.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/FloatDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/HostPort.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/IntegerDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/InvalidValueException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/NamedDeviceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/NamedServiceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/NotificationSubtype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/PragmaType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/ServiceId.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/ServiceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/ShortDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/SoapActionType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/StringDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UDADeviceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UDAServiceId.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UDAServiceType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UDN.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/URIDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerFourBytes.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerFourBytesDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerOneByte.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerOneByteDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerTwoBytes.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerTwoBytesDatatype.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedVariableInteger.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSV.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVBoolean.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVBytes.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVCharacter.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVDate.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVDouble.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVFloat.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVInteger.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVShort.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVString.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVURI.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerFourBytes.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerOneByte.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerTwoBytes.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolCreationException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolFactory.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolFactoryImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/ReceivingAsync.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/ReceivingSync.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/RetrieveRemoteDescriptors.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/SendingAsync.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/SendingSync.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingNotification.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingSearch.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingSearchResponse.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotification.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotificationAlive.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotificationByebye.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingSearch.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingAction.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingEvent.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingRetrieval.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingSubscribe.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingUnsubscribe.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingAction.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingEvent.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingRenewal.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingSubscribe.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingUnsubscribe.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/DefaultRegistryListener.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/LocalItems.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/RegistrationException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/Registry.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryItem.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryItems.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryListener.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryMaintainer.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/RemoteItems.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/event/After.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/event/Before.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/event/DeviceDiscovery.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/event/FailedRemoteDeviceDiscovery.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/event/LocalDeviceDiscovery.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/event/Phase.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/event/RegistryShutdown.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/registry/event/RemoteDeviceDiscovery.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AVTransportErrorCode.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AVTransportException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AbstractAVTransportService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetCurrentTransportActions.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetDeviceCapabilities.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetMediaInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetPositionInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetTransportInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Next.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Pause.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Play.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Previous.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Seek.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/SetAVTransportURI.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/SetPlayMode.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Stop.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/AVTransportService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/AVTransportStateMachine.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/AbstractState.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/NoMediaPresent.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/PausedPlay.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/Playing.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/Stopped.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/lastchange/AVTransportLastChangeParser.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/lastchange/AVTransportVariable.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/AbstractPeeringConnectionManagerService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerErrorCode.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/ConnectionComplete.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/GetCurrentConnectionInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/GetProtocolInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/PrepareForConnection.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/AbstractContentDirectoryService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ContentDirectoryErrorCode.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ContentDirectoryException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/DIDLParser.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/Browse.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/GetSystemUpdateID.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/Search.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentBrowseActionCallback.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentBrowseActionCallbackCreator.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTree.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTreeCellRenderer.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTreeExpandListener.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/igd/PortMappingListener.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/GetExternalIP.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/GetStatusInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingAdd.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingDelete.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingEntryGet.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/Event.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValue.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueEnum.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueEnumArray.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueShort.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueString.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueURI.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueUnsignedIntegerFourBytes.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueUnsignedIntegerTwoBytes.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/InstanceID.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChange.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeAwareServiceManager.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeDelegator.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeParser.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/AddMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/RemoveMessage.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/DateTime.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/ElementAppender.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/Message.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageIncomingCall.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageSMS.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageScheduleReminder.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/NumberName.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageDOM.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageDOMParser.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageElement.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/AVTransport.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/BrowseFlag.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/BrowseResult.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/Channel.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/Connection.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/ConnectionInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLAttribute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLContent.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLObject.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/DescMeta.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/DeviceCapabilities.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/MediaInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/Person.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/PersonWithRole.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/PlayMode.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/PortMapping.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/PositionInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/PresetName.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/Protocol.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/ProtocolInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/ProtocolInfos.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/RecordMediumWriteStatus.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/RecordQualityMode.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/Res.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/SearchResult.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/SeekMode.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/SortCriterion.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/StorageMedium.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportAction.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportSettings.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportState.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportStatus.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/VolumeDBRange.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/WriteStatus.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/Album.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/Container.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/GenreContainer.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MovieGenre.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicAlbum.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicArtist.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicGenre.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PersonContainer.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PhotoAlbum.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PlaylistContainer.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageFolder.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageSystem.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageVolume.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAAttribute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAConversionIndicator.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAConversionIndicatorAttribute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAFlags.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAFlagsAttribute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAOperations.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAOperationsAttribute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAPlaySpeedAttribute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProfileAttribute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProfiles.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProtocolInfo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/InvalidDLNAProtocolAttributeException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/DLNAHeaders.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/AvailableRangeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/AvailableSeekRangeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/BufferBytesHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/BufferInfoHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/ContentFeaturesHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/DLNAHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/EventTypeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/FriendlyNameHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/GetAvailableSeekRangeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/GetContentFeaturesHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/MaxPrateHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PeerManagerHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PlaySpeedHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PragmaHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/RealTimeInfoHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/SCIDHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/ScmsFlagHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/SupportedHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/TimeSeekRangeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/TransferModeHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/WCTHeader.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/AvailableSeekRangeType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/BufferInfoType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/CodedDataBuffer.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/NormalPlayTime.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/NormalPlayTimeRange.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/ScmsFlagType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/TimeSeekRangeType.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioBook.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioBroadcast.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioItem.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/ImageItem.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Item.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Movie.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/MusicTrack.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/MusicVideoClip.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Photo.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/PlaylistItem.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/TextItem.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/VideoBroadcast.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/model/item/VideoItem.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/AbstractAudioRenderingControl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/RenderingControlErrorCode.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/RenderingControlException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/GetMute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/GetVolume.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/SetMute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/SetVolume.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelLoudness.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelMute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelVolume.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelVolumeDB.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelLoudness.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelMute.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelVolume.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelVolumeDB.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/RenderingControlLastChangeParser.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/RenderingControlVariable.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/AWTExceptionHandler.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/AbstractMap.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/CenterWindow.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/CoreLogCategories.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/Main.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/MainController.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/NewPlatformApple.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/PlatformApple.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/ShutdownHandler.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpand.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpandDialog.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpandEvent.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/View.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/LogView.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/impl/LogPresenter.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/impl/LogViewImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/support/xmicrosoft/AbstractMediaReceiverRegistrarService.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/DisableRouter.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/EnableRouter.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/Router.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/RouterException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/RouterImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletStreamServerConfigurationImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletStreamServerImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletUpnpStream.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramIOConfigurationImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramIOImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramProcessorImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/FixedSunURLStreamHandler.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/GENAEventProcessorImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/HttpExchangeUpnpStream.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/MulticastReceiverConfigurationImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/MulticastReceiverImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/NetworkAddressFactoryImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/PullGENAEventProcessorImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/PullSOAPActionProcessorImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/RecoveringGENAEventProcessorImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/RecoveringSOAPActionProcessorImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/SOAPActionProcessorImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamClientConfigurationImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamClientImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamServerConfigurationImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamServerImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/JettyServletContainer.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/StreamClientConfigurationImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/StreamClientImpl.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/AbstractStreamClient.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/AbstractStreamClientConfiguration.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramIO.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramIOConfiguration.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramProcessor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/GENAEventProcessor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/InitializationException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/MulticastReceiver.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/MulticastReceiverConfiguration.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/NetworkAddressFactory.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/NoNetworkException.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/SOAPActionProcessor.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/ServletContainerAdapter.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamClient.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamClientConfiguration.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamServer.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamServerConfiguration.java delete mode 100644 clinglibrary/src/main/java/org/fourthline/cling/transport/spi/UpnpStream.java delete mode 100644 clinglibrary/src/main/res/values/strings.xml delete mode 100644 clinglibrary/src/test/java/com/zane/clinglibrary/ExampleUnitTest.java delete mode 100644 dkplayer-java/src/main/res/drawable-xhdpi/dkplayer_dlna_connected_change_device.png delete mode 100644 dkplayer-java/src/main/res/drawable-xhdpi/dkplayer_dlna_connected_exit.png delete mode 100644 dkplayer-java/src/main/res/drawable-xhdpi/dkplayer_dlna_connected_tv_bg.png delete mode 100644 dkplayer-java/src/main/res/drawable-xhdpi/dkplayer_icon_dlna.png delete mode 100644 dkplayer-java/src/main/res/drawable-xxhdpi/dkplayer_dlna_connected_change_device.png delete mode 100644 dkplayer-java/src/main/res/drawable-xxhdpi/dkplayer_dlna_connected_exit.png delete mode 100644 other/module-lite.sh delete mode 100644 other/test.ffconcat diff --git a/clinglibrary/.gitignore b/clinglibrary/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/clinglibrary/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/clinglibrary/build.gradle b/clinglibrary/build.gradle deleted file mode 100644 index 06ae33b..0000000 --- a/clinglibrary/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 27 - buildToolsVersion "26.0.2" - - defaultConfig { - minSdkVersion 14 - targetSdkVersion 26 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { - exclude group: 'com.android.support', module: 'support-annotations' - }) - compile 'com.android.support:appcompat-v7:25.3.1' - testCompile 'junit:junit:4.12' -} diff --git a/clinglibrary/proguard-rules.pro b/clinglibrary/proguard-rules.pro deleted file mode 100644 index 7edc23c..0000000 --- a/clinglibrary/proguard-rules.pro +++ /dev/null @@ -1,25 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /Users/brian/WorkSpace/Android/SDK/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/clinglibrary/src/androidTest/java/com/zane/clinglibrary/ExampleInstrumentedTest.java b/clinglibrary/src/androidTest/java/com/zane/clinglibrary/ExampleInstrumentedTest.java deleted file mode 100644 index 2c0ca31..0000000 --- a/clinglibrary/src/androidTest/java/com/zane/clinglibrary/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.zane.clinglibrary; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumentation test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.zane.clinglibrary.test", appContext.getPackageName()); - } -} diff --git a/clinglibrary/src/main/AndroidManifest.xml b/clinglibrary/src/main/AndroidManifest.xml deleted file mode 100644 index ef65f66..0000000 --- a/clinglibrary/src/main/AndroidManifest.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/DefaultUpnpServiceConfiguration.java b/clinglibrary/src/main/java/org/fourthline/cling/DefaultUpnpServiceConfiguration.java deleted file mode 100644 index e894aa6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/DefaultUpnpServiceConfiguration.java +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling; - -import org.fourthline.cling.binding.xml.DeviceDescriptorBinder; -import org.fourthline.cling.binding.xml.ServiceDescriptorBinder; -import org.fourthline.cling.binding.xml.UDA10DeviceDescriptorBinderImpl; -import org.fourthline.cling.binding.xml.UDA10ServiceDescriptorBinderImpl; -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.meta.RemoteDeviceIdentity; -import org.fourthline.cling.model.meta.RemoteService; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.transport.impl.DatagramIOConfigurationImpl; -import org.fourthline.cling.transport.impl.DatagramIOImpl; -import org.fourthline.cling.transport.impl.DatagramProcessorImpl; -import org.fourthline.cling.transport.impl.GENAEventProcessorImpl; -import org.fourthline.cling.transport.impl.MulticastReceiverConfigurationImpl; -import org.fourthline.cling.transport.impl.MulticastReceiverImpl; -import org.fourthline.cling.transport.impl.NetworkAddressFactoryImpl; -import org.fourthline.cling.transport.impl.SOAPActionProcessorImpl; -import org.fourthline.cling.transport.impl.StreamClientConfigurationImpl; -import org.fourthline.cling.transport.impl.StreamClientImpl; -import org.fourthline.cling.transport.impl.StreamServerConfigurationImpl; -import org.fourthline.cling.transport.impl.StreamServerImpl; -import org.fourthline.cling.transport.spi.DatagramIO; -import org.fourthline.cling.transport.spi.DatagramProcessor; -import org.fourthline.cling.transport.spi.GENAEventProcessor; -import org.fourthline.cling.transport.spi.MulticastReceiver; -import org.fourthline.cling.transport.spi.NetworkAddressFactory; -import org.fourthline.cling.transport.spi.SOAPActionProcessor; -import org.fourthline.cling.transport.spi.StreamClient; -import org.fourthline.cling.transport.spi.StreamServer; -import org.seamless.util.Exceptions; - -import javax.enterprise.inject.Alternative; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Logger; - -/** - * Default configuration data of a typical UPnP stack. - *

- * This configuration utilizes the default network transport implementation found in - * {@link org.fourthline.cling.transport.impl}. - *

- *

- * This configuration utilizes the DOM default descriptor binders found in - * {@link org.fourthline.cling.binding.xml}. - *

- *

- * The thread Executor is an Executors.newCachedThreadPool() with - * a custom {@link ClingThreadFactory} (it only sets a thread name). - *

- *

- * Note that this pool is effectively unlimited, so the number of threads will - * grow (and shrink) as needed - or restricted by your JVM. - *

- *

- * The default {@link org.fourthline.cling.model.Namespace} is configured without any - * base path or prefix. - *

- * - * @author Christian Bauer - */ -@Alternative -public class DefaultUpnpServiceConfiguration implements UpnpServiceConfiguration { - - private static Logger log = Logger.getLogger(DefaultUpnpServiceConfiguration.class.getName()); - - final private int streamListenPort; - - final private ExecutorService defaultExecutorService; - - final private DatagramProcessor datagramProcessor; - final private SOAPActionProcessor soapActionProcessor; - final private GENAEventProcessor genaEventProcessor; - - final private DeviceDescriptorBinder deviceDescriptorBinderUDA10; - final private ServiceDescriptorBinder serviceDescriptorBinderUDA10; - - final private Namespace namespace; - - /** - * Defaults to port '0', ephemeral. - */ - public DefaultUpnpServiceConfiguration() { - this(NetworkAddressFactoryImpl.DEFAULT_TCP_HTTP_LISTEN_PORT); - } - - public DefaultUpnpServiceConfiguration(int streamListenPort) { - this(streamListenPort, true); - } - - protected DefaultUpnpServiceConfiguration(boolean checkRuntime) { - this(NetworkAddressFactoryImpl.DEFAULT_TCP_HTTP_LISTEN_PORT, checkRuntime); - } - - protected DefaultUpnpServiceConfiguration(int streamListenPort, boolean checkRuntime) { - if (checkRuntime && ModelUtil.ANDROID_RUNTIME) { - throw new Error("Unsupported runtime environment, use org.fourthline.cling.android.AndroidUpnpServiceConfiguration"); - } - - this.streamListenPort = streamListenPort; - - defaultExecutorService = createDefaultExecutorService(); - - datagramProcessor = createDatagramProcessor(); - soapActionProcessor = createSOAPActionProcessor(); - genaEventProcessor = createGENAEventProcessor(); - - deviceDescriptorBinderUDA10 = createDeviceDescriptorBinderUDA10(); - serviceDescriptorBinderUDA10 = createServiceDescriptorBinderUDA10(); - - namespace = createNamespace(); - } - - public DatagramProcessor getDatagramProcessor() { - return datagramProcessor; - } - - public SOAPActionProcessor getSoapActionProcessor() { - return soapActionProcessor; - } - - public GENAEventProcessor getGenaEventProcessor() { - return genaEventProcessor; - } - - public StreamClient createStreamClient() { - return new StreamClientImpl( - new StreamClientConfigurationImpl( - getSyncProtocolExecutorService() - ) - ); - } - - public MulticastReceiver createMulticastReceiver(NetworkAddressFactory networkAddressFactory) { - return new MulticastReceiverImpl( - new MulticastReceiverConfigurationImpl( - networkAddressFactory.getMulticastGroup(), - networkAddressFactory.getMulticastPort() - ) - ); - } - - public DatagramIO createDatagramIO(NetworkAddressFactory networkAddressFactory) { - return new DatagramIOImpl(new DatagramIOConfigurationImpl()); - } - - public StreamServer createStreamServer(NetworkAddressFactory networkAddressFactory) { - return new StreamServerImpl( - new StreamServerConfigurationImpl( - networkAddressFactory.getStreamListenPort() - ) - ); - } - - public Executor getMulticastReceiverExecutor() { - return getDefaultExecutorService(); - } - - public Executor getDatagramIOExecutor() { - return getDefaultExecutorService(); - } - - public ExecutorService getStreamServerExecutorService() { - return getDefaultExecutorService(); - } - - public DeviceDescriptorBinder getDeviceDescriptorBinderUDA10() { - return deviceDescriptorBinderUDA10; - } - - public ServiceDescriptorBinder getServiceDescriptorBinderUDA10() { - return serviceDescriptorBinderUDA10; - } - - public ServiceType[] getExclusiveServiceTypes() { - return new ServiceType[0]; - } - - /** - * @return Defaults to false. - */ - public boolean isReceivedSubscriptionTimeoutIgnored() { - return false; - } - - public UpnpHeaders getDescriptorRetrievalHeaders(RemoteDeviceIdentity identity) { - return null; - } - - public UpnpHeaders getEventSubscriptionHeaders(RemoteService service) { - return null; - } - - /** - * @return Defaults to 1000 milliseconds. - */ - public int getRegistryMaintenanceIntervalMillis() { - return 1000; - } - - /** - * @return Defaults to zero, disabling ALIVE flooding. - */ - public int getAliveIntervalMillis() { - return 0; - } - - public Integer getRemoteDeviceMaxAgeSeconds() { - return null; - } - - public Executor getAsyncProtocolExecutor() { - return getDefaultExecutorService(); - } - - public ExecutorService getSyncProtocolExecutorService() { - return getDefaultExecutorService(); - } - - public Namespace getNamespace() { - return namespace; - } - - public Executor getRegistryMaintainerExecutor() { - return getDefaultExecutorService(); - } - - public Executor getRegistryListenerExecutor() { - return getDefaultExecutorService(); - } - - public NetworkAddressFactory createNetworkAddressFactory() { - return createNetworkAddressFactory(streamListenPort); - } - - public void shutdown() { - log.fine("Shutting down default executor service"); - getDefaultExecutorService().shutdownNow(); - } - - protected NetworkAddressFactory createNetworkAddressFactory(int streamListenPort) { - return new NetworkAddressFactoryImpl(streamListenPort); - } - - protected DatagramProcessor createDatagramProcessor() { - return new DatagramProcessorImpl(); - } - - protected SOAPActionProcessor createSOAPActionProcessor() { - return new SOAPActionProcessorImpl(); - } - - protected GENAEventProcessor createGENAEventProcessor() { - return new GENAEventProcessorImpl(); - } - - protected DeviceDescriptorBinder createDeviceDescriptorBinderUDA10() { - return new UDA10DeviceDescriptorBinderImpl(); - } - - protected ServiceDescriptorBinder createServiceDescriptorBinderUDA10() { - return new UDA10ServiceDescriptorBinderImpl(); - } - - protected Namespace createNamespace() { - return new Namespace(); - } - - protected ExecutorService getDefaultExecutorService() { - return defaultExecutorService; - } - - protected ExecutorService createDefaultExecutorService() { - return new ClingExecutor(); - } - - public static class ClingExecutor extends ThreadPoolExecutor { - - public ClingExecutor() { - this(new ClingThreadFactory(), - new ThreadPoolExecutor.DiscardPolicy() { - // The pool is unbounded but rejections will happen during shutdown - @Override - public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) { - // Log and discard - log.info("Thread pool rejected execution of " + runnable.getClass()); - super.rejectedExecution(runnable, threadPoolExecutor); - } - } - ); - } - - public ClingExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedHandler) { - // This is the same as Executors.newCachedThreadPool - super(0, - Integer.MAX_VALUE, - 60L, - TimeUnit.SECONDS, - new SynchronousQueue(), - threadFactory, - rejectedHandler - ); - } - - @Override - protected void afterExecute(Runnable runnable, Throwable throwable) { - super.afterExecute(runnable, throwable); - if (throwable != null) { - Throwable cause = Exceptions.unwrap(throwable); - if (cause instanceof InterruptedException) { - // Ignore this, might happen when we shutdownNow() the executor. We can't - // log at this point as the logging system might be stopped already (e.g. - // if it's a CDI component). - return; - } - // Log only - log.warning("Thread terminated " + runnable + " abruptly with exception: " + throwable); - log.warning("Root cause: " + cause); - } - } - } - - // Executors.DefaultThreadFactory is package visibility (...no touching, you unworthy JDK user!) - public static class ClingThreadFactory implements ThreadFactory { - - protected final ThreadGroup group; - protected final AtomicInteger threadNumber = new AtomicInteger(1); - protected final String namePrefix = "cling-"; - - public ClingThreadFactory() { - SecurityManager s = System.getSecurityManager(); - group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); - } - - public Thread newThread(Runnable r) { - Thread t = new Thread( - group, r, - namePrefix + threadNumber.getAndIncrement(), - 0 - ); - if (t.isDaemon()) - t.setDaemon(false); - if (t.getPriority() != Thread.NORM_PRIORITY) - t.setPriority(Thread.NORM_PRIORITY); - - return t; - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/Main.java b/clinglibrary/src/main/java/org/fourthline/cling/Main.java deleted file mode 100644 index 394d89a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/Main.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling; - -import org.fourthline.cling.model.message.header.STAllHeader; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.meta.RemoteDevice; -import org.fourthline.cling.registry.Registry; -import org.fourthline.cling.registry.RegistryListener; - -/** - * Runs a simple UPnP discovery procedure. - */ -public class Main { - - public static void main(String[] args) throws Exception { - - // UPnP discovery is asynchronous, we need a callback - RegistryListener listener = new RegistryListener() { - - public void remoteDeviceDiscoveryStarted(Registry registry, - RemoteDevice device) { - System.out.println( - "Discovery started: " + device.getDisplayString() - ); - } - - public void remoteDeviceDiscoveryFailed(Registry registry, RemoteDevice device, Exception ex) { - System.out.println( - "Discovery failed: " + device.getDisplayString() + " => " + ex - ); - } - - public void remoteDeviceAdded(Registry registry, RemoteDevice device) { - System.out.println( - "Remote device available: " + device.getDisplayString() - ); - } - - public void remoteDeviceUpdated(Registry registry, RemoteDevice device) { - System.out.println( - "Remote device updated: " + device.getDisplayString() - ); - } - - public void remoteDeviceRemoved(Registry registry, RemoteDevice device) { - System.out.println( - "Remote device removed: " + device.getDisplayString() - ); - } - - public void localDeviceAdded(Registry registry, LocalDevice device) { - System.out.println( - "Local device added: " + device.getDisplayString() - ); - } - - public void localDeviceRemoved(Registry registry, LocalDevice device) { - System.out.println( - "Local device removed: " + device.getDisplayString() - ); - } - - public void beforeShutdown(Registry registry) { - System.out.println( - "Before shutdown, the registry has devices: " + registry.getDevices().size() - ); - } - - public void afterShutdown() { - System.out.println("Shutdown of registry complete!"); - - } - }; - - // This will create necessary network resources for UPnP right away - System.out.println("Starting Cling..."); - UpnpService upnpService = new UpnpServiceImpl(listener); - - // Send a search message to all devices and services, they should respond soon - System.out.println("Sending SEARCH message to all devices..."); - upnpService.getControlPoint().search(new STAllHeader()); - - // Let's wait 10 seconds for them to respond - System.out.println("Waiting 10 seconds before shutting down..."); - Thread.sleep(10000); - - // Release all resources and advertise BYEBYE to other UPnP devices - System.out.println("Stopping Cling..."); - upnpService.shutdown(); - } -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/ManagedUpnpService.java b/clinglibrary/src/main/java/org/fourthline/cling/ManagedUpnpService.java deleted file mode 100644 index 8770c15..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/ManagedUpnpService.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling; - -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.meta.RemoteDevice; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.registry.Registry; -import org.fourthline.cling.registry.RegistryListener; -import org.fourthline.cling.registry.event.After; -import org.fourthline.cling.registry.event.Before; -import org.fourthline.cling.registry.event.FailedRemoteDeviceDiscovery; -import org.fourthline.cling.registry.event.LocalDeviceDiscovery; -import org.fourthline.cling.registry.event.Phase; -import org.fourthline.cling.registry.event.RegistryShutdown; -import org.fourthline.cling.registry.event.RemoteDeviceDiscovery; -import org.fourthline.cling.transport.DisableRouter; -import org.fourthline.cling.transport.EnableRouter; -import org.fourthline.cling.transport.Router; - -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.event.Event; -import javax.enterprise.event.Observes; -import javax.enterprise.inject.Any; -import javax.enterprise.inject.Instance; -import javax.enterprise.util.AnnotationLiteral; -import javax.inject.Inject; -import java.util.logging.Logger; - -/** - * Adapter for CDI environments. - *

- * The CDI container provides injectable instances of Cling UPnP interfaces, e.g. - * you can @Inject Registry or @Inject ControlPoint. - *

- *

- * Furthermore, this adapter also binds Cling into the CDI eventing system. You - * can @Observe RemoteDeviceDiscoveryStart etc. events of the - * registry. - *

- *

- * Even better, in the future you might be able to listen to GENA UPnP events with - * the same API - although this will require some magic for subscription... - *

- *

- * TODO: This is a work in progress. - *

- * - * @author Christian Bauer - */ -@ApplicationScoped -public class ManagedUpnpService implements UpnpService { - - final private static Logger log = Logger.getLogger(ManagedUpnpService.class.getName()); - - @Inject - RegistryListenerAdapter registryListenerAdapter; - - @Inject - Instance configuration; - - @Inject - Instance registryInstance; - - @Inject - Instance routerInstance; - - @Inject - Instance protocolFactoryInstance; - - @Inject - Instance controlPointInstance; - - @Inject - Event enableRouterEvent; - - @Inject - Event disableRouterEvent; - - @Override - public UpnpServiceConfiguration getConfiguration() { - return configuration.get(); - } - - @Override - public ControlPoint getControlPoint() { - return controlPointInstance.get(); - } - - @Override - public ProtocolFactory getProtocolFactory() { - return protocolFactoryInstance.get(); - } - - @Override - public Registry getRegistry() { - return registryInstance.get(); - } - - @Override - public Router getRouter() { - return routerInstance.get(); - } - - public void start(@Observes Start start) { - log.info(">>> Starting managed UPnP service..."); - - // First start the registry before we can receive messages through the transport - - getRegistry().addListener(registryListenerAdapter); - - enableRouterEvent.fire(new EnableRouter()); - - log.info("<<< Managed UPnP service started successfully"); - } - - @Override - public void shutdown() { - shutdown(null); - } - - public void shutdown(@Observes Shutdown shutdown) { - - // Well, since java.util.logging has its own shutdown hook, this - // might actually make it into the log or not... - log.info(">>> Shutting down managed UPnP service..."); - - // First stop the registry and announce BYEBYE on the transport - getRegistry().shutdown(); - - disableRouterEvent.fire(new DisableRouter()); - - getConfiguration().shutdown(); - - log.info("<<< Managed UPnP service shutdown completed"); - } - - @ApplicationScoped - static class RegistryListenerAdapter implements RegistryListener { - - @Inject - @Any - Event remoteDeviceDiscoveryEvent; - - @Inject - @Any - Event failedRemoteDeviceDiscoveryEvent; - - @Inject - @Any - Event localDeviceDiscoveryEvent; - - @Inject - @Any - Event registryShutdownEvent; - - @Override - public void remoteDeviceDiscoveryStarted(Registry registry, RemoteDevice device) { - remoteDeviceDiscoveryEvent.select(Phase.ALIVE).fire( - new RemoteDeviceDiscovery(device) - ); - } - - @Override - public void remoteDeviceDiscoveryFailed(Registry registry, RemoteDevice device, Exception ex) { - failedRemoteDeviceDiscoveryEvent.fire( - new FailedRemoteDeviceDiscovery(device, ex) - ); - } - - @Override - public void remoteDeviceAdded(Registry registry, RemoteDevice device) { - remoteDeviceDiscoveryEvent.select(Phase.COMPLETE).fire( - new RemoteDeviceDiscovery(device) - ); - } - - @Override - public void remoteDeviceUpdated(Registry registry, RemoteDevice device) { - remoteDeviceDiscoveryEvent.select(Phase.UPDATED).fire( - new RemoteDeviceDiscovery(device) - ); - } - - @Override - public void remoteDeviceRemoved(Registry registry, RemoteDevice device) { - remoteDeviceDiscoveryEvent.select(Phase.BYEBYE).fire( - new RemoteDeviceDiscovery(device) - ); - } - - @Override - public void localDeviceAdded(Registry registry, LocalDevice device) { - localDeviceDiscoveryEvent.select(Phase.COMPLETE).fire( - new LocalDeviceDiscovery(device) - ); - } - - @Override - public void localDeviceRemoved(Registry registry, LocalDevice device) { - localDeviceDiscoveryEvent.select(Phase.BYEBYE).fire( - new LocalDeviceDiscovery(device) - ); - } - - @Override - public void beforeShutdown(Registry registry) { - registryShutdownEvent.select(new AnnotationLiteral() { - }).fire( - new RegistryShutdown() - ); - } - - @Override - public void afterShutdown() { - registryShutdownEvent.select(new AnnotationLiteral() { - }).fire( - new RegistryShutdown() - ); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/ManagedUpnpServiceConfiguration.java b/clinglibrary/src/main/java/org/fourthline/cling/ManagedUpnpServiceConfiguration.java deleted file mode 100644 index 3166fce..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/ManagedUpnpServiceConfiguration.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling; - -import org.fourthline.cling.binding.xml.DeviceDescriptorBinder; -import org.fourthline.cling.binding.xml.ServiceDescriptorBinder; -import org.fourthline.cling.binding.xml.UDA10DeviceDescriptorBinderImpl; -import org.fourthline.cling.binding.xml.UDA10ServiceDescriptorBinderImpl; -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.meta.RemoteDeviceIdentity; -import org.fourthline.cling.model.meta.RemoteService; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.transport.impl.DatagramIOConfigurationImpl; -import org.fourthline.cling.transport.impl.DatagramIOImpl; -import org.fourthline.cling.transport.impl.GENAEventProcessorImpl; -import org.fourthline.cling.transport.impl.MulticastReceiverConfigurationImpl; -import org.fourthline.cling.transport.impl.MulticastReceiverImpl; -import org.fourthline.cling.transport.impl.NetworkAddressFactoryImpl; -import org.fourthline.cling.transport.impl.SOAPActionProcessorImpl; -import org.fourthline.cling.transport.impl.StreamClientConfigurationImpl; -import org.fourthline.cling.transport.impl.StreamClientImpl; -import org.fourthline.cling.transport.impl.StreamServerConfigurationImpl; -import org.fourthline.cling.transport.impl.StreamServerImpl; -import org.fourthline.cling.transport.spi.DatagramIO; -import org.fourthline.cling.transport.spi.DatagramProcessor; -import org.fourthline.cling.transport.spi.GENAEventProcessor; -import org.fourthline.cling.transport.spi.MulticastReceiver; -import org.fourthline.cling.transport.spi.NetworkAddressFactory; -import org.fourthline.cling.transport.spi.SOAPActionProcessor; -import org.fourthline.cling.transport.spi.StreamClient; -import org.fourthline.cling.transport.spi.StreamServer; - -import javax.annotation.PostConstruct; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.logging.Logger; - -/** - * Adapter for CDI environments. - * - * @author Christian Bauer - */ -@ApplicationScoped -public class ManagedUpnpServiceConfiguration implements UpnpServiceConfiguration { - - private static Logger log = Logger.getLogger(DefaultUpnpServiceConfiguration.class.getName()); - - // TODO: All of these fields should be injected so users can provide values through CDI - - private int streamListenPort; - - private ExecutorService defaultExecutorService; - - @Inject - protected DatagramProcessor datagramProcessor; - - private SOAPActionProcessor soapActionProcessor; - private GENAEventProcessor genaEventProcessor; - - private DeviceDescriptorBinder deviceDescriptorBinderUDA10; - private ServiceDescriptorBinder serviceDescriptorBinderUDA10; - - private Namespace namespace; - - @PostConstruct - public void init() { - - if (ModelUtil.ANDROID_RUNTIME) { - throw new Error("Unsupported runtime environment, use org.fourthline.cling.android.AndroidUpnpServiceConfiguration"); - } - - this.streamListenPort = NetworkAddressFactoryImpl.DEFAULT_TCP_HTTP_LISTEN_PORT; - - defaultExecutorService = createDefaultExecutorService(); - - soapActionProcessor = createSOAPActionProcessor(); - genaEventProcessor = createGENAEventProcessor(); - - deviceDescriptorBinderUDA10 = createDeviceDescriptorBinderUDA10(); - serviceDescriptorBinderUDA10 = createServiceDescriptorBinderUDA10(); - - namespace = createNamespace(); - } - - public DatagramProcessor getDatagramProcessor() { - return datagramProcessor; - } - - public SOAPActionProcessor getSoapActionProcessor() { - return soapActionProcessor; - } - - public GENAEventProcessor getGenaEventProcessor() { - return genaEventProcessor; - } - - public StreamClient createStreamClient() { - return new StreamClientImpl( - new StreamClientConfigurationImpl( - getSyncProtocolExecutorService() - ) - ); - } - - public MulticastReceiver createMulticastReceiver(NetworkAddressFactory networkAddressFactory) { - return new MulticastReceiverImpl( - new MulticastReceiverConfigurationImpl( - networkAddressFactory.getMulticastGroup(), - networkAddressFactory.getMulticastPort() - ) - ); - } - - public DatagramIO createDatagramIO(NetworkAddressFactory networkAddressFactory) { - return new DatagramIOImpl(new DatagramIOConfigurationImpl()); - } - - public StreamServer createStreamServer(NetworkAddressFactory networkAddressFactory) { - return new StreamServerImpl( - new StreamServerConfigurationImpl( - networkAddressFactory.getStreamListenPort() - ) - ); - } - - public Executor getMulticastReceiverExecutor() { - return getDefaultExecutorService(); - } - - public Executor getDatagramIOExecutor() { - return getDefaultExecutorService(); - } - - public ExecutorService getStreamServerExecutorService() { - return getDefaultExecutorService(); - } - - public DeviceDescriptorBinder getDeviceDescriptorBinderUDA10() { - return deviceDescriptorBinderUDA10; - } - - public ServiceDescriptorBinder getServiceDescriptorBinderUDA10() { - return serviceDescriptorBinderUDA10; - } - - public ServiceType[] getExclusiveServiceTypes() { - return new ServiceType[0]; - } - - /** - * @return Defaults to false. - */ - public boolean isReceivedSubscriptionTimeoutIgnored() { - return false; - } - - public UpnpHeaders getDescriptorRetrievalHeaders(RemoteDeviceIdentity identity) { - return null; - } - - public UpnpHeaders getEventSubscriptionHeaders(RemoteService service) { - return null; - } - - /** - * @return Defaults to 1000 milliseconds. - */ - public int getRegistryMaintenanceIntervalMillis() { - return 1000; - } - - /** - * @return Defaults to zero, disabling ALIVE flooding. - */ - public int getAliveIntervalMillis() { - return 0; - } - - public Integer getRemoteDeviceMaxAgeSeconds() { - return null; - } - - public Executor getAsyncProtocolExecutor() { - return getDefaultExecutorService(); - } - - public ExecutorService getSyncProtocolExecutorService() { - return getDefaultExecutorService(); - } - - public Namespace getNamespace() { - return namespace; - } - - public Executor getRegistryMaintainerExecutor() { - return getDefaultExecutorService(); - } - - public Executor getRegistryListenerExecutor() { - return getDefaultExecutorService(); - } - - public NetworkAddressFactory createNetworkAddressFactory() { - return createNetworkAddressFactory(streamListenPort); - } - - public void shutdown() { - log.fine("Shutting down default executor service"); - getDefaultExecutorService().shutdownNow(); - } - - protected NetworkAddressFactory createNetworkAddressFactory(int streamListenPort) { - return new NetworkAddressFactoryImpl(streamListenPort); - } - - protected SOAPActionProcessor createSOAPActionProcessor() { - return new SOAPActionProcessorImpl(); - } - - protected GENAEventProcessor createGENAEventProcessor() { - return new GENAEventProcessorImpl(); - } - - protected DeviceDescriptorBinder createDeviceDescriptorBinderUDA10() { - return new UDA10DeviceDescriptorBinderImpl(); - } - - protected ServiceDescriptorBinder createServiceDescriptorBinderUDA10() { - return new UDA10ServiceDescriptorBinderImpl(); - } - - protected Namespace createNamespace() { - return new Namespace(); - } - - protected ExecutorService getDefaultExecutorService() { - return defaultExecutorService; - } - - protected ExecutorService createDefaultExecutorService() { - return new DefaultUpnpServiceConfiguration.ClingExecutor(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/UpnpService.java b/clinglibrary/src/main/java/org/fourthline/cling/UpnpService.java deleted file mode 100644 index efda528..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/UpnpService.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling; - -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.registry.Registry; -import org.fourthline.cling.transport.Router; - -/** - * Primary interface of the Cling Core UPnP stack. - *

- * An implementation can either start immediately when constructed or offer an additional - * method that starts the UPnP stack on-demand. Implementations are not required to be - * restartable after shutdown. - *

- *

- * Implementations are always thread-safe and can be shared and called concurrently. - *

- * - * @author Christian Bauer - */ -public interface UpnpService { - - public UpnpServiceConfiguration getConfiguration(); - - public ControlPoint getControlPoint(); - - public ProtocolFactory getProtocolFactory(); - - public Registry getRegistry(); - - public Router getRouter(); - - /** - * Stopping the UPnP stack. - *

- * Clients are required to stop the UPnP stack properly. Notifications for - * disappearing devices will be multicast'ed, existing event subscriptions cancelled. - *

- */ - public void shutdown(); - - static public class Start { - - } - - static public class Shutdown { - - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/UpnpServiceConfiguration.java b/clinglibrary/src/main/java/org/fourthline/cling/UpnpServiceConfiguration.java deleted file mode 100644 index 0f06979..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/UpnpServiceConfiguration.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling; - -import org.fourthline.cling.binding.xml.DeviceDescriptorBinder; -import org.fourthline.cling.binding.xml.ServiceDescriptorBinder; -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.meta.RemoteDeviceIdentity; -import org.fourthline.cling.model.meta.RemoteService; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.transport.spi.DatagramIO; -import org.fourthline.cling.transport.spi.DatagramProcessor; -import org.fourthline.cling.transport.spi.GENAEventProcessor; -import org.fourthline.cling.transport.spi.MulticastReceiver; -import org.fourthline.cling.transport.spi.NetworkAddressFactory; -import org.fourthline.cling.transport.spi.SOAPActionProcessor; -import org.fourthline.cling.transport.spi.StreamClient; -import org.fourthline.cling.transport.spi.StreamServer; - -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; - -/** - * Shared configuration data of the UPnP stack. - *

- * This interface offers methods for retrieval of configuration data by the - * {@link org.fourthline.cling.transport.Router} and the {@link org.fourthline.cling.registry.Registry}, - * as well as other parts of the UPnP stack. - *

- *

- * You can re-use this interface if you implement a subclass of {@link UpnpServiceImpl} or - * if you create a new implementation of {@link UpnpService}. - *

- * - * @author Christian Bauer - */ -public interface UpnpServiceConfiguration { - - /** - * @return A new instance of the {@link org.fourthline.cling.transport.spi.NetworkAddressFactory} interface. - */ - public NetworkAddressFactory createNetworkAddressFactory(); - - /** - * @return The shared implementation of {@link org.fourthline.cling.transport.spi.DatagramProcessor}. - */ - public DatagramProcessor getDatagramProcessor(); - - /** - * @return The shared implementation of {@link org.fourthline.cling.transport.spi.SOAPActionProcessor}. - */ - public SOAPActionProcessor getSoapActionProcessor(); - - /** - * @return The shared implementation of {@link org.fourthline.cling.transport.spi.GENAEventProcessor}. - */ - public GENAEventProcessor getGenaEventProcessor(); - - /** - * @return A new instance of the {@link org.fourthline.cling.transport.spi.StreamClient} interface. - */ - public StreamClient createStreamClient(); - - /** - * @param networkAddressFactory The configured {@link org.fourthline.cling.transport.spi.NetworkAddressFactory}. - * @return A new instance of the {@link org.fourthline.cling.transport.spi.MulticastReceiver} interface. - */ - public MulticastReceiver createMulticastReceiver(NetworkAddressFactory networkAddressFactory); - - /** - * @param networkAddressFactory The configured {@link org.fourthline.cling.transport.spi.NetworkAddressFactory}. - * @return A new instance of the {@link org.fourthline.cling.transport.spi.DatagramIO} interface. - */ - public DatagramIO createDatagramIO(NetworkAddressFactory networkAddressFactory); - - /** - * @param networkAddressFactory The configured {@link org.fourthline.cling.transport.spi.NetworkAddressFactory}. - * @return A new instance of the {@link org.fourthline.cling.transport.spi.StreamServer} interface. - */ - public StreamServer createStreamServer(NetworkAddressFactory networkAddressFactory); - - /** - * @return The executor which runs the listening background threads for multicast datagrams. - */ - public Executor getMulticastReceiverExecutor(); - - /** - * @return The executor which runs the listening background threads for unicast datagrams. - */ - public Executor getDatagramIOExecutor(); - - /** - * @return The executor which runs the listening background threads for HTTP requests. - */ - public ExecutorService getStreamServerExecutorService(); - - /** - * @return The shared implementation of {@link org.fourthline.cling.binding.xml.DeviceDescriptorBinder} for the UPnP 1.0 Device Architecture.. - */ - public DeviceDescriptorBinder getDeviceDescriptorBinderUDA10(); - - /** - * @return The shared implementation of {@link org.fourthline.cling.binding.xml.ServiceDescriptorBinder} for the UPnP 1.0 Device Architecture.. - */ - public ServiceDescriptorBinder getServiceDescriptorBinderUDA10(); - - /** - * Returns service types that can be handled by this UPnP stack, all others will be ignored. - *

- * Return null to completely disable remote device and service discovery. - * All incoming notifications and search responses will then be dropped immediately. - * This is mostly useful in applications that only provide services with no (remote) - * control point functionality. - *

- *

- * Note that a discovered service type with version 2 or 3 will match an exclusive - * service type with version 1. UPnP services are required to be backwards - * compatible, version 2 is a superset of version 1, and version 3 is a superset - * of version 2, etc. - *

- * - * @return An array of service types that are exclusively discovered, no other service will - * be discovered. A null return value will disable discovery! - * An empty array means all services will be discovered. - */ - public ServiceType[] getExclusiveServiceTypes(); - - /** - * @return The time in milliseconds to wait between each registry maintenance operation. - */ - public int getRegistryMaintenanceIntervalMillis(); - - /** - * Optional setting for flooding alive NOTIFY messages for local devices. - *

- * Use this to advertise local devices at the specified interval, independent of its - * {@link org.fourthline.cling.model.meta.DeviceIdentity#maxAgeSeconds} value. Note - * that this will increase network traffic. - *

- *

- * Some control points (XBMC and other Platinum UPnP SDK based devices, OPPO-93) seem - * to not properly receive SSDP M-SEARCH replies sent by Cling, but will handle NOTIFY - * alive messages just fine. - *

- * - * @return The time in milliseconds for ALIVE message intervals, set to 0 to disable - */ - public int getAliveIntervalMillis(); - - /** - * Ignore the received event subscription timeout from remote control points. - *

- * Some control points have trouble renewing subscriptions properly; enabling this option - * in conjunction with a high value for - * {@link org.fourthline.cling.model.UserConstants#DEFAULT_SUBSCRIPTION_DURATION_SECONDS} - * ensures that your devices will not disappear on such control points. - *

- * - * @return true if the timeout in incoming event subscriptions should be ignored - * and the default value ({@link org.fourthline.cling.model.UserConstants#DEFAULT_SUBSCRIPTION_DURATION_SECONDS}) - * should be used instead. - * - */ - public boolean isReceivedSubscriptionTimeoutIgnored(); - - /** - * Returns the time in seconds a remote device will be registered until it is expired. - *

- * This setting is useful on systems which do not support multicast networking - * (Android on HTC phones, for example). On such a system you will not receive messages when a - * remote device disappears from the network and you will not receive its periodic heartbeat - * alive messages. Only an initial search response (UDP unicast) has been received from the - * remote device, with its proposed maximum age. To avoid (early) expiration of the remote - * device, you can override its maximum age with this configuration setting, ignoring the - * initial maximum age sent by the device. You most likely want to return - * 0 in this case, so that the remote device is never expired unless you - * manually remove it from the {@link org.fourthline.cling.registry.Registry}. You typically remove - * the device when an action or GENA subscription request to the remote device failed. - *

- * - * @return null (the default) to accept the remote device's proposed maximum age, or - * 0 for unlimited age, or a value in seconds. - */ - public Integer getRemoteDeviceMaxAgeSeconds(); - - /** - * Optional extra headers for device descriptor retrieval HTTP requests. - *

- * Some devices might require extra headers to recognize your control point, use this - * method to set these headers. They will be used for every descriptor (XML) retrieval - * HTTP request by Cling. See {@link org.fourthline.cling.model.profile.ClientInfo} for - * action request messages. - *

- * - * @param identity The (so far) discovered identity of the remote device. - * @return null or extra HTTP headers. - */ - public UpnpHeaders getDescriptorRetrievalHeaders(RemoteDeviceIdentity identity); - - /** - * Optional extra headers for event subscription (almost HTTP) messages. - *

- * Some devices might require extra headers to recognize your control point, use this - * method to set these headers for GENA subscriptions. Note that the headers will - * not be applied to actual event messages, only subscribe, unsubscribe, and renewal. - *

- * - * @return null or extra HTTP headers. - */ - public UpnpHeaders getEventSubscriptionHeaders(RemoteService service); - - /** - * @return The executor which runs the processing of asynchronous aspects of the UPnP stack (discovery). - */ - public Executor getAsyncProtocolExecutor(); - - /** - * @return The executor service which runs the processing of synchronous aspects of the UPnP stack (description, control, GENA). - */ - public ExecutorService getSyncProtocolExecutorService(); - - /** - * @return An instance of {@link org.fourthline.cling.model.Namespace} for this UPnP stack. - */ - public Namespace getNamespace(); - - /** - * @return The executor which runs the background thread for maintaining the registry. - */ - public Executor getRegistryMaintainerExecutor(); - - /** - * @return The executor which runs the notification threads of registry listeners. - */ - public Executor getRegistryListenerExecutor(); - - /** - * Called by the {@link org.fourthline.cling.UpnpService} on shutdown, useful to e.g. shutdown thread pools. - */ - public void shutdown(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/UpnpServiceImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/UpnpServiceImpl.java deleted file mode 100644 index 3c23e3b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/UpnpServiceImpl.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling; - -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.controlpoint.ControlPointImpl; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.protocol.ProtocolFactoryImpl; -import org.fourthline.cling.registry.Registry; -import org.fourthline.cling.registry.RegistryImpl; -import org.fourthline.cling.registry.RegistryListener; -import org.fourthline.cling.transport.Router; -import org.fourthline.cling.transport.RouterException; -import org.fourthline.cling.transport.RouterImpl; -import org.seamless.util.Exceptions; - -import javax.enterprise.inject.Alternative; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Default implementation of {@link UpnpService}, starts immediately on construction. - *

- * If no {@link UpnpServiceConfiguration} is provided it will automatically - * instantiate {@link DefaultUpnpServiceConfiguration}. This configuration does not - * work on Android! Use the {@link org.fourthline.cling.android.AndroidUpnpService} - * application component instead. - *

- *

- * Override the various create...() methods to customize instantiation of protocol factory, - * router, etc. - *

- * - * @author Christian Bauer - */ -@Alternative -public class UpnpServiceImpl implements UpnpService { - - private static Logger log = Logger.getLogger(UpnpServiceImpl.class.getName()); - - protected final UpnpServiceConfiguration configuration; - protected final ControlPoint controlPoint; - protected final ProtocolFactory protocolFactory; - protected final Registry registry; - protected final Router router; - - public UpnpServiceImpl() { - this(new DefaultUpnpServiceConfiguration()); - } - - public UpnpServiceImpl(RegistryListener... registryListeners) { - this(new DefaultUpnpServiceConfiguration(), registryListeners); - } - - public UpnpServiceImpl(UpnpServiceConfiguration configuration, RegistryListener... registryListeners) { - this.configuration = configuration; - - log.info(">>> Starting UPnP service..."); - - log.info("Using configuration: " + getConfiguration().getClass().getName()); - - // Instantiation order is important: Router needs to start its network services after registry is ready - - this.protocolFactory = createProtocolFactory(); - - this.registry = createRegistry(protocolFactory); - for (RegistryListener registryListener : registryListeners) { - this.registry.addListener(registryListener); - } - - this.router = createRouter(protocolFactory, registry); - - try { - this.router.enable(); - } catch (RouterException ex) { - throw new RuntimeException("Enabling network router failed: " + ex, ex); - } - - this.controlPoint = createControlPoint(protocolFactory, registry); - - log.info("<<< UPnP service started successfully"); - } - - protected ProtocolFactory createProtocolFactory() { - return new ProtocolFactoryImpl(this); - } - - protected Registry createRegistry(ProtocolFactory protocolFactory) { - return new RegistryImpl(this); - } - - protected Router createRouter(ProtocolFactory protocolFactory, Registry registry) { - return new RouterImpl(getConfiguration(), protocolFactory); - } - - protected ControlPoint createControlPoint(ProtocolFactory protocolFactory, Registry registry) { - return new ControlPointImpl(getConfiguration(), protocolFactory, registry); - } - - public UpnpServiceConfiguration getConfiguration() { - return configuration; - } - - public ControlPoint getControlPoint() { - return controlPoint; - } - - public ProtocolFactory getProtocolFactory() { - return protocolFactory; - } - - public Registry getRegistry() { - return registry; - } - - public Router getRouter() { - return router; - } - - synchronized public void shutdown() { - shutdown(false); - } - - protected void shutdown(boolean separateThread) { - Runnable shutdown = new Runnable() { - @Override - public void run() { - log.info(">>> Shutting down UPnP service..."); - shutdownRegistry(); - shutdownRouter(); - shutdownConfiguration(); - log.info("<<< UPnP service shutdown completed"); - } - }; - if (separateThread) { - // This is not a daemon thread, it has to complete! - new Thread(shutdown).start(); - } else { - shutdown.run(); - } - } - - protected void shutdownRegistry() { - getRegistry().shutdown(); - } - - protected void shutdownRouter() { - try { - getRouter().shutdown(); - } catch (RouterException ex) { - Throwable cause = Exceptions.unwrap(ex); - if (cause instanceof InterruptedException) { - log.log(Level.INFO, "Router shutdown was interrupted: " + ex, cause); - } else { - log.log(Level.SEVERE, "Router error on shutdown: " + ex, cause); - } - } - } - - protected void shutdownConfiguration() { - getConfiguration().shutdown(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidNetworkAddressFactory.java b/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidNetworkAddressFactory.java deleted file mode 100644 index 74d8bd4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidNetworkAddressFactory.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.android; - -import org.fourthline.cling.transport.impl.NetworkAddressFactoryImpl; -import org.fourthline.cling.transport.spi.InitializationException; - -import java.lang.reflect.Field; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * This factory tries to work around and patch some Android bugs. - * - * @author Michael Pujos - * @author Christian Bauer - */ -public class AndroidNetworkAddressFactory extends NetworkAddressFactoryImpl { - - final private static Logger log = Logger.getLogger(AndroidUpnpServiceConfiguration.class.getName()); - - public AndroidNetworkAddressFactory(int streamListenPort) { - super(streamListenPort); - } - - @Override - protected boolean requiresNetworkInterface() { - return false; - } - - @Override - protected boolean isUsableAddress(NetworkInterface networkInterface, InetAddress address) { - boolean result = super.isUsableAddress(networkInterface, address); - if (result) { - // TODO: Workaround Android DNS reverse lookup issue, still a problem on ICS+? - // http://4thline.org/projects/mailinglists.html#nabble-td3011461 - String hostName = address.getHostAddress(); - - Field field0 = null; - Object target = null; - - try { - - try { - field0 = InetAddress.class.getDeclaredField("holder"); - field0.setAccessible(true); - target = field0.get(address); - field0 = target.getClass().getDeclaredField("hostName"); - } catch( NoSuchFieldException e ) { - // Let's try the non-OpenJDK variant - field0 = InetAddress.class.getDeclaredField("hostName"); - target = address; - } - - if (field0 != null && target != null && hostName != null) { - field0.setAccessible(true); - field0.set(target, hostName); - } else { - return false; - } - - } catch (Exception ex) { - log.log(Level.SEVERE, - "Failed injecting hostName to work around Android InetAddress DNS bug: " + address, - ex - ); - return false; - } - } - return result; - } - - @Override - public InetAddress getLocalAddress(NetworkInterface networkInterface, boolean isIPv6, InetAddress remoteAddress) { - // TODO: This is totally random because we can't access low level InterfaceAddress on Android! - for (InetAddress localAddress : getInetAddresses(networkInterface)) { - if (isIPv6 && localAddress instanceof Inet6Address) - return localAddress; - if (!isIPv6 && localAddress instanceof Inet4Address) - return localAddress; - } - throw new IllegalStateException("Can't find any IPv4 or IPv6 address on interface: " + networkInterface.getDisplayName()); - } - - @Override - protected void discoverNetworkInterfaces() throws InitializationException { - try { - super.discoverNetworkInterfaces(); - } catch (Exception ex) { - // TODO: ICS bug on some models with network interface disappearing while enumerated - // http://code.google.com/p/android/issues/detail?id=33661 - log.warning("Exception while enumerating network interfaces, trying once more: " + ex); - super.discoverNetworkInterfaces(); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidRouter.java b/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidRouter.java deleted file mode 100644 index 7ebb1b1..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidRouter.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.android; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.net.wifi.WifiManager; -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.transport.Router; -import org.fourthline.cling.transport.RouterException; -import org.fourthline.cling.transport.RouterImpl; -import org.fourthline.cling.transport.spi.InitializationException; -import org.seamless.util.Exceptions; - -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Monitors all network connectivity changes, switching the router accordingly. - * - * @author Michael Pujos - * @author Christian Bauer - */ -public class AndroidRouter extends RouterImpl { - - final private static Logger log = Logger.getLogger(Router.class.getName()); - - final private Context context; - - final private WifiManager wifiManager; - protected WifiManager.MulticastLock multicastLock; - protected WifiManager.WifiLock wifiLock; - protected NetworkInfo networkInfo; - protected BroadcastReceiver broadcastReceiver; - - public AndroidRouter(UpnpServiceConfiguration configuration, - ProtocolFactory protocolFactory, - Context context) throws InitializationException { - super(configuration, protocolFactory); - - this.context = context; - this.wifiManager = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)); - this.networkInfo = NetworkUtils.getConnectedNetworkInfo(context); - - // Only register for network connectivity changes if we are not running on emulator - if (!ModelUtil.ANDROID_EMULATOR) { - this.broadcastReceiver = createConnectivityBroadcastReceiver(); - context.registerReceiver(broadcastReceiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")); - } - } - - protected BroadcastReceiver createConnectivityBroadcastReceiver() { - return new ConnectivityBroadcastReceiver(); - } - - @Override - protected int getLockTimeoutMillis() { - return 15000; - } - - @Override - public void shutdown() throws RouterException { - super.shutdown(); - unregisterBroadcastReceiver(); - } - - @Override - public boolean enable() throws RouterException { - lock(writeLock); - try { - boolean enabled; - if ((enabled = super.enable())) { - // Enable multicast on the WiFi network interface, - // requires android.permission.CHANGE_WIFI_MULTICAST_STATE - if (isWifi()) { - setWiFiMulticastLock(true); - setWifiLock(true); - } - } - return enabled; - } finally { - unlock(writeLock); - } - } - - @Override - public boolean disable() throws RouterException { - lock(writeLock); - try { - // Disable multicast on WiFi network interface, - // requires android.permission.CHANGE_WIFI_MULTICAST_STATE - if (isWifi()) { - setWiFiMulticastLock(false); - setWifiLock(false); - } - return super.disable(); - } finally { - unlock(writeLock); - } - } - - public NetworkInfo getNetworkInfo() { - return networkInfo; - } - - public boolean isMobile() { - return NetworkUtils.isMobile(networkInfo); - } - - public boolean isWifi() { - return NetworkUtils.isWifi(networkInfo); - } - - public boolean isEthernet() { - return NetworkUtils.isEthernet(networkInfo); - } - - public boolean enableWiFi() { - log.info("Enabling WiFi..."); - try { - return wifiManager.setWifiEnabled(true); - } catch (Throwable t) { - // workaround (HTC One X, 4.0.3) - //java.lang.SecurityException: Permission Denial: writing com.android.providers.settings.SettingsProvider - // uri content://settings/system from pid=4691, uid=10226 requires android.permission.WRITE_SETTINGS - // at android.os.Parcel.readException(Parcel.java:1332) - // at android.os.Parcel.readException(Parcel.java:1286) - // at android.net.wifi.IWifiManager$Stub$Proxy.setWifiEnabled(IWifiManager.java:1115) - // at android.net.wifi.WifiManager.setWifiEnabled(WifiManager.java:946) - log.log(Level.WARNING, "SetWifiEnabled failed", t); - return false; - } - } - - public void unregisterBroadcastReceiver() { - if (broadcastReceiver != null) { - context.unregisterReceiver(broadcastReceiver); - broadcastReceiver = null; - } - } - - protected void setWiFiMulticastLock(boolean enable) { - if (multicastLock == null) { - multicastLock = wifiManager.createMulticastLock(getClass().getSimpleName()); - } - - if (enable) { - if (multicastLock.isHeld()) { - log.warning("WiFi multicast lock already acquired"); - } else { - log.info("WiFi multicast lock acquired"); - multicastLock.acquire(); - } - } else { - if (multicastLock.isHeld()) { - log.info("WiFi multicast lock released"); - multicastLock.release(); - } else { - log.warning("WiFi multicast lock already released"); - } - } - } - - protected void setWifiLock(boolean enable) { - if (wifiLock == null) { - wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, getClass().getSimpleName()); - } - - if (enable) { - if (wifiLock.isHeld()) { - log.warning("WiFi lock already acquired"); - } else { - log.info("WiFi lock acquired"); - wifiLock.acquire(); - } - } else { - if (wifiLock.isHeld()) { - log.info("WiFi lock released"); - wifiLock.release(); - } else { - log.warning("WiFi lock already released"); - } - } - } - - /** - * Can be overriden by subclasses to do additional work. - * - * @param oldNetwork null when first called by constructor. - */ - protected void onNetworkTypeChange(NetworkInfo oldNetwork, NetworkInfo newNetwork) throws RouterException { - log.info(String.format("Network type changed %s => %s", - oldNetwork == null ? "" : oldNetwork.getTypeName(), - newNetwork == null ? "NONE" : newNetwork.getTypeName())); - - if (disable()) { - log.info(String.format( - "Disabled router on network type change (old network: %s)", - oldNetwork == null ? "NONE" : oldNetwork.getTypeName() - )); - } - - networkInfo = newNetwork; - if (enable()) { - // Can return false (via earlier InitializationException thrown by NetworkAddressFactory) if - // no bindable network address found! - log.info(String.format( - "Enabled router on network type change (new network: %s)", - newNetwork == null ? "NONE" : newNetwork.getTypeName() - )); - } - } - - /** - * Handles errors when network has been switched, during reception of - * network switch broadcast. Logs a warning by default, override to - * change this behavior. - */ - protected void handleRouterExceptionOnNetworkTypeChange(RouterException ex) { - Throwable cause = Exceptions.unwrap(ex); - if (cause instanceof InterruptedException) { - log.log(Level.INFO, "Router was interrupted: " + ex, cause); - } else { - log.log(Level.WARNING, "Router error on network change: " + ex, ex); - } - } - - class ConnectivityBroadcastReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - - if (!intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) - return; - - displayIntentInfo(intent); - - NetworkInfo newNetworkInfo = NetworkUtils.getConnectedNetworkInfo(context); - - // When Android switches WiFI => MOBILE, sometimes we may have a short transition - // with no network: WIFI => NONE, NONE => MOBILE - // The code below attempts to make it look like a single WIFI => MOBILE - // transition, retrying up to 3 times getting the current network. - // - // Note: this can block the UI thread for up to 3s - if (networkInfo != null && newNetworkInfo == null) { - for (int i = 1; i <= 3; i++) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - return; - } - log.warning(String.format( - "%s => NONE network transition, waiting for new network... retry #%d", - networkInfo.getTypeName(), i - )); - newNetworkInfo = NetworkUtils.getConnectedNetworkInfo(context); - if (newNetworkInfo != null) - break; - } - } - - if (isSameNetworkType(networkInfo, newNetworkInfo)) { - log.info("No actual network change... ignoring event!"); - } else { - try { - onNetworkTypeChange(networkInfo, newNetworkInfo); - } catch (RouterException ex) { - handleRouterExceptionOnNetworkTypeChange(ex); - } - } - } - - protected boolean isSameNetworkType(NetworkInfo network1, NetworkInfo network2) { - if (network1 == null && network2 == null) - return true; - if (network1 == null || network2 == null) - return false; - return network1.getType() == network2.getType(); - } - - protected void displayIntentInfo(Intent intent) { - boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); - String reason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON); - boolean isFailover = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false); - - NetworkInfo currentNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); - NetworkInfo otherNetworkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO); - - log.info("Connectivity change detected..."); - log.info("EXTRA_NO_CONNECTIVITY: " + noConnectivity); - log.info("EXTRA_REASON: " + reason); - log.info("EXTRA_IS_FAILOVER: " + isFailover); - log.info("EXTRA_NETWORK_INFO: " + (currentNetworkInfo == null ? "none" : currentNetworkInfo)); - log.info("EXTRA_OTHER_NETWORK_INFO: " + (otherNetworkInfo == null ? "none" : otherNetworkInfo)); - log.info("EXTRA_EXTRA_INFO: " + intent.getStringExtra(ConnectivityManager.EXTRA_EXTRA_INFO)); - } - - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpService.java b/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpService.java deleted file mode 100644 index b15d1ea..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpService.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.android; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.registry.Registry; - -/** - * Interface of the Android UPnP application service component. - *

- * Usage example in an Android activity: - *

- *
{@code
- *AndroidUpnpService upnpService;
- *
- *ServiceConnection serviceConnection = new ServiceConnection() {
- *     public void onServiceConnected(ComponentName className, IBinder service) {
- *         upnpService = (AndroidUpnpService) service;
- *     }
- *     public void onServiceDisconnected(ComponentName className) {
- *         upnpService = null;
- *     }
- *};
- *
- *public void onCreate(...) {
- * ...
- *     getApplicationContext().bindService(
- *         new Intent(this, AndroidUpnpServiceImpl.class),
- *         serviceConnection,
- *         Context.BIND_AUTO_CREATE
- *     );
- *}}
- *

- * The default implementation requires permissions in AndroidManifest.xml: - *

- *
{@code
- *
- *
- *
- *
- *
- *}
- *

- * You also have to add the application service component: - *

- *
{@code
- *
- *  ...
- *  
- *
- * }
- * - * @author Christian Bauer - */ -// DOC:CLASS -public interface AndroidUpnpService { - - /** - * @return The actual main instance and interface of the UPnP service. - */ - public UpnpService get(); - - /** - * @return The configuration of the UPnP service. - */ - public UpnpServiceConfiguration getConfiguration(); - - /** - * @return The registry of the UPnP service. - */ - public Registry getRegistry(); - - /** - * @return The client API of the UPnP service. - */ - public ControlPoint getControlPoint(); - -} -// DOC:CLASS diff --git a/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpServiceConfiguration.java b/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpServiceConfiguration.java deleted file mode 100644 index 82a8b0a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpServiceConfiguration.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.android; - -import android.os.Build; -import org.fourthline.cling.DefaultUpnpServiceConfiguration; -import org.fourthline.cling.binding.xml.DeviceDescriptorBinder; -import org.fourthline.cling.binding.xml.RecoveringUDA10DeviceDescriptorBinderImpl; -import org.fourthline.cling.binding.xml.ServiceDescriptorBinder; -import org.fourthline.cling.binding.xml.UDA10ServiceDescriptorBinderSAXImpl; -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.ServerClientTokens; -import org.fourthline.cling.transport.impl.AsyncServletStreamServerConfigurationImpl; -import org.fourthline.cling.transport.impl.AsyncServletStreamServerImpl; -import org.fourthline.cling.transport.impl.RecoveringGENAEventProcessorImpl; -import org.fourthline.cling.transport.impl.RecoveringSOAPActionProcessorImpl; -import org.fourthline.cling.transport.impl.jetty.JettyServletContainer; -import org.fourthline.cling.transport.impl.jetty.StreamClientConfigurationImpl; -import org.fourthline.cling.transport.impl.jetty.StreamClientImpl; -import org.fourthline.cling.transport.spi.GENAEventProcessor; -import org.fourthline.cling.transport.spi.NetworkAddressFactory; -import org.fourthline.cling.transport.spi.SOAPActionProcessor; -import org.fourthline.cling.transport.spi.StreamClient; -import org.fourthline.cling.transport.spi.StreamServer; - -/** - * Configuration settings for deployment on Android. - *

- * This configuration utilizes the Jetty transport implementation - * found in {@link org.fourthline.cling.transport.impl.jetty} for TCP/HTTP networking, as - * client and server. The servlet context path for UPnP is set to /upnp. - *

- *

- * The kxml2 implementation of org.xmlpull is available on Android, therefore - * this configuration uses {@link RecoveringUDA10DeviceDescriptorBinderImpl}, - * {@link RecoveringSOAPActionProcessorImpl}, and {@link RecoveringGENAEventProcessorImpl}. - *

- *

- * This configuration utilizes {@link UDA10ServiceDescriptorBinderSAXImpl}, the system property - * org.xml.sax.driver is set to org.xmlpull.v1.sax2.Driver. - *

- *

- * To preserve battery, the {@link org.fourthline.cling.registry.Registry} will only - * be maintained every 3 seconds. - *

- * - * @author Christian Bauer - */ -public class AndroidUpnpServiceConfiguration extends DefaultUpnpServiceConfiguration { - - public AndroidUpnpServiceConfiguration() { - this(0); // Ephemeral port - } - - public AndroidUpnpServiceConfiguration(int streamListenPort) { - super(streamListenPort, false); - - // This should be the default on Android 2.1 but it's not set by default - System.setProperty("org.xml.sax.driver", "org.xmlpull.v1.sax2.Driver"); - } - - @Override - protected NetworkAddressFactory createNetworkAddressFactory(int streamListenPort) { - return new AndroidNetworkAddressFactory(streamListenPort); - } - - @Override - protected Namespace createNamespace() { - // For the Jetty server, this is the servlet context path - return new Namespace("/upnp"); - } - - @Override - public StreamClient createStreamClient() { - // Use Jetty - return new StreamClientImpl( - new StreamClientConfigurationImpl( - getSyncProtocolExecutorService() - ) { - @Override - public String getUserAgentValue(int majorVersion, int minorVersion) { - // TODO: UPNP VIOLATION: Synology NAS requires User-Agent to contain - // "Android" to return DLNA protocolInfo required to stream to Samsung TV - // see: http://two-play.com/forums/viewtopic.php?f=6&t=81 - ServerClientTokens tokens = new ServerClientTokens(majorVersion, minorVersion); - tokens.setOsName("Android"); - tokens.setOsVersion(Build.VERSION.RELEASE); - return tokens.toString(); - } - } - ); - } - - @Override - public StreamServer createStreamServer(NetworkAddressFactory networkAddressFactory) { - // Use Jetty, start/stop a new shared instance of JettyServletContainer - return new AsyncServletStreamServerImpl( - new AsyncServletStreamServerConfigurationImpl( - JettyServletContainer.INSTANCE, - networkAddressFactory.getStreamListenPort() - ) - ); - } - - @Override - protected DeviceDescriptorBinder createDeviceDescriptorBinderUDA10() { - return new RecoveringUDA10DeviceDescriptorBinderImpl(); - } - - @Override - protected ServiceDescriptorBinder createServiceDescriptorBinderUDA10() { - return new UDA10ServiceDescriptorBinderSAXImpl(); - } - - @Override - protected SOAPActionProcessor createSOAPActionProcessor() { - return new RecoveringSOAPActionProcessorImpl(); - } - - @Override - protected GENAEventProcessor createGENAEventProcessor() { - return new RecoveringGENAEventProcessorImpl(); - } - - @Override - public int getRegistryMaintenanceIntervalMillis() { - return 3000; // Preserve battery on Android, only run every 3 seconds - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpServiceImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpServiceImpl.java deleted file mode 100644 index 61a18bb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/android/AndroidUpnpServiceImpl.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.android; - -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.IBinder; -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.UpnpServiceImpl; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.registry.Registry; -import org.fourthline.cling.transport.Router; - -/** - * Provides a UPnP stack with Android configuration as an application service component. - *

- * Sends a search for all UPnP devices on instantiation. See the - * {@link org.fourthline.cling.android.AndroidUpnpService} interface for a usage example. - *

- *

- * Override the {@link #createRouter(org.fourthline.cling.UpnpServiceConfiguration, org.fourthline.cling.protocol.ProtocolFactory, android.content.Context)} - * and {@link #createConfiguration()} methods to customize the service. - * - * @author Christian Bauer - */ -public class AndroidUpnpServiceImpl extends Service { - - protected UpnpService upnpService; - protected Binder binder = new Binder(); - - /** - * Starts the UPnP service. - */ - @Override - public void onCreate() { - super.onCreate(); - - upnpService = new UpnpServiceImpl(createConfiguration()) { - - @Override - protected Router createRouter(ProtocolFactory protocolFactory, Registry registry) { - return AndroidUpnpServiceImpl.this.createRouter( - getConfiguration(), - protocolFactory, - AndroidUpnpServiceImpl.this - ); - } - - @Override - public synchronized void shutdown() { - // First have to remove the receiver, so Android won't complain about it leaking - // when the main UI thread exits. - ((AndroidRouter)getRouter()).unregisterBroadcastReceiver(); - - // Now we can concurrently run the Cling shutdown code, without occupying the - // Android main UI thread. This will complete probably after the main UI thread - // is done. - super.shutdown(true); - } - }; - } - - protected UpnpServiceConfiguration createConfiguration() { - return new AndroidUpnpServiceConfiguration(); - } - - protected AndroidRouter createRouter(UpnpServiceConfiguration configuration, - ProtocolFactory protocolFactory, - Context context) { - return new AndroidRouter(configuration, protocolFactory, context); - } - - @Override - public IBinder onBind(Intent intent) { - return binder; - } - - /** - * Stops the UPnP service, when the last Activity unbinds from this Service. - */ - @Override - public void onDestroy() { - upnpService.shutdown(); - super.onDestroy(); - } - - protected class Binder extends android.os.Binder implements AndroidUpnpService { - - public UpnpService get() { - return upnpService; - } - - public UpnpServiceConfiguration getConfiguration() { - return upnpService.getConfiguration(); - } - - public Registry getRegistry() { - return upnpService.getRegistry(); - } - - public ControlPoint getControlPoint() { - return upnpService.getControlPoint(); - } - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/android/FixedAndroidLogHandler.java b/clinglibrary/src/main/java/org/fourthline/cling/android/FixedAndroidLogHandler.java deleted file mode 100644 index 6d20e0e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/android/FixedAndroidLogHandler.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.fourthline.cling.android; - -import android.util.Log; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.logging.Formatter; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogRecord; - -/* -Taken from: http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/com/android/internal/logging/AndroidHandler.java;hb=c2ad241504fcaa12d4579d3b0b4038d1ca8d08c9 - */ -public class FixedAndroidLogHandler extends Handler { - /** - * Holds the formatter for all Android log handlers. - */ - private static final Formatter THE_FORMATTER = new Formatter() { - @Override - public String format(LogRecord r) { - Throwable thrown = r.getThrown(); - if (thrown != null) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - sw.write(r.getMessage()); - sw.write("\n"); - thrown.printStackTrace(pw); - pw.flush(); - return sw.toString(); - } else { - return r.getMessage(); - } - } - }; - - /** - * Constructs a new instance of the Android log handler. - */ - public FixedAndroidLogHandler() { - setFormatter(THE_FORMATTER); - } - - @Override - public void close() { - // No need to close, but must implement abstract method. - } - - @Override - public void flush() { - // No need to flush, but must implement abstract method. - } - - @Override - public void publish(LogRecord record) { - try { - int level = getAndroidLevel(record.getLevel()); - String tag = record.getLoggerName(); - - if (tag == null) { - // Anonymous logger. - tag = "null"; - } else { - // Tags must be <= 23 characters. - int length = tag.length(); - if (length > 23) { - // Most loggers use the full class name. Try dropping the - // package. - int lastPeriod = tag.lastIndexOf("."); - if (length - lastPeriod - 1 <= 23) { - tag = tag.substring(lastPeriod + 1); - } else { - // Use last 23 chars. - tag = tag.substring(tag.length() - 23); - } - } - } - - /* ############################################################################################ - - Instead of using the perfectly fine java.util.logging API for setting the - loggable levels, this call relies on a totally obscure "local.prop" file which you have to place on - your device. By default, if you do not have that file and if you do not execute some magic - "setprop" commands on your device, only INFO/WARN/ERROR is loggable. So whatever you do with - java.util.logging.Logger.setLevel(...) doesn't have any effect. The debug messages might arrive - here but they are dropped because you _also_ have to set the Android internal logging level with - the aforementioned magic switches. - - Also, consider that you have to understand how a JUL logger name is mapped to the "tag" of - the Android log. Basically, the whole cutting and cropping procedure above is what you have to - memorize if you want to log with JUL and configure Android for debug output. - - I actually admire the pure evil of this setup, even Mr. Ceki can learn something! - - Commenting out these lines makes it all work as expected: - - if (!Log.isLoggable(tag, level)) { - return; - } - - ############################################################################################### */ - - String message = getFormatter().format(record); - Log.println(level, tag, message); - } catch (RuntimeException e) { - Log.e("AndroidHandler", "Error logging message.", e); - } - } - - /** - * Converts a {@link java.util.logging.Logger} logging level into an Android one. - * - * @param level The {@link java.util.logging.Logger} logging level. - * - * @return The resulting Android logging level. - */ - static int getAndroidLevel(Level level) { - int value = level.intValue(); - if (value >= 1000) { // SEVERE - return Log.ERROR; - } else if (value >= 900) { // WARNING - return Log.WARN; - } else if (value >= 800) { // INFO - return Log.INFO; - } else { - return Log.DEBUG; - } - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/android/NetworkUtils.java b/clinglibrary/src/main/java/org/fourthline/cling/android/NetworkUtils.java deleted file mode 100644 index 6ea212e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/android/NetworkUtils.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.android; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import org.fourthline.cling.model.ModelUtil; - -import java.util.logging.Logger; - -/** - * Android network helpers. - * - * @author Michael Pujos - */ -public class NetworkUtils { - - final private static Logger log = Logger.getLogger(NetworkUtils.class.getName()); - - static public NetworkInfo getConnectedNetworkInfo(Context context) { - - ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - - NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); - if (networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected()) { - return networkInfo; - } - - networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); - if (networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected()) return networkInfo; - - networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); - if (networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected()) return networkInfo; - - networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIMAX); - if (networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected()) return networkInfo; - - networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_ETHERNET); - if (networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected()) return networkInfo; - - log.info("Could not find any connected network..."); - - return null; - } - - static public boolean isEthernet(NetworkInfo networkInfo) { - return isNetworkType(networkInfo, ConnectivityManager.TYPE_ETHERNET); - } - - static public boolean isWifi(NetworkInfo networkInfo) { - return isNetworkType(networkInfo, ConnectivityManager.TYPE_WIFI) || ModelUtil.ANDROID_EMULATOR; - } - - static public boolean isMobile(NetworkInfo networkInfo) { - return isNetworkType(networkInfo, ConnectivityManager.TYPE_MOBILE) || isNetworkType(networkInfo, ConnectivityManager.TYPE_WIMAX); - } - - static public boolean isNetworkType(NetworkInfo networkInfo, int type) { - return networkInfo != null && networkInfo.getType() == type; - } - - static public boolean isSSDPAwareNetwork(NetworkInfo networkInfo) { - return isWifi(networkInfo) || isEthernet(networkInfo); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/AllowedValueProvider.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/AllowedValueProvider.java deleted file mode 100644 index 8211b40..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/AllowedValueProvider.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding; - -/** - * @author Christian Bauer - */ -public interface AllowedValueProvider { - - public String[] getValues(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/AllowedValueRangeProvider.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/AllowedValueRangeProvider.java deleted file mode 100644 index 5f8a698..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/AllowedValueRangeProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding; - -/** - * @author Christian Bauer - */ -public interface AllowedValueRangeProvider { - - public long getMinimum(); - public long getMaximum(); - public long getStep(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/LocalServiceBinder.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/LocalServiceBinder.java deleted file mode 100644 index c0b4fee..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/LocalServiceBinder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding; - -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; - -/** - * Reads {@link org.fourthline.cling.model.meta.LocalService} metadata given a Java class. - * - * @author Christian Bauer - */ -public interface LocalServiceBinder { - - /** - * @param clazz The Java class that is the source of the service metadata. - * @return The produced metadata. - * @throws LocalServiceBindingException If binding failed. - */ - public LocalService read(Class clazz) throws LocalServiceBindingException; - - /** - * - * @param clazz The Java class that is the source of the service metadata. - * @param id The pre-defined identifier of the service. - * @param type The pre-defined type of the service. - * @param supportsQueryStateVariables true if the service should support the - * deprecated "query any state variable value" action. - * @param stringConvertibleTypes A list of Java classes which map directly to string-typed - * UPnP state variables. - * @return The produced metadata. - * @throws LocalServiceBindingException If binding failed. - */ - public LocalService read(Class clazz, ServiceId id, ServiceType type, - boolean supportsQueryStateVariables, Class[] stringConvertibleTypes) throws LocalServiceBindingException; -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/LocalServiceBindingException.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/LocalServiceBindingException.java deleted file mode 100644 index a211fee..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/LocalServiceBindingException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding; - -/** - * Thrown when reading/writing {@link org.fourthline.cling.model.meta.LocalService} metadata failed. - * - * @author Christian Bauer - */ -public class LocalServiceBindingException extends RuntimeException { - - public LocalServiceBindingException(String s) { - super(s); - } - - public LocalServiceBindingException(String s, Throwable throwable) { - super(s, throwable); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationActionBinder.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationActionBinder.java deleted file mode 100644 index fcb7028..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationActionBinder.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import org.fourthline.cling.binding.LocalServiceBindingException; -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.action.ActionExecutor; -import org.fourthline.cling.model.action.MethodActionExecutor; -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.meta.ActionArgument; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.profile.RemoteClientInfo; -import org.fourthline.cling.model.state.GetterStateVariableAccessor; -import org.fourthline.cling.model.state.StateVariableAccessor; -import org.fourthline.cling.model.types.Datatype; -import org.seamless.util.Reflections; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public class AnnotationActionBinder { - - private static Logger log = Logger.getLogger(AnnotationLocalServiceBinder.class.getName()); - - protected UpnpAction annotation; - protected Method method; - protected Map stateVariables; - protected Set stringConvertibleTypes; - - public AnnotationActionBinder(Method method, Map stateVariables, Set stringConvertibleTypes) { - this.annotation = method.getAnnotation(UpnpAction.class); - this.stateVariables = stateVariables; - this.method = method; - this.stringConvertibleTypes = stringConvertibleTypes; - } - - public UpnpAction getAnnotation() { - return annotation; - } - - public Map getStateVariables() { - return stateVariables; - } - - public Method getMethod() { - return method; - } - - public Set getStringConvertibleTypes() { - return stringConvertibleTypes; - } - - public Action appendAction(Map actions) throws LocalServiceBindingException { - - String name; - if (getAnnotation().name().length() != 0) { - name = getAnnotation().name(); - } else { - name = AnnotationLocalServiceBinder.toUpnpActionName(getMethod().getName()); - } - - log.fine("Creating action and executor: " + name); - - List inputArguments = createInputArguments(); - Map, StateVariableAccessor> outputArguments = createOutputArguments(); - - inputArguments.addAll(outputArguments.keySet()); - ActionArgument[] actionArguments = - inputArguments.toArray(new ActionArgument[inputArguments.size()]); - - Action action = new Action(name, actionArguments); - ActionExecutor executor = createExecutor(outputArguments); - - actions.put(action, executor); - return action; - } - - protected ActionExecutor createExecutor(Map, StateVariableAccessor> outputArguments) { - // TODO: Invent an annotation for this configuration - return new MethodActionExecutor(outputArguments, getMethod()); - } - - protected List createInputArguments() throws LocalServiceBindingException { - - List list = new ArrayList<>(); - - // Input arguments are always method parameters - int annotatedParams = 0; - Annotation[][] params = getMethod().getParameterAnnotations(); - for (int i = 0; i < params.length; i++) { - Annotation[] param = params[i]; - for (Annotation paramAnnotation : param) { - if (paramAnnotation instanceof UpnpInputArgument) { - UpnpInputArgument inputArgumentAnnotation = (UpnpInputArgument) paramAnnotation; - annotatedParams++; - - String argumentName = - inputArgumentAnnotation.name(); - - StateVariable stateVariable = - findRelatedStateVariable( - inputArgumentAnnotation.stateVariable(), - argumentName, - getMethod().getName() - ); - - if (stateVariable == null) { - throw new LocalServiceBindingException( - "Could not detected related state variable of argument: " + argumentName - ); - } - - validateType(stateVariable, getMethod().getParameterTypes()[i]); - - ActionArgument inputArgument = new ActionArgument( - argumentName, - inputArgumentAnnotation.aliases(), - stateVariable.getName(), - ActionArgument.Direction.IN - ); - - list.add(inputArgument); - } - } - } - // A method can't have any parameters that are not annotated with @UpnpInputArgument - we wouldn't know what - // value to pass when we invoke it later on... unless the last parameter is of type RemoteClientInfo - if (annotatedParams < getMethod().getParameterTypes().length - && !RemoteClientInfo.class.isAssignableFrom(method.getParameterTypes()[method.getParameterTypes().length-1])) { - throw new LocalServiceBindingException("Method has parameters that are not input arguments: " + getMethod().getName()); - } - - return list; - } - - protected Map, StateVariableAccessor> createOutputArguments() throws LocalServiceBindingException { - - Map, StateVariableAccessor> map = new LinkedHashMap<>(); // !!! Insertion order! - - UpnpAction actionAnnotation = getMethod().getAnnotation(UpnpAction.class); - if (actionAnnotation.out().length == 0) return map; - - boolean hasMultipleOutputArguments = actionAnnotation.out().length > 1; - - for (UpnpOutputArgument outputArgumentAnnotation : actionAnnotation.out()) { - - String argumentName = outputArgumentAnnotation.name(); - - StateVariable stateVariable = findRelatedStateVariable( - outputArgumentAnnotation.stateVariable(), - argumentName, - getMethod().getName() - ); - - // Might-just-work attempt, try the name of the getter - if (stateVariable == null && outputArgumentAnnotation.getterName().length() > 0) { - stateVariable = findRelatedStateVariable(null, null, outputArgumentAnnotation.getterName()); - } - - if (stateVariable == null) { - throw new LocalServiceBindingException( - "Related state variable not found for output argument: " + argumentName - ); - } - - StateVariableAccessor accessor = findOutputArgumentAccessor( - stateVariable, - outputArgumentAnnotation.getterName(), - hasMultipleOutputArguments - ); - - log.finer("Found related state variable for output argument '" + argumentName + "': " + stateVariable); - - ActionArgument outputArgument = new ActionArgument( - argumentName, - stateVariable.getName(), - ActionArgument.Direction.OUT, - !hasMultipleOutputArguments - ); - - map.put(outputArgument, accessor); - } - - return map; - } - - protected StateVariableAccessor findOutputArgumentAccessor(StateVariable stateVariable, String getterName, boolean multipleArguments) - throws LocalServiceBindingException { - - boolean isVoid = getMethod().getReturnType().equals(Void.TYPE); - - if (isVoid) { - - if (getterName != null && getterName.length() > 0) { - log.finer("Action method is void, will use getter method named: " + getterName); - - // Use the same class as the action method - Method getter = Reflections.getMethod(getMethod().getDeclaringClass(), getterName); - if (getter == null) - throw new LocalServiceBindingException( - "Declared getter method '" + getterName + "' not found on: " + getMethod().getDeclaringClass() - ); - - validateType(stateVariable, getter.getReturnType()); - - return new GetterStateVariableAccessor(getter); - - } else { - log.finer("Action method is void, trying to find existing accessor of related: " + stateVariable); - return getStateVariables().get(stateVariable); - } - - - } else if (getterName != null && getterName.length() > 0) { - log.finer("Action method is not void, will use getter method on returned instance: " + getterName); - - // Use the returned class - Method getter = Reflections.getMethod(getMethod().getReturnType(), getterName); - if (getter == null) - throw new LocalServiceBindingException( - "Declared getter method '" + getterName + "' not found on return type: " + getMethod().getReturnType() - ); - - validateType(stateVariable, getter.getReturnType()); - - return new GetterStateVariableAccessor(getter); - - } else if (!multipleArguments) { - log.finer("Action method is not void, will use the returned instance: " + getMethod().getReturnType()); - validateType(stateVariable, getMethod().getReturnType()); - } - - return null; - } - - protected StateVariable findRelatedStateVariable(String declaredName, String argumentName, String methodName) - throws LocalServiceBindingException { - - StateVariable relatedStateVariable = null; - - if (declaredName != null && declaredName.length() > 0) { - relatedStateVariable = getStateVariable(declaredName); - } - - if (relatedStateVariable == null && argumentName != null && argumentName.length() > 0) { - String actualName = AnnotationLocalServiceBinder.toUpnpStateVariableName(argumentName); - log.finer("Finding related state variable with argument name (converted to UPnP name): " + actualName); - relatedStateVariable = getStateVariable(argumentName); - } - - if (relatedStateVariable == null && argumentName != null && argumentName.length() > 0) { - // Try with A_ARG_TYPE prefix - String actualName = AnnotationLocalServiceBinder.toUpnpStateVariableName(argumentName); - actualName = Constants.ARG_TYPE_PREFIX + actualName; - log.finer("Finding related state variable with prefixed argument name (converted to UPnP name): " + actualName); - relatedStateVariable = getStateVariable(actualName); - } - - if (relatedStateVariable == null && methodName != null && methodName.length() > 0) { - // TODO: Well, this is often a nice shortcut but sometimes might have false positives - String methodPropertyName = Reflections.getMethodPropertyName(methodName); - if (methodPropertyName != null) { - log.finer("Finding related state variable with method property name: " + methodPropertyName); - relatedStateVariable = - getStateVariable( - AnnotationLocalServiceBinder.toUpnpStateVariableName(methodPropertyName) - ); - } - } - - return relatedStateVariable; - } - - protected void validateType(StateVariable stateVariable, Class type) throws LocalServiceBindingException { - - // Validate datatype as good as we can - // (for enums and other convertible types, the state variable type should be STRING) - - Datatype.Default expectedDefaultMapping = - ModelUtil.isStringConvertibleType(getStringConvertibleTypes(), type) - ? Datatype.Default.STRING - : Datatype.Default.getByJavaType(type); - - log.finer("Expecting '" + stateVariable + "' to match default mapping: " + expectedDefaultMapping); - - if (expectedDefaultMapping != null && - !stateVariable.getTypeDetails().getDatatype().isHandlingJavaType(expectedDefaultMapping.getJavaType())) { - - // TODO: Consider custom types?! - throw new LocalServiceBindingException( - "State variable '" + stateVariable + "' datatype can't handle action " + - "argument's Java type (change one): " + expectedDefaultMapping.getJavaType() - ); - - } else if (expectedDefaultMapping == null && stateVariable.getTypeDetails().getDatatype().getBuiltin() != null) { - throw new LocalServiceBindingException( - "State variable '" + stateVariable + "' should be custom datatype " + - "(action argument type is unknown Java type): " + type.getSimpleName() - ); - } - - log.finer("State variable matches required argument datatype (or can't be validated because it is custom)"); - } - - protected StateVariable getStateVariable(String name) { - for (StateVariable stateVariable : getStateVariables().keySet()) { - if (stateVariable.getName().equals(name)) { - return stateVariable; - } - } - return null; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationLocalServiceBinder.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationLocalServiceBinder.java deleted file mode 100644 index d857a8a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationLocalServiceBinder.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import org.fourthline.cling.binding.LocalServiceBinder; -import org.fourthline.cling.binding.LocalServiceBindingException; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.action.ActionExecutor; -import org.fourthline.cling.model.action.QueryStateVariableExecutor; -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.QueryStateVariableAction; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.state.FieldStateVariableAccessor; -import org.fourthline.cling.model.state.GetterStateVariableAccessor; -import org.fourthline.cling.model.state.StateVariableAccessor; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDAServiceId; -import org.fourthline.cling.model.types.UDAServiceType; -import org.fourthline.cling.model.types.csv.CSV; -import org.seamless.util.Reflections; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.net.URI; -import java.net.URL; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.Locale; -import java.util.logging.Logger; - -/** - * Reads {@link org.fourthline.cling.model.meta.LocalService} metadata from annotations. - * - * @author Christian Bauer - */ -public class AnnotationLocalServiceBinder implements LocalServiceBinder { - - private static Logger log = Logger.getLogger(AnnotationLocalServiceBinder.class.getName()); - - public LocalService read(Class clazz) throws LocalServiceBindingException { - log.fine("Reading and binding annotations of service implementation class: " + clazz); - - // Read the service ID and service type from the annotation - if (clazz.isAnnotationPresent(UpnpService.class)) { - - UpnpService annotation = clazz.getAnnotation(UpnpService.class); - UpnpServiceId idAnnotation = annotation.serviceId(); - UpnpServiceType typeAnnotation = annotation.serviceType(); - - ServiceId serviceId = idAnnotation.namespace().equals(UDAServiceId.DEFAULT_NAMESPACE) - ? new UDAServiceId(idAnnotation.value()) - : new ServiceId(idAnnotation.namespace(), idAnnotation.value()); - - ServiceType serviceType = typeAnnotation.namespace().equals(UDAServiceType.DEFAULT_NAMESPACE) - ? new UDAServiceType(typeAnnotation.value(), typeAnnotation.version()) - : new ServiceType(typeAnnotation.namespace(), typeAnnotation.value(), typeAnnotation.version()); - - boolean supportsQueryStateVariables = annotation.supportsQueryStateVariables(); - - Set stringConvertibleTypes = readStringConvertibleTypes(annotation.stringConvertibleTypes()); - - return read(clazz, serviceId, serviceType, supportsQueryStateVariables, stringConvertibleTypes); - } else { - throw new LocalServiceBindingException("Given class is not an @UpnpService"); - } - } - - public LocalService read(Class clazz, ServiceId id, ServiceType type, - boolean supportsQueryStateVariables, Class[] stringConvertibleTypes) throws LocalServiceBindingException { - return read(clazz, id, type, supportsQueryStateVariables, new HashSet<>(Arrays.asList(stringConvertibleTypes))); - } - - public LocalService read(Class clazz, ServiceId id, ServiceType type, - boolean supportsQueryStateVariables, Set stringConvertibleTypes) - throws LocalServiceBindingException { - - Map stateVariables = readStateVariables(clazz, stringConvertibleTypes); - Map actions = readActions(clazz, stateVariables, stringConvertibleTypes); - - // Special treatment of the state variable querying action - if (supportsQueryStateVariables) { - actions.put(new QueryStateVariableAction(), new QueryStateVariableExecutor()); - } - - try { - return new LocalService(type, id, actions, stateVariables, stringConvertibleTypes, supportsQueryStateVariables); - - } catch (ValidationException ex) { - log.severe("Could not validate device model: " + ex.toString()); - for (ValidationError validationError : ex.getErrors()) { - log.severe(validationError.toString()); - } - throw new LocalServiceBindingException("Validation of model failed, check the log"); - } - } - - protected Set readStringConvertibleTypes(Class[] declaredTypes) throws LocalServiceBindingException { - - for (Class stringConvertibleType : declaredTypes) { - if (!Modifier.isPublic(stringConvertibleType.getModifiers())) { - throw new LocalServiceBindingException( - "Declared string-convertible type must be public: " + stringConvertibleType - ); - } - try { - stringConvertibleType.getConstructor(String.class); - } catch (NoSuchMethodException ex) { - throw new LocalServiceBindingException( - "Declared string-convertible type needs a public single-argument String constructor: " + stringConvertibleType - ); - } - } - Set stringConvertibleTypes = new HashSet(Arrays.asList(declaredTypes)); - - // Some defaults - stringConvertibleTypes.add(URI.class); - stringConvertibleTypes.add(URL.class); - stringConvertibleTypes.add(CSV.class); - - return stringConvertibleTypes; - } - - protected Map readStateVariables(Class clazz, Set stringConvertibleTypes) - throws LocalServiceBindingException { - - Map map = new HashMap<>(); - - // State variables declared on the class - if (clazz.isAnnotationPresent(UpnpStateVariables.class)) { - UpnpStateVariables variables = clazz.getAnnotation(UpnpStateVariables.class); - for (UpnpStateVariable v : variables.value()) { - - if (v.name().length() == 0) - throw new LocalServiceBindingException("Class-level @UpnpStateVariable name attribute value required"); - - String javaPropertyName = toJavaStateVariableName(v.name()); - - Method getter = Reflections.getGetterMethod(clazz, javaPropertyName); - Field field = Reflections.getField(clazz, javaPropertyName); - - StateVariableAccessor accessor = null; - if (getter != null && field != null) { - accessor = variables.preferFields() ? - new FieldStateVariableAccessor(field) - : new GetterStateVariableAccessor(getter); - } else if (field != null) { - accessor = new FieldStateVariableAccessor(field); - } else if (getter != null) { - accessor = new GetterStateVariableAccessor(getter); - } else { - log.finer("No field or getter found for state variable, skipping accessor: " + v.name()); - } - - StateVariable stateVar = - new AnnotationStateVariableBinder(v, v.name(), accessor, stringConvertibleTypes) - .createStateVariable(); - - map.put(stateVar, accessor); - } - } - - // State variables declared on fields - for (Field field : Reflections.getFields(clazz, UpnpStateVariable.class)) { - - UpnpStateVariable svAnnotation = field.getAnnotation(UpnpStateVariable.class); - - StateVariableAccessor accessor = new FieldStateVariableAccessor(field); - - StateVariable stateVar = new AnnotationStateVariableBinder( - svAnnotation, - svAnnotation.name().length() == 0 - ? toUpnpStateVariableName(field.getName()) - : svAnnotation.name(), - accessor, - stringConvertibleTypes - ).createStateVariable(); - - map.put(stateVar, accessor); - } - - // State variables declared on getters - for (Method getter : Reflections.getMethods(clazz, UpnpStateVariable.class)) { - - String propertyName = Reflections.getMethodPropertyName(getter.getName()); - if (propertyName == null) { - throw new LocalServiceBindingException( - "Annotated method is not a getter method (: " + getter - ); - } - - if (getter.getParameterTypes().length > 0) - throw new LocalServiceBindingException( - "Getter method defined as @UpnpStateVariable can not have parameters: " + getter - ); - - UpnpStateVariable svAnnotation = getter.getAnnotation(UpnpStateVariable.class); - - StateVariableAccessor accessor = new GetterStateVariableAccessor(getter); - - StateVariable stateVar = new AnnotationStateVariableBinder( - svAnnotation, - svAnnotation.name().length() == 0 - ? - toUpnpStateVariableName(propertyName) - : svAnnotation.name(), - accessor, - stringConvertibleTypes - ).createStateVariable(); - - map.put(stateVar, accessor); - } - - return map; - } - - protected Map readActions(Class clazz, - Map stateVariables, - Set stringConvertibleTypes) - throws LocalServiceBindingException { - - Map map = new HashMap<>(); - - for (Method method : Reflections.getMethods(clazz, UpnpAction.class)) { - AnnotationActionBinder actionBinder = - new AnnotationActionBinder(method, stateVariables, stringConvertibleTypes); - Action action = actionBinder.appendAction(map); - if(isActionExcluded(action)) { - map.remove(action); - } - } - - return map; - } - - /** - * Override this method to exclude action/methods after they have been discovered. - */ - protected boolean isActionExcluded(Action action) { - return false; - } - - // TODO: I don't like the exceptions much, user has no idea what to do - - static String toUpnpStateVariableName(String javaName) { - if (javaName.length() < 1) { - throw new IllegalArgumentException("Variable name must be at least 1 character long"); - } - return javaName.substring(0, 1).toUpperCase(Locale.ROOT) + javaName.substring(1); - } - - static String toJavaStateVariableName(String upnpName) { - if (upnpName.length() < 1) { - throw new IllegalArgumentException("Variable name must be at least 1 character long"); - } - return upnpName.substring(0, 1).toLowerCase(Locale.ROOT) + upnpName.substring(1); - } - - - static String toUpnpActionName(String javaName) { - if (javaName.length() < 1) { - throw new IllegalArgumentException("Action name must be at least 1 character long"); - } - return javaName.substring(0, 1).toUpperCase(Locale.ROOT) + javaName.substring(1); - } - - static String toJavaActionName(String upnpName) { - if (upnpName.length() < 1) { - throw new IllegalArgumentException("Variable name must be at least 1 character long"); - } - return upnpName.substring(0, 1).toLowerCase(Locale.ROOT) + upnpName.substring(1); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationStateVariableBinder.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationStateVariableBinder.java deleted file mode 100644 index e3d050d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/AnnotationStateVariableBinder.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import org.fourthline.cling.binding.AllowedValueProvider; -import org.fourthline.cling.binding.AllowedValueRangeProvider; -import org.fourthline.cling.binding.LocalServiceBindingException; -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.meta.StateVariableAllowedValueRange; -import org.fourthline.cling.model.meta.StateVariableEventDetails; -import org.fourthline.cling.model.meta.StateVariableTypeDetails; -import org.fourthline.cling.model.state.StateVariableAccessor; -import org.fourthline.cling.model.types.Datatype; - -import java.util.Set; -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public class AnnotationStateVariableBinder { - - private static Logger log = Logger.getLogger(AnnotationLocalServiceBinder.class.getName()); - - protected UpnpStateVariable annotation; - protected String name; - protected StateVariableAccessor accessor; - protected Set stringConvertibleTypes; - - public AnnotationStateVariableBinder(UpnpStateVariable annotation, String name, - StateVariableAccessor accessor, Set stringConvertibleTypes) { - this.annotation = annotation; - this.name = name; - this.accessor = accessor; - this.stringConvertibleTypes = stringConvertibleTypes; - } - - public UpnpStateVariable getAnnotation() { - return annotation; - } - - public String getName() { - return name; - } - - public StateVariableAccessor getAccessor() { - return accessor; - } - - public Set getStringConvertibleTypes() { - return stringConvertibleTypes; - } - - protected StateVariable createStateVariable() throws LocalServiceBindingException { - - log.fine("Creating state variable '" + getName() + "' with accessor: " + getAccessor()); - - // Datatype - Datatype datatype = createDatatype(); - - // Default value - String defaultValue = createDefaultValue(datatype); - - // Allowed values - String[] allowedValues = null; - if (Datatype.Builtin.STRING.equals(datatype.getBuiltin())) { - - if (getAnnotation().allowedValueProvider() != void.class) { - allowedValues = getAllowedValuesFromProvider(); - } else if (getAnnotation().allowedValues().length > 0) { - allowedValues = getAnnotation().allowedValues(); - } else if (getAnnotation().allowedValuesEnum() != void.class) { - allowedValues = getAllowedValues(getAnnotation().allowedValuesEnum()); - } else if (getAccessor() != null && getAccessor().getReturnType().isEnum()) { - allowedValues = getAllowedValues(getAccessor().getReturnType()); - } else { - log.finer("Not restricting allowed values (of string typed state var): " + getName()); - } - - if (allowedValues != null && defaultValue != null) { - - // Check if the default value is an allowed value - boolean foundValue = false; - for (String s : allowedValues) { - if (s.equals(defaultValue)) { - foundValue = true; - break; - } - } - if (!foundValue) { - throw new LocalServiceBindingException( - "Default value '" + defaultValue + "' is not in allowed values of: " + getName() - ); - } - } - } - - // Allowed value range - StateVariableAllowedValueRange allowedValueRange = null; - if (Datatype.Builtin.isNumeric(datatype.getBuiltin())) { - - if (getAnnotation().allowedValueRangeProvider() != void.class) { - allowedValueRange = getAllowedRangeFromProvider(); - } else if (getAnnotation().allowedValueMinimum() > 0 || getAnnotation().allowedValueMaximum() > 0) { - allowedValueRange = getAllowedValueRange( - getAnnotation().allowedValueMinimum(), - getAnnotation().allowedValueMaximum(), - getAnnotation().allowedValueStep() - ); - } else { - log.finer("Not restricting allowed value range (of numeric typed state var): " + getName()); - } - - // Check if the default value is an allowed value - if (defaultValue != null && allowedValueRange != null) { - - long v; - try { - v = Long.valueOf(defaultValue); - } catch (Exception ex) { - throw new LocalServiceBindingException( - "Default value '" + defaultValue + "' is not numeric (for range checking) of: " + getName() - ); - } - - if (!allowedValueRange.isInRange(v)) { - throw new LocalServiceBindingException( - "Default value '" + defaultValue + "' is not in allowed range of: " + getName() - ); - } - } - } - - // Event details - boolean sendEvents = getAnnotation().sendEvents(); - if (sendEvents && getAccessor() == null) { - throw new LocalServiceBindingException( - "State variable sends events but has no accessor for field or getter: " + getName() - ); - } - - int eventMaximumRateMillis = 0; - int eventMinimumDelta = 0; - if (sendEvents) { - if (getAnnotation().eventMaximumRateMilliseconds() > 0) { - log.finer("Moderating state variable events using maximum rate (milliseconds): " + getAnnotation().eventMaximumRateMilliseconds()); - eventMaximumRateMillis = getAnnotation().eventMaximumRateMilliseconds(); - } - - if (getAnnotation().eventMinimumDelta() > 0 && Datatype.Builtin.isNumeric(datatype.getBuiltin())) { - // TODO: Doesn't consider floating point types! - log.finer("Moderating state variable events using minimum delta: " + getAnnotation().eventMinimumDelta()); - eventMinimumDelta = getAnnotation().eventMinimumDelta(); - } - } - - StateVariableTypeDetails typeDetails = - new StateVariableTypeDetails(datatype, defaultValue, allowedValues, allowedValueRange); - - StateVariableEventDetails eventDetails = - new StateVariableEventDetails(sendEvents, eventMaximumRateMillis, eventMinimumDelta); - - return new StateVariable(getName(), typeDetails, eventDetails); - } - - protected Datatype createDatatype() throws LocalServiceBindingException { - - String declaredDatatype = getAnnotation().datatype(); - - if (declaredDatatype.length() == 0 && getAccessor() != null) { - Class returnType = getAccessor().getReturnType(); - log.finer("Using accessor return type as state variable type: " + returnType); - - if (ModelUtil.isStringConvertibleType(getStringConvertibleTypes(), returnType)) { - // Enums and toString() convertible types are always state variables with type STRING - log.finer("Return type is string-convertible, using string datatype"); - return Datatype.Default.STRING.getBuiltinType().getDatatype(); - } else { - Datatype.Default defaultDatatype = Datatype.Default.getByJavaType(returnType); - if (defaultDatatype != null) { - log.finer("Return type has default UPnP datatype: " + defaultDatatype); - return defaultDatatype.getBuiltinType().getDatatype(); - } - } - } - - // We can also guess that if the allowed values are set then it's a string - if ((declaredDatatype == null || declaredDatatype.length() == 0) && - (getAnnotation().allowedValues().length > 0 || getAnnotation().allowedValuesEnum() != void.class)) { - log.finer("State variable has restricted allowed values, hence using 'string' datatype"); - declaredDatatype = "string"; - } - - // If we still don't have it, there is nothing more we can do - if (declaredDatatype == null || declaredDatatype.length() == 0) { - throw new LocalServiceBindingException("Could not detect datatype of state variable: " + getName()); - } - - log.finer("Trying to find built-in UPnP datatype for detected name: " + declaredDatatype); - - // Now try to find the actual UPnP datatype by mapping the Default to Builtin - Datatype.Builtin builtin = Datatype.Builtin.getByDescriptorName(declaredDatatype); - if (builtin != null) { - log.finer("Found built-in UPnP datatype: " + builtin); - return builtin.getDatatype(); - } else { - // TODO - throw new LocalServiceBindingException("No built-in UPnP datatype found, using CustomDataType (TODO: NOT IMPLEMENTED)"); - } - } - - protected String createDefaultValue(Datatype datatype) throws LocalServiceBindingException { - - // Next, the default value of the state variable, first the declared one - if (getAnnotation().defaultValue().length() != 0) { - // The declared default value needs to match the datatype - try { - datatype.valueOf(getAnnotation().defaultValue()); - log.finer("Found state variable default value: " + getAnnotation().defaultValue()); - return getAnnotation().defaultValue(); - } catch (Exception ex) { - throw new LocalServiceBindingException( - "Default value doesn't match datatype of state variable '" + getName() + "': " + ex.getMessage() - ); - } - } - - return null; - } - - protected String[] getAllowedValues(Class enumType) throws LocalServiceBindingException { - - if (!enumType.isEnum()) { - throw new LocalServiceBindingException("Allowed values type is not an Enum: " + enumType); - } - - log.finer("Restricting allowed values of state variable to Enum: " + getName()); - String[] allowedValueStrings = new String[enumType.getEnumConstants().length]; - for (int i = 0; i < enumType.getEnumConstants().length; i++) { - Object o = enumType.getEnumConstants()[i]; - if (o.toString().length() > 32) { - throw new LocalServiceBindingException( - "Allowed value string (that is, Enum constant name) is longer than 32 characters: " + o.toString() - ); - } - log.finer("Adding allowed value (converted to string): " + o.toString()); - allowedValueStrings[i] = o.toString(); - } - - return allowedValueStrings; - } - - protected StateVariableAllowedValueRange getAllowedValueRange(long min, - long max, - long step) throws LocalServiceBindingException { - if (max < min) { - throw new LocalServiceBindingException( - "Allowed value range maximum is smaller than minimum: " + getName() - ); - } - - return new StateVariableAllowedValueRange(min, max, step); - } - - protected String[] getAllowedValuesFromProvider() throws LocalServiceBindingException { - Class provider = getAnnotation().allowedValueProvider(); - if (!AllowedValueProvider.class.isAssignableFrom(provider)) - throw new LocalServiceBindingException( - "Allowed value provider is not of type " + AllowedValueProvider.class + ": " + getName() - ); - try { - return ((Class) provider).newInstance().getValues(); - } catch (Exception ex) { - throw new LocalServiceBindingException( - "Allowed value provider can't be instantiated: " + getName(), ex - ); - } - } - - protected StateVariableAllowedValueRange getAllowedRangeFromProvider() throws LocalServiceBindingException { - Class provider = getAnnotation().allowedValueRangeProvider(); - if (!AllowedValueRangeProvider.class.isAssignableFrom(provider)) - throw new LocalServiceBindingException( - "Allowed value range provider is not of type " + AllowedValueRangeProvider.class + ": " + getName() - ); - try { - AllowedValueRangeProvider providerInstance = - ((Class) provider).newInstance(); - return getAllowedValueRange( - providerInstance.getMinimum(), - providerInstance.getMaximum(), - providerInstance.getStep() - ); - } catch (Exception ex) { - throw new LocalServiceBindingException( - "Allowed value range provider can't be instantiated: " + getName(), ex - ); - } - } - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpAction.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpAction.java deleted file mode 100644 index 8d551bf..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpAction.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface UpnpAction { - - String name() default ""; - UpnpOutputArgument[] out() default {}; -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpInputArgument.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpInputArgument.java deleted file mode 100644 index 2c7c589..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpInputArgument.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Retention; -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - - -@Target({ElementType.PARAMETER}) -@Retention(RetentionPolicy.RUNTIME) -public @interface UpnpInputArgument { - - String name(); - String[] aliases() default {}; - String stateVariable() default ""; -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpOutputArgument.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpOutputArgument.java deleted file mode 100644 index ac3506c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpOutputArgument.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Retention; -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - - -@Target({ElementType.PARAMETER}) -@Retention(RetentionPolicy.RUNTIME) -public @interface UpnpOutputArgument { - - String name(); - String stateVariable() default ""; - String getterName() default ""; - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpService.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpService.java deleted file mode 100644 index 899f11f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpService.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Inherited -public @interface UpnpService { - - UpnpServiceId serviceId(); - UpnpServiceType serviceType(); - - boolean supportsQueryStateVariables() default true; - Class[] stringConvertibleTypes() default {}; -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpServiceId.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpServiceId.java deleted file mode 100644 index b81184a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpServiceId.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import org.fourthline.cling.model.types.UDAServiceId; - -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - - -@Target({}) -@Retention(RetentionPolicy.RUNTIME) -public @interface UpnpServiceId { - - String namespace() default UDAServiceId.DEFAULT_NAMESPACE; - String value(); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpServiceType.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpServiceType.java deleted file mode 100644 index 1e4dfec..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpServiceType.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import org.fourthline.cling.model.types.UDAServiceType; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -@Target({}) -@Retention(RetentionPolicy.RUNTIME) -public @interface UpnpServiceType { - - String namespace() default UDAServiceType.DEFAULT_NAMESPACE; - String value(); - int version() default 1; -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpStateVariable.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpStateVariable.java deleted file mode 100644 index de2128e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpStateVariable.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -@Target({ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface UpnpStateVariable { - - String name() default ""; - String datatype() default ""; - - String defaultValue() default ""; - - // String types - String[] allowedValues() default {}; - Class allowedValuesEnum() default void.class; - - // Numeric types - long allowedValueMinimum() default 0; - long allowedValueMaximum() default 0; - long allowedValueStep() default 1; - - // Dynamic - Class allowedValueProvider() default void.class; - Class allowedValueRangeProvider() default void.class; - - boolean sendEvents() default true; - int eventMaximumRateMilliseconds() default 0; - int eventMinimumDelta() default 0; - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpStateVariables.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpStateVariables.java deleted file mode 100644 index 4e16ccb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/annotations/UpnpStateVariables.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.annotations; - -import java.lang.annotation.Inherited; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Retention; -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - - -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Inherited -public @interface UpnpStateVariables { - - UpnpStateVariable[] value() default {}; - boolean preferFields() default true; - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableAction.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableAction.java deleted file mode 100644 index 20aa64a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableAction.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.staging; - -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.meta.ActionArgument; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class MutableAction { - - public String name; - public List arguments = new ArrayList<>(); - - public Action build() { - return new Action(name, createActionArgumennts()); - } - - public ActionArgument[] createActionArgumennts() { - ActionArgument[] array = new ActionArgument[arguments.size()]; - int i = 0; - for (MutableActionArgument argument : arguments) { - array[i++] = argument.build(); - } - return array; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableActionArgument.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableActionArgument.java deleted file mode 100644 index 0369b86..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableActionArgument.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.staging; - -import org.fourthline.cling.model.meta.ActionArgument; - -/** - * @author Christian Bauer - */ -public class MutableActionArgument { - - public String name; - public String relatedStateVariable; - public ActionArgument.Direction direction; - public boolean retval; - - public ActionArgument build() { - return new ActionArgument(name, relatedStateVariable, direction, retval); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableAllowedValueRange.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableAllowedValueRange.java deleted file mode 100644 index c87aede..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableAllowedValueRange.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.staging; - -/** - * @author Christian Bauer - */ -public class MutableAllowedValueRange { - - // TODO: UPNP VIOLATION: Some devices (Netgear Router again...) send empty elements, so use some sane defaults - // TODO: UPNP VIOLATION: The WANCommonInterfaceConfig example XML is even wrong, it does not include a element! - public Long minimum = 0l; - public Long maximum = Long.MAX_VALUE; - public Long step = 1l; - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableDevice.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableDevice.java deleted file mode 100644 index 3017524..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableDevice.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.staging; - -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.meta.DeviceDetails; -import org.fourthline.cling.model.meta.Icon; -import org.fourthline.cling.model.meta.ManufacturerDetails; -import org.fourthline.cling.model.meta.ModelDetails; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.meta.UDAVersion; -import org.fourthline.cling.model.types.DLNACaps; -import org.fourthline.cling.model.types.DLNADoc; -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.UDN; - -import java.net.URI; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class MutableDevice { - - public UDN udn; - public MutableUDAVersion udaVersion = new MutableUDAVersion(); - public URL baseURL; - public String deviceType; - public String friendlyName; - public String manufacturer; - public URI manufacturerURI; - public String modelName; - public String modelDescription; - public String modelNumber; - public URI modelURI; - public String serialNumber; - public String upc; - public URI presentationURI; - public List dlnaDocs = new ArrayList<>(); - public DLNACaps dlnaCaps; - public List icons = new ArrayList<>(); - public List services = new ArrayList<>(); - public List embeddedDevices = new ArrayList<>(); - public MutableDevice parentDevice; - - public Device build(Device prototype) throws ValidationException { - // Note how all embedded devices inherit the version and baseURL of the root! - return build(prototype, createDeviceVersion(), baseURL); - } - - public Device build(Device prototype, UDAVersion deviceVersion, URL baseURL) throws ValidationException { - - List embeddedDevicesList = new ArrayList<>(); - for (MutableDevice embeddedDevice : embeddedDevices) { - embeddedDevicesList.add(embeddedDevice.build(prototype, deviceVersion, baseURL)); - } - return prototype.newInstance( - udn, - deviceVersion, - createDeviceType(), - createDeviceDetails(baseURL), - createIcons(), - createServices(prototype), - embeddedDevicesList - ); - } - - public UDAVersion createDeviceVersion() { - return new UDAVersion(udaVersion.major, udaVersion.minor); - } - - public DeviceType createDeviceType() { - return DeviceType.valueOf(deviceType); - } - - public DeviceDetails createDeviceDetails(URL baseURL) { - return new DeviceDetails( - baseURL, - friendlyName, - new ManufacturerDetails(manufacturer, manufacturerURI), - new ModelDetails(modelName, modelDescription, modelNumber, modelURI), - serialNumber, upc, presentationURI, dlnaDocs.toArray(new DLNADoc[dlnaDocs.size()]), dlnaCaps - ); - } - - public Icon[] createIcons() { - Icon[] iconArray = new Icon[icons.size()]; - int i = 0; - for (MutableIcon icon : icons) { - iconArray[i++] = icon.build(); - } - return iconArray; - } - - public Service[] createServices(Device prototype) throws ValidationException { - Service[] services = prototype.newServiceArray(this.services.size()); - int i = 0; - for (MutableService service : this.services) { - services[i++] = service.build(prototype); - } - return services; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableIcon.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableIcon.java deleted file mode 100644 index b50b320..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableIcon.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.staging; - -import org.fourthline.cling.model.meta.Icon; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class MutableIcon { - - public String mimeType; - public int width; - public int height; - public int depth; - public URI uri; - - public Icon build() { - return new Icon(mimeType, width, height, depth, uri); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableService.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableService.java deleted file mode 100644 index 29c08c5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableService.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.staging; - -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class MutableService { - - public ServiceType serviceType; - public ServiceId serviceId; - public URI descriptorURI; - public URI controlURI; - public URI eventSubscriptionURI; - - public List actions = new ArrayList<>(); - public List stateVariables = new ArrayList<>(); - - public Service build(Device prototype) throws ValidationException { - return prototype.newInstance( - serviceType, serviceId, - descriptorURI, controlURI, eventSubscriptionURI, - createActions(), - createStateVariables() - ); - } - - public Action[] createActions() { - Action[] array = new Action[actions.size()]; - int i = 0; - for (MutableAction action : actions) { - array[i++] = action.build(); - } - return array; - } - - public StateVariable[] createStateVariables() { - StateVariable[] array = new StateVariable[stateVariables.size()]; - int i = 0; - for (MutableStateVariable stateVariable : stateVariables) { - array[i++] = stateVariable.build(); - } - return array; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableStateVariable.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableStateVariable.java deleted file mode 100644 index 7ab723a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableStateVariable.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.staging; - -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.meta.StateVariableAllowedValueRange; -import org.fourthline.cling.model.meta.StateVariableEventDetails; -import org.fourthline.cling.model.meta.StateVariableTypeDetails; -import org.fourthline.cling.model.types.Datatype; - -import java.util.List; - -/** - * @author Christian Bauer - */ -public class MutableStateVariable { - - public String name; - public Datatype dataType; - public String defaultValue; - public List allowedValues; - public MutableAllowedValueRange allowedValueRange; - public StateVariableEventDetails eventDetails; - - public StateVariable build() { - return new StateVariable( - name, - new StateVariableTypeDetails( - dataType, - defaultValue, - allowedValues == null || allowedValues.size() == 0 - ? null - : allowedValues.toArray(new String[allowedValues.size()]), - allowedValueRange == null - ? null : - new StateVariableAllowedValueRange( - allowedValueRange.minimum, - allowedValueRange.maximum, - allowedValueRange.step - ) - ), - eventDetails - ); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableUDAVersion.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableUDAVersion.java deleted file mode 100644 index 432ddbf..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/staging/MutableUDAVersion.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.staging; - -/** - * @author Christian Bauer - */ -public class MutableUDAVersion { - public int major = 1; - public int minor = 0; -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/Descriptor.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/Descriptor.java deleted file mode 100644 index 95b468e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/Descriptor.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.xml; - -import org.w3c.dom.Node; - -/** - * Utility interface with static declarations of all "strings". - * - * @author Christian Bauer - */ -public abstract class Descriptor { - - public interface Device { - - public static final String NAMESPACE_URI = "urn:schemas-upnp-org:device-1-0"; - public static final String DLNA_NAMESPACE_URI = "urn:schemas-dlna-org:device-1-0"; - public static final String DLNA_PREFIX = "dlna"; - public static final String SEC_NAMESPACE_URI = "http://www.sec.co.kr/dlna"; - public static final String SEC_PREFIX = "sec"; - - public enum ELEMENT { - root, - specVersion, major, minor, - URLBase, - device, - UDN, - X_DLNADOC, - X_DLNACAP, - ProductCap, - X_ProductCap, - deviceType, - friendlyName, - manufacturer, - manufacturerURL, - modelDescription, - modelName, - modelNumber, - modelURL, - presentationURL, - UPC, - serialNumber, - iconList, icon, width, height, depth, url, mimetype, - serviceList, service, serviceType, serviceId, SCPDURL, controlURL, eventSubURL, - deviceList; - - public static ELEMENT valueOrNullOf(String s) { - try { - return valueOf(s); - } catch (IllegalArgumentException ex) { - return null; - } - } - - public boolean equals(Node node) { - return toString().equals(node.getLocalName()); - } - } - } - - public interface Service { - - public static final String NAMESPACE_URI = "urn:schemas-upnp-org:service-1-0"; - - public enum ELEMENT { - scpd, - specVersion, major, minor, - actionList, action, name, - argumentList, argument, direction, relatedStateVariable, retval, - serviceStateTable, stateVariable, dataType, defaultValue, - allowedValueList, allowedValue, allowedValueRange, minimum, maximum, step; - - public static ELEMENT valueOrNullOf(String s) { - try { - return valueOf(s); - } catch (IllegalArgumentException ex) { - return null; - } - } - - public boolean equals(Node node) { - return toString().equals(node.getLocalName()); - } - - } - - public enum ATTRIBUTE { - sendEvents - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/DescriptorBindingException.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/DescriptorBindingException.java deleted file mode 100644 index f36f51f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/DescriptorBindingException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.xml; - -/** - * Thrown if device or service descriptor metadata couldn't be read or written. - * - * @author Christian Bauer - */ -public class DescriptorBindingException extends Exception { - - public DescriptorBindingException(String s) { - super(s); - } - - public DescriptorBindingException(String s, Throwable throwable) { - super(s, throwable); - } -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/DeviceDescriptorBinder.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/DeviceDescriptorBinder.java deleted file mode 100644 index 4c4a5cf..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/DeviceDescriptorBinder.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.xml; - -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.profile.RemoteClientInfo; -import org.w3c.dom.Document; - -/** - * Reads and generates device descriptor XML metadata. - * - * @author Christian Bauer - */ -public interface DeviceDescriptorBinder { - - public T describe(T undescribedDevice, String descriptorXml) - throws DescriptorBindingException, ValidationException; - - public T describe(T undescribedDevice, Document dom) - throws DescriptorBindingException, ValidationException; - - public String generate(Device device, RemoteClientInfo info, Namespace namespace) throws DescriptorBindingException; - - public Document buildDOM(Device device, RemoteClientInfo info, Namespace namespace) throws DescriptorBindingException; - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/RecoveringUDA10DeviceDescriptorBinderImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/RecoveringUDA10DeviceDescriptorBinderImpl.java deleted file mode 100644 index 00c5f6e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/RecoveringUDA10DeviceDescriptorBinderImpl.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.xml; - -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.meta.Device; -import org.seamless.util.Exceptions; -import org.seamless.xml.ParserException; -import org.seamless.xml.XmlPullParserUtils; -import org.xml.sax.SAXParseException; - -import java.util.Locale; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @author Michael Pujos - */ -public class RecoveringUDA10DeviceDescriptorBinderImpl extends UDA10DeviceDescriptorBinderImpl { - - private static Logger log = Logger.getLogger(RecoveringUDA10DeviceDescriptorBinderImpl.class.getName()); - - @Override - public D describe(D undescribedDevice, String descriptorXml) throws DescriptorBindingException, ValidationException { - - D device = null; - DescriptorBindingException originalException; - try { - - try { - if (descriptorXml != null) - descriptorXml = descriptorXml.trim(); // Always trim whitespace - device = super.describe(undescribedDevice, descriptorXml); - return device; - } catch (DescriptorBindingException ex) { - log.warning("Regular parsing failed: " + Exceptions.unwrap(ex).getMessage()); - originalException = ex; - } - - String fixedXml; - // The following modifications are not cumulative! - - fixedXml = fixGarbageLeadingChars(descriptorXml); - if (fixedXml != null) { - try { - device = super.describe(undescribedDevice, fixedXml); - return device; - } catch (DescriptorBindingException ex) { - log.warning("Removing leading garbage didn't work: " + Exceptions.unwrap(ex).getMessage()); - } - } - - fixedXml = fixGarbageTrailingChars(descriptorXml, originalException); - if (fixedXml != null) { - try { - device = super.describe(undescribedDevice, fixedXml); - return device; - } catch (DescriptorBindingException ex) { - log.warning("Removing trailing garbage didn't work: " + Exceptions.unwrap(ex).getMessage()); - } - } - - // Try to fix "up to five" missing namespace declarations - DescriptorBindingException lastException = originalException; - fixedXml = descriptorXml; - for (int retryCount = 0; retryCount < 5; retryCount++) { - fixedXml = fixMissingNamespaces(fixedXml, lastException); - if (fixedXml != null) { - try { - device = super.describe(undescribedDevice, fixedXml); - return device; - } catch (DescriptorBindingException ex) { - log.warning("Fixing namespace prefix didn't work: " + Exceptions.unwrap(ex).getMessage()); - lastException = ex; - } - } else { - break; // We can stop, no more namespace fixing can be done - } - } - - fixedXml = XmlPullParserUtils.fixXMLEntities(descriptorXml); - if(!fixedXml.equals(descriptorXml)) { - try { - device = super.describe(undescribedDevice, fixedXml); - return device; - } catch (DescriptorBindingException ex) { - log.warning("Fixing XML entities didn't work: " + Exceptions.unwrap(ex).getMessage()); - } - } - - handleInvalidDescriptor(descriptorXml, originalException); - - } catch (ValidationException ex) { - device = handleInvalidDevice(descriptorXml, device, ex); - if (device != null) - return device; - } - throw new IllegalStateException("No device produced, did you swallow exceptions in your subclass?"); - } - - private String fixGarbageLeadingChars(String descriptorXml) { - /* Recover this: - - HTTP/1.1 200 OK - Content-Length: 4268 - Content-Type: text/xml; charset="utf-8" - Server: Microsoft-Windows/6.2 UPnP/1.0 UPnP-Device-Host/1.0 Microsoft-HTTPAPI/2.0 - Date: Sun, 07 Apr 2013 02:11:30 GMT - - @7:5 in java.io.StringReader@407f6b00) : HTTP/1.1 200 OK - Content-Length: 4268 - Content-Type: text/xml; charset="utf-8" - Server: Microsoft-Windows/6.2 UPnP/1.0 UPnP-Device-Host/1.0 Microsoft-HTTPAPI/2.0 - Date: Sun, 07 Apr 2013 02:11:30 GMT - - ... - */ - - int index = descriptorXml.indexOf(""); - if (index == -1) { - log.warning("No closing element in descriptor"); - return null; - } - if (descriptorXml.length() != index + "".length()) { - log.warning("Detected garbage characters after node, removing"); - return descriptorXml.substring(0, index) + ""; - } - return null; - } - - protected String fixMissingNamespaces(String descriptorXml, DescriptorBindingException ex) { - // Windows: org.fourthline.cling.binding.xml.DescriptorBindingException: Could not parse device descriptor: org.seamless.xml.ParserException: org.xml.sax.SAXParseException: The prefix "dlna" for element "dlna:X_DLNADOC" is not bound. - // Android: org.xmlpull.v1.XmlPullParserException: undefined prefix: dlna (position:START_TAG <{null}dlna:X_DLNADOC>@19:17 in java.io.StringReader@406dff48) - - // We can only handle certain exceptions, depending on their type and message - Throwable cause = ex.getCause(); - if (!((cause instanceof SAXParseException) || (cause instanceof ParserException))) - return null; - String message = cause.getMessage(); - if (message == null) - return null; - - Pattern pattern = Pattern.compile("The prefix \"(.*)\" for element"); // Windows - Matcher matcher = pattern.matcher(message); - if (!matcher.find() || matcher.groupCount() != 1) { - pattern = Pattern.compile("undefined prefix: ([^ ]*)"); // Android - matcher = pattern.matcher(message); - if (!matcher.find() || matcher.groupCount() != 1) - return null; - } - - String missingNS = matcher.group(1); - log.warning("Fixing missing namespace declaration for: " + missingNS); - - // Extract attributes - pattern = Pattern.compile("]*)"); - matcher = pattern.matcher(descriptorXml); - if (!matcher.find() || matcher.groupCount() != 1) { - log.fine("Could not find element attributes"); - return null; - } - - String rootAttributes = matcher.group(1); - log.fine("Preserving existing element attributes/namespace declarations: " + matcher.group(0)); - - // Extract body - pattern = Pattern.compile("]*>(.*)", Pattern.DOTALL); - matcher = pattern.matcher(descriptorXml); - if (!matcher.find() || matcher.groupCount() != 1) { - log.fine("Could not extract body of element"); - return null; - } - - String rootBody = matcher.group(1); - - // Add missing namespace, it only matters that it is defined, not that it is correct - return "" - + "" - + rootBody - + ""; - - // TODO: Should we match different undeclared prefixes with their correct namespace? - // So if it's "dlna" we use "urn:schemas-dlna-org:device-1-0" etc. - } - - /** - * Handle processing errors while reading XML descriptors. - *

- *

- * Typically you want to log this problem or create an error report, and in any - * case, throw a {@link DescriptorBindingException} to notify the caller of the - * binder of this failure. The default implementation simply rethrows the - * given exception. - *

- * - * @param xml The original XML causing the parsing failure. - * @param exception The original exception while parsing the XML. - */ - protected void handleInvalidDescriptor(String xml, DescriptorBindingException exception) - throws DescriptorBindingException { - throw exception; - } - - /** - * Handle processing errors while binding XML descriptors. - *

- *

- * Typically you want to log this problem or create an error report. You - * should throw a {@link ValidationException} to notify the caller of the - * binder of failure. The default implementation simply rethrows the - * given exception. - *

- *

- * This method gives you a final chance to fix the problem, instead of - * throwing an exception, you could try to create valid {@link Device} - * model and return it. - *

- * - * @param xml The original XML causing the binding failure. - * @param device The unfinished {@link Device} that failed validation - * @param exception The errors found when validating the {@link Device} model. - * @return Device A "fixed" {@link Device} model, instead of throwing an exception. - */ - protected D handleInvalidDevice(String xml, D device, ValidationException exception) - throws ValidationException { - throw exception; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/ServiceDescriptorBinder.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/ServiceDescriptorBinder.java deleted file mode 100644 index 6e5545f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/ServiceDescriptorBinder.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.xml; - -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.meta.Service; -import org.w3c.dom.Document; - -/** - * Reads and generates service descriptor XML metadata. - * - * @author Christian Bauer - */ -public interface ServiceDescriptorBinder { - - public T describe(T undescribedService, String descriptorXml) - throws DescriptorBindingException, ValidationException; - - public T describe(T undescribedService, Document dom) - throws DescriptorBindingException, ValidationException; - - public String generate(Service service) throws DescriptorBindingException; - - public Document buildDOM(Service service) throws DescriptorBindingException; -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10DeviceDescriptorBinderImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10DeviceDescriptorBinderImpl.java deleted file mode 100644 index 9359fb3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10DeviceDescriptorBinderImpl.java +++ /dev/null @@ -1,626 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.xml; - -import static org.fourthline.cling.model.XMLUtil.appendNewElement; -import static org.fourthline.cling.model.XMLUtil.appendNewElementIfNotNull; - -import java.io.StringReader; -import java.net.URI; -import java.net.URL; -import java.util.logging.Logger; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.fourthline.cling.binding.staging.MutableDevice; -import org.fourthline.cling.binding.staging.MutableIcon; -import org.fourthline.cling.binding.staging.MutableService; -import org.fourthline.cling.binding.xml.Descriptor.Device.ELEMENT; -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.XMLUtil; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.meta.DeviceDetails; -import org.fourthline.cling.model.meta.Icon; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.RemoteDevice; -import org.fourthline.cling.model.meta.RemoteService; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.profile.RemoteClientInfo; -import org.fourthline.cling.model.types.DLNACaps; -import org.fourthline.cling.model.types.DLNADoc; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; -import org.seamless.util.Exceptions; -import org.seamless.util.MimeType; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -/** - * Implementation based on JAXP DOM. - * - * @author Christian Bauer - */ -public class UDA10DeviceDescriptorBinderImpl implements DeviceDescriptorBinder, ErrorHandler { - - private static Logger log = Logger.getLogger(DeviceDescriptorBinder.class.getName()); - - public D describe(D undescribedDevice, String descriptorXml) throws DescriptorBindingException, ValidationException { - - if (descriptorXml == null || descriptorXml.length() == 0) { - throw new DescriptorBindingException("Null or empty descriptor"); - } - - try { - log.fine("Populating device from XML descriptor: " + undescribedDevice); - // We can not validate the XML document. There is no possible XML schema (maybe RELAX NG) that would properly - // constrain the UDA 1.0 device descriptor documents: Any unknown element or attribute must be ignored, order of elements - // is not guaranteed. Try to write a schema for that! No combination of and - // works with that... But hey, MSFT sure has great tech guys! So what we do here is just parsing out the known elements - // and ignoring the other shit. We'll also do some very very basic validation of required elements, but that's it. - - // And by the way... try this with JAXB instead of manual DOM processing! And you thought it couldn't get worse.... - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - DocumentBuilder documentBuilder = factory.newDocumentBuilder(); - documentBuilder.setErrorHandler(this); - - Document d = documentBuilder.parse( - new InputSource( - // TODO: UPNP VIOLATION: Virgin Media Superhub sends trailing spaces/newlines after last XML element, need to trim() - new StringReader(descriptorXml.trim()) - ) - ); - - return describe(undescribedDevice, d); - - } catch (ValidationException ex) { - throw ex; - } catch (Exception ex) { - throw new DescriptorBindingException("Could not parse device descriptor: " + ex.toString(), ex); - } - } - - public D describe(D undescribedDevice, Document dom) throws DescriptorBindingException, ValidationException { - try { - log.fine("Populating device from DOM: " + undescribedDevice); - - // Read the XML into a mutable descriptor graph - MutableDevice descriptor = new MutableDevice(); - Element rootElement = dom.getDocumentElement(); - hydrateRoot(descriptor, rootElement); - - // Build the immutable descriptor graph - return buildInstance(undescribedDevice, descriptor); - - } catch (ValidationException ex) { - throw ex; - } catch (Exception ex) { - throw new DescriptorBindingException("Could not parse device DOM: " + ex.toString(), ex); - } - } - - public D buildInstance(D undescribedDevice, MutableDevice descriptor) throws ValidationException { - return (D) descriptor.build(undescribedDevice); - } - - protected void hydrateRoot(MutableDevice descriptor, Element rootElement) throws DescriptorBindingException { - - if (rootElement.getNamespaceURI() == null || !rootElement.getNamespaceURI().equals(Descriptor.Device.NAMESPACE_URI)) { - log.warning("Wrong XML namespace declared on root element: " + rootElement.getNamespaceURI()); - } - - if (!rootElement.getNodeName().equals(ELEMENT.root.name())) { - throw new DescriptorBindingException("Root element name is not : " + rootElement.getNodeName()); - } - - NodeList rootChildren = rootElement.getChildNodes(); - - Node deviceNode = null; - - for (int i = 0; i < rootChildren.getLength(); i++) { - Node rootChild = rootChildren.item(i); - - if (rootChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.specVersion.equals(rootChild)) { - hydrateSpecVersion(descriptor, rootChild); - } else if (ELEMENT.URLBase.equals(rootChild)) { - try { - String urlString = XMLUtil.getTextContent(rootChild); - if (urlString != null && urlString.length() > 0) { - // We hope it's RFC 2396 and RFC 2732 compliant - descriptor.baseURL = new URL(urlString); - } - } catch (Exception ex) { - throw new DescriptorBindingException("Invalid URLBase: " + ex.getMessage()); - } - } else if (ELEMENT.device.equals(rootChild)) { - // Just sanity check here... - if (deviceNode != null) - throw new DescriptorBindingException("Found multiple elements in "); - deviceNode = rootChild; - } else { - log.finer("Ignoring unknown element: " + rootChild.getNodeName()); - } - } - - if (deviceNode == null) { - throw new DescriptorBindingException("No element in "); - } - hydrateDevice(descriptor, deviceNode); - } - - public void hydrateSpecVersion(MutableDevice descriptor, Node specVersionNode) throws DescriptorBindingException { - - NodeList specVersionChildren = specVersionNode.getChildNodes(); - for (int i = 0; i < specVersionChildren.getLength(); i++) { - Node specVersionChild = specVersionChildren.item(i); - - if (specVersionChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.major.equals(specVersionChild)) { - String version = XMLUtil.getTextContent(specVersionChild).trim(); - if (!version.equals("1")) { - log.warning("Unsupported UDA major version, ignoring: " + version); - version = "1"; - } - descriptor.udaVersion.major = Integer.valueOf(version); - } else if (ELEMENT.minor.equals(specVersionChild)) { - String version = XMLUtil.getTextContent(specVersionChild).trim(); - if (!version.equals("0")) { - log.warning("Unsupported UDA minor version, ignoring: " + version); - version = "0"; - } - descriptor.udaVersion.minor = Integer.valueOf(version); - } - - } - - } - - public void hydrateDevice(MutableDevice descriptor, Node deviceNode) throws DescriptorBindingException { - - NodeList deviceNodeChildren = deviceNode.getChildNodes(); - for (int i = 0; i < deviceNodeChildren.getLength(); i++) { - Node deviceNodeChild = deviceNodeChildren.item(i); - - if (deviceNodeChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.deviceType.equals(deviceNodeChild)) { - descriptor.deviceType = XMLUtil.getTextContent(deviceNodeChild); - } else if (ELEMENT.friendlyName.equals(deviceNodeChild)) { - descriptor.friendlyName = XMLUtil.getTextContent(deviceNodeChild); - } else if (ELEMENT.manufacturer.equals(deviceNodeChild)) { - descriptor.manufacturer = XMLUtil.getTextContent(deviceNodeChild); - } else if (ELEMENT.manufacturerURL.equals(deviceNodeChild)) { - descriptor.manufacturerURI = parseURI(XMLUtil.getTextContent(deviceNodeChild)); - } else if (ELEMENT.modelDescription.equals(deviceNodeChild)) { - descriptor.modelDescription = XMLUtil.getTextContent(deviceNodeChild); - } else if (ELEMENT.modelName.equals(deviceNodeChild)) { - descriptor.modelName = XMLUtil.getTextContent(deviceNodeChild); - } else if (ELEMENT.modelNumber.equals(deviceNodeChild)) { - descriptor.modelNumber = XMLUtil.getTextContent(deviceNodeChild); - } else if (ELEMENT.modelURL.equals(deviceNodeChild)) { - descriptor.modelURI = parseURI(XMLUtil.getTextContent(deviceNodeChild)); - } else if (ELEMENT.presentationURL.equals(deviceNodeChild)) { - descriptor.presentationURI = parseURI(XMLUtil.getTextContent(deviceNodeChild)); - } else if (ELEMENT.UPC.equals(deviceNodeChild)) { - descriptor.upc = XMLUtil.getTextContent(deviceNodeChild); - } else if (ELEMENT.serialNumber.equals(deviceNodeChild)) { - descriptor.serialNumber = XMLUtil.getTextContent(deviceNodeChild); - } else if (ELEMENT.UDN.equals(deviceNodeChild)) { - descriptor.udn = UDN.valueOf(XMLUtil.getTextContent(deviceNodeChild)); - } else if (ELEMENT.iconList.equals(deviceNodeChild)) { - hydrateIconList(descriptor, deviceNodeChild); - } else if (ELEMENT.serviceList.equals(deviceNodeChild)) { - hydrateServiceList(descriptor, deviceNodeChild); - } else if (ELEMENT.deviceList.equals(deviceNodeChild)) { - hydrateDeviceList(descriptor, deviceNodeChild); - } else if (ELEMENT.X_DLNADOC.equals(deviceNodeChild) && - Descriptor.Device.DLNA_PREFIX.equals(deviceNodeChild.getPrefix())) { - String txt = XMLUtil.getTextContent(deviceNodeChild); - try { - descriptor.dlnaDocs.add(DLNADoc.valueOf(txt)); - } catch (InvalidValueException ex) { - log.info("Invalid X_DLNADOC value, ignoring value: " + txt); - } - } else if (ELEMENT.X_DLNACAP.equals(deviceNodeChild) && - Descriptor.Device.DLNA_PREFIX.equals(deviceNodeChild.getPrefix())) { - descriptor.dlnaCaps = DLNACaps.valueOf(XMLUtil.getTextContent(deviceNodeChild)); - } - } - } - - public void hydrateIconList(MutableDevice descriptor, Node iconListNode) throws DescriptorBindingException { - - NodeList iconListNodeChildren = iconListNode.getChildNodes(); - for (int i = 0; i < iconListNodeChildren.getLength(); i++) { - Node iconListNodeChild = iconListNodeChildren.item(i); - - if (iconListNodeChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.icon.equals(iconListNodeChild)) { - - MutableIcon icon = new MutableIcon(); - - NodeList iconChildren = iconListNodeChild.getChildNodes(); - - for (int x = 0; x < iconChildren.getLength(); x++) { - Node iconChild = iconChildren.item(x); - - if (iconChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.width.equals(iconChild)) { - icon.width = (Integer.valueOf(XMLUtil.getTextContent(iconChild))); - } else if (ELEMENT.height.equals(iconChild)) { - icon.height = (Integer.valueOf(XMLUtil.getTextContent(iconChild))); - } else if (ELEMENT.depth.equals(iconChild)) { - String depth = XMLUtil.getTextContent(iconChild); - try { - icon.depth = (Integer.valueOf(depth)); - } catch(NumberFormatException ex) { - log.warning("Invalid icon depth '" + depth + "', using 16 as default: " + ex); - icon.depth = 16; - } - } else if (ELEMENT.url.equals(iconChild)) { - icon.uri = parseURI(XMLUtil.getTextContent(iconChild)); - } else if (ELEMENT.mimetype.equals(iconChild)) { - try { - icon.mimeType = XMLUtil.getTextContent(iconChild); - MimeType.valueOf(icon.mimeType); - } catch(IllegalArgumentException ex) { - log.warning("Ignoring invalid icon mime type: " + icon.mimeType); - icon.mimeType = ""; - } - } - - } - - descriptor.icons.add(icon); - } - } - } - - public void hydrateServiceList(MutableDevice descriptor, Node serviceListNode) throws DescriptorBindingException { - - NodeList serviceListNodeChildren = serviceListNode.getChildNodes(); - for (int i = 0; i < serviceListNodeChildren.getLength(); i++) { - Node serviceListNodeChild = serviceListNodeChildren.item(i); - - if (serviceListNodeChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.service.equals(serviceListNodeChild)) { - - NodeList serviceChildren = serviceListNodeChild.getChildNodes(); - - try { - MutableService service = new MutableService(); - - for (int x = 0; x < serviceChildren.getLength(); x++) { - Node serviceChild = serviceChildren.item(x); - - if (serviceChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.serviceType.equals(serviceChild)) { - service.serviceType = (ServiceType.valueOf(XMLUtil.getTextContent(serviceChild))); - } else if (ELEMENT.serviceId.equals(serviceChild)) { - service.serviceId = (ServiceId.valueOf(XMLUtil.getTextContent(serviceChild))); - } else if (ELEMENT.SCPDURL.equals(serviceChild)) { - service.descriptorURI = parseURI(XMLUtil.getTextContent(serviceChild)); - } else if (ELEMENT.controlURL.equals(serviceChild)) { - service.controlURI = parseURI(XMLUtil.getTextContent(serviceChild)); - } else if (ELEMENT.eventSubURL.equals(serviceChild)) { - service.eventSubscriptionURI = parseURI(XMLUtil.getTextContent(serviceChild)); - } - - } - - descriptor.services.add(service); - } catch (InvalidValueException ex) { - log.warning( - "UPnP specification violation, skipping invalid service declaration. " + ex.getMessage() - ); - } - } - } - } - - public void hydrateDeviceList(MutableDevice descriptor, Node deviceListNode) throws DescriptorBindingException { - - NodeList deviceListNodeChildren = deviceListNode.getChildNodes(); - for (int i = 0; i < deviceListNodeChildren.getLength(); i++) { - Node deviceListNodeChild = deviceListNodeChildren.item(i); - - if (deviceListNodeChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.device.equals(deviceListNodeChild)) { - MutableDevice embeddedDevice = new MutableDevice(); - embeddedDevice.parentDevice = descriptor; - descriptor.embeddedDevices.add(embeddedDevice); - hydrateDevice(embeddedDevice, deviceListNodeChild); - } - } - - } - - public String generate(Device deviceModel, RemoteClientInfo info, Namespace namespace) throws DescriptorBindingException { - try { - log.fine("Generating XML descriptor from device model: " + deviceModel); - - return XMLUtil.documentToString(buildDOM(deviceModel, info, namespace)); - - } catch (Exception ex) { - throw new DescriptorBindingException("Could not build DOM: " + ex.getMessage(), ex); - } - } - - public Document buildDOM(Device deviceModel, RemoteClientInfo info, Namespace namespace) throws DescriptorBindingException { - - try { - log.fine("Generating DOM from device model: " + deviceModel); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - - Document d = factory.newDocumentBuilder().newDocument(); - generateRoot(namespace, deviceModel, d, info); - - return d; - - } catch (Exception ex) { - throw new DescriptorBindingException("Could not generate device descriptor: " + ex.getMessage(), ex); - } - } - - protected void generateRoot(Namespace namespace, Device deviceModel, Document descriptor, RemoteClientInfo info) { - - Element rootElement = descriptor.createElementNS(Descriptor.Device.NAMESPACE_URI, ELEMENT.root.toString()); - descriptor.appendChild(rootElement); - - generateSpecVersion(namespace, deviceModel, descriptor, rootElement); - - /* UDA 1.1 spec says: Don't use URLBase anymore - if (deviceModel.getBaseURL() != null) { - appendChildElementWithTextContent(descriptor, rootElement, "URLBase", deviceModel.getBaseURL()); - } - */ - - generateDevice(namespace, deviceModel, descriptor, rootElement, info); - } - - protected void generateSpecVersion(Namespace namespace, Device deviceModel, Document descriptor, Element rootElement) { - Element specVersionElement = appendNewElement(descriptor, rootElement, ELEMENT.specVersion); - appendNewElementIfNotNull(descriptor, specVersionElement, ELEMENT.major, deviceModel.getVersion().getMajor()); - appendNewElementIfNotNull(descriptor, specVersionElement, ELEMENT.minor, deviceModel.getVersion().getMinor()); - } - - protected void generateDevice(Namespace namespace, Device deviceModel, Document descriptor, Element rootElement, RemoteClientInfo info) { - - Element deviceElement = appendNewElement(descriptor, rootElement, ELEMENT.device); - - appendNewElementIfNotNull(descriptor, deviceElement, ELEMENT.deviceType, deviceModel.getType()); - - DeviceDetails deviceModelDetails = deviceModel.getDetails(info); - appendNewElementIfNotNull( - descriptor, deviceElement, ELEMENT.friendlyName, - deviceModelDetails.getFriendlyName() - ); - if (deviceModelDetails.getManufacturerDetails() != null) { - appendNewElementIfNotNull( - descriptor, deviceElement, ELEMENT.manufacturer, - deviceModelDetails.getManufacturerDetails().getManufacturer() - ); - appendNewElementIfNotNull( - descriptor, deviceElement, ELEMENT.manufacturerURL, - deviceModelDetails.getManufacturerDetails().getManufacturerURI() - ); - } - if (deviceModelDetails.getModelDetails() != null) { - appendNewElementIfNotNull( - descriptor, deviceElement, ELEMENT.modelDescription, - deviceModelDetails.getModelDetails().getModelDescription() - ); - appendNewElementIfNotNull( - descriptor, deviceElement, ELEMENT.modelName, - deviceModelDetails.getModelDetails().getModelName() - ); - appendNewElementIfNotNull( - descriptor, deviceElement, ELEMENT.modelNumber, - deviceModelDetails.getModelDetails().getModelNumber() - ); - appendNewElementIfNotNull( - descriptor, deviceElement, ELEMENT.modelURL, - deviceModelDetails.getModelDetails().getModelURI() - ); - } - appendNewElementIfNotNull( - descriptor, deviceElement, ELEMENT.serialNumber, - deviceModelDetails.getSerialNumber() - ); - appendNewElementIfNotNull(descriptor, deviceElement, ELEMENT.UDN, deviceModel.getIdentity().getUdn()); - appendNewElementIfNotNull( - descriptor, deviceElement, ELEMENT.presentationURL, - deviceModelDetails.getPresentationURI() - ); - appendNewElementIfNotNull( - descriptor, deviceElement, ELEMENT.UPC, - deviceModelDetails.getUpc() - ); - - if (deviceModelDetails.getDlnaDocs() != null) { - for (DLNADoc dlnaDoc : deviceModelDetails.getDlnaDocs()) { - appendNewElementIfNotNull( - descriptor, deviceElement, Descriptor.Device.DLNA_PREFIX + ":" + ELEMENT.X_DLNADOC, - dlnaDoc, Descriptor.Device.DLNA_NAMESPACE_URI - ); - } - } - appendNewElementIfNotNull( - descriptor, deviceElement, Descriptor.Device.DLNA_PREFIX + ":" + ELEMENT.X_DLNACAP, - deviceModelDetails.getDlnaCaps(), Descriptor.Device.DLNA_NAMESPACE_URI - ); - - appendNewElementIfNotNull( - descriptor, deviceElement, Descriptor.Device.SEC_PREFIX + ":" + ELEMENT.ProductCap, - deviceModelDetails.getSecProductCaps(), Descriptor.Device.SEC_NAMESPACE_URI - ); - - appendNewElementIfNotNull( - descriptor, deviceElement, Descriptor.Device.SEC_PREFIX + ":" + ELEMENT.X_ProductCap, - deviceModelDetails.getSecProductCaps(), Descriptor.Device.SEC_NAMESPACE_URI - ); - - generateIconList(namespace, deviceModel, descriptor, deviceElement); - generateServiceList(namespace, deviceModel, descriptor, deviceElement); - generateDeviceList(namespace, deviceModel, descriptor, deviceElement, info); - } - - protected void generateIconList(Namespace namespace, Device deviceModel, Document descriptor, Element deviceElement) { - if (!deviceModel.hasIcons()) return; - - Element iconListElement = appendNewElement(descriptor, deviceElement, ELEMENT.iconList); - - for (Icon icon : deviceModel.getIcons()) { - Element iconElement = appendNewElement(descriptor, iconListElement, ELEMENT.icon); - - appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.mimetype, icon.getMimeType()); - appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.width, icon.getWidth()); - appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.height, icon.getHeight()); - appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.depth, icon.getDepth()); - if (deviceModel instanceof RemoteDevice) { - appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.url, icon.getUri()); - } else if (deviceModel instanceof LocalDevice) { - appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.url, namespace.getIconPath(icon)); - } - } - } - - protected void generateServiceList(Namespace namespace, Device deviceModel, Document descriptor, Element deviceElement) { - if (!deviceModel.hasServices()) return; - - Element serviceListElement = appendNewElement(descriptor, deviceElement, ELEMENT.serviceList); - - for (Service service : deviceModel.getServices()) { - Element serviceElement = appendNewElement(descriptor, serviceListElement, ELEMENT.service); - - appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.serviceType, service.getServiceType()); - appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.serviceId, service.getServiceId()); - if (service instanceof RemoteService) { - RemoteService rs = (RemoteService) service; - appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.SCPDURL, rs.getDescriptorURI()); - appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.controlURL, rs.getControlURI()); - appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.eventSubURL, rs.getEventSubscriptionURI()); - } else if (service instanceof LocalService) { - LocalService ls = (LocalService) service; - appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.SCPDURL, namespace.getDescriptorPath(ls)); - appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.controlURL, namespace.getControlPath(ls)); - appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.eventSubURL, namespace.getEventSubscriptionPath(ls)); - } - } - } - - protected void generateDeviceList(Namespace namespace, Device deviceModel, Document descriptor, Element deviceElement, RemoteClientInfo info) { - if (!deviceModel.hasEmbeddedDevices()) return; - - Element deviceListElement = appendNewElement(descriptor, deviceElement, ELEMENT.deviceList); - - for (Device device : deviceModel.getEmbeddedDevices()) { - generateDevice(namespace, device, descriptor, deviceListElement, info); - } - } - - public void warning(SAXParseException e) throws SAXException { - log.warning(e.toString()); - } - - public void error(SAXParseException e) throws SAXException { - throw e; - } - - public void fatalError(SAXParseException e) throws SAXException { - throw e; - } - - static protected URI parseURI(String uri) { - - // TODO: UPNP VIOLATION: Netgear DG834 uses a non-URI: 'www.netgear.com' - if (uri.startsWith("www.")) { - uri = "http://" + uri; - } - - // TODO: UPNP VIOLATION: Plutinosoft uses unencoded relative URIs - // /var/mobile/Applications/71367E68-F30F-460B-A2D2-331509441D13/Windows Media Player Streamer.app/Icon-ps3.jpg - if (uri.contains(" ")) { - // We don't want to split/encode individual parts of the URI, too much work - // TODO: But we probably should do this? Because browsers do it, everyone - // seems to think that spaces in URLs are somehow OK... - uri = uri.replaceAll(" ", "%20"); - } - - try { - return URI.create(uri); - } catch (Throwable ex) { - /* - catch Throwable because on Android 2.2, parsing some invalid URI like "http://..." gives: - java.lang.NullPointerException - at java.net.URI$Helper.isValidDomainName(URI.java:631) - at java.net.URI$Helper.isValidHost(URI.java:595) - at java.net.URI$Helper.parseAuthority(URI.java:544) - at java.net.URI$Helper.parseURI(URI.java:404) - at java.net.URI$Helper.access$100(URI.java:302) - at java.net.URI.(URI.java:87) - at java.net.URI.create(URI.java:968) - */ - log.fine("Illegal URI, trying with ./ prefix: " + Exceptions.unwrap(ex)); - // Ignore - } - try { - // The java.net.URI class can't deal with "_urn:foobar" (yeah, great idea Intel UPnP tools guy), as - // explained in RFC 3986: - // - // A path segment that contains a colon character (e.g., "this:that") cannot be used as the first segment - // of a relative-path reference, as it would be mistaken for a scheme name. Such a segment must - // be preceded by a dot-segment (e.g., "./this:that") to make a relative-path reference. - // - return URI.create("./" + uri); - } catch (IllegalArgumentException ex) { - log.warning("Illegal URI '" + uri + "', ignoring value: " + Exceptions.unwrap(ex)); - // Ignore - } - return null; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10DeviceDescriptorBinderSAXImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10DeviceDescriptorBinderSAXImpl.java deleted file mode 100644 index 76824cc..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10DeviceDescriptorBinderSAXImpl.java +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.xml; - -import org.fourthline.cling.binding.staging.MutableDevice; -import org.fourthline.cling.binding.staging.MutableIcon; -import org.fourthline.cling.binding.staging.MutableService; -import org.fourthline.cling.binding.staging.MutableUDAVersion; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.XMLUtil; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.types.DLNACaps; -import org.fourthline.cling.model.types.DLNADoc; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; -import org.seamless.util.MimeType; -import org.seamless.xml.SAXParser; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -import java.io.StringReader; -import java.net.URL; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.logging.Logger; - -import static org.fourthline.cling.binding.xml.Descriptor.Device.ELEMENT; - -/** - * A JAXP SAX parser implementation, which is actually slower than the DOM implementation (on desktop and on Android)! - * - * @author Christian Bauer - */ -public class UDA10DeviceDescriptorBinderSAXImpl extends UDA10DeviceDescriptorBinderImpl { - - private static Logger log = Logger.getLogger(DeviceDescriptorBinder.class.getName()); - - @Override - public D describe(D undescribedDevice, String descriptorXml) throws DescriptorBindingException, ValidationException { - - if (descriptorXml == null || descriptorXml.length() == 0) { - throw new DescriptorBindingException("Null or empty descriptor"); - } - - try { - log.fine("Populating device from XML descriptor: " + undescribedDevice); - - // Read the XML into a mutable descriptor graph - - SAXParser parser = new SAXParser(); - - MutableDevice descriptor = new MutableDevice(); - new RootHandler(descriptor, parser); - - parser.parse( - new InputSource( - // TODO: UPNP VIOLATION: Virgin Media Superhub sends trailing spaces/newlines after last XML element, need to trim() - new StringReader(descriptorXml.trim()) - ) - ); - - // Build the immutable descriptor graph - return (D) descriptor.build(undescribedDevice); - - } catch (ValidationException ex) { - throw ex; - } catch (Exception ex) { - throw new DescriptorBindingException("Could not parse device descriptor: " + ex.toString(), ex); - } - } - - protected static class RootHandler extends DeviceDescriptorHandler { - - public RootHandler(MutableDevice instance, SAXParser parser) { - super(instance, parser); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - - if (element.equals(SpecVersionHandler.EL)) { - MutableUDAVersion udaVersion = new MutableUDAVersion(); - getInstance().udaVersion = udaVersion; - new SpecVersionHandler(udaVersion, this); - } - - if (element.equals(DeviceHandler.EL)) { - new DeviceHandler(getInstance(), this); - } - - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - switch (element) { - case URLBase: - try { - String urlString = getCharacters(); - if (urlString != null && urlString.length() > 0) { - // We hope it's RFC 2396 and RFC 2732 compliant - getInstance().baseURL = new URL(urlString); - } - } catch (Exception ex) { - throw new SAXException("Invalid URLBase: " + ex.toString()); - } - break; - } - } - } - - protected static class SpecVersionHandler extends DeviceDescriptorHandler { - - public static final ELEMENT EL = ELEMENT.specVersion; - - public SpecVersionHandler(MutableUDAVersion instance, DeviceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - switch (element) { - case major: - String majorVersion = getCharacters().trim(); - if (!majorVersion.equals("1")) { - log.warning("Unsupported UDA major version, ignoring: " + majorVersion); - majorVersion = "1"; - } - getInstance().major = Integer.valueOf(majorVersion); - break; - case minor: - String minorVersion = getCharacters().trim(); - if (!minorVersion.equals("0")) { - log.warning("Unsupported UDA minor version, ignoring: " + minorVersion); - minorVersion = "0"; - } - getInstance().minor = Integer.valueOf(minorVersion); - break; - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class DeviceHandler extends DeviceDescriptorHandler { - - public static final ELEMENT EL = ELEMENT.device; - - public DeviceHandler(MutableDevice instance, DeviceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - - if (element.equals(IconListHandler.EL)) { - List icons = new ArrayList<>(); - getInstance().icons = icons; - new IconListHandler(icons, this); - } - - if (element.equals(ServiceListHandler.EL)) { - List services = new ArrayList<>(); - getInstance().services = services; - new ServiceListHandler(services, this); - } - - if (element.equals(DeviceListHandler.EL)) { - List devices = new ArrayList<>(); - getInstance().embeddedDevices = devices; - new DeviceListHandler(devices, this); - } - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - switch (element) { - case deviceType: - getInstance().deviceType = getCharacters(); - break; - case friendlyName: - getInstance().friendlyName = getCharacters(); - break; - case manufacturer: - getInstance().manufacturer = getCharacters(); - break; - case manufacturerURL: - getInstance().manufacturerURI = parseURI(getCharacters()); - break; - case modelDescription: - getInstance().modelDescription = getCharacters(); - break; - case modelName: - getInstance().modelName = getCharacters(); - break; - case modelNumber: - getInstance().modelNumber = getCharacters(); - break; - case modelURL: - getInstance().modelURI = parseURI(getCharacters()); - break; - case presentationURL: - getInstance().presentationURI = parseURI(getCharacters()); - break; - case UPC: - getInstance().upc = getCharacters(); - break; - case serialNumber: - getInstance().serialNumber = getCharacters(); - break; - case UDN: - getInstance().udn = UDN.valueOf(getCharacters()); - break; - case X_DLNADOC: - String txt = getCharacters(); - try { - getInstance().dlnaDocs.add(DLNADoc.valueOf(txt)); - } catch (InvalidValueException ex) { - log.info("Invalid X_DLNADOC value, ignoring value: " + txt); - } - break; - case X_DLNACAP: - getInstance().dlnaCaps = DLNACaps.valueOf(getCharacters()); - break; - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class IconListHandler extends DeviceDescriptorHandler> { - - public static final ELEMENT EL = ELEMENT.iconList; - - public IconListHandler(List instance, DeviceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - if (element.equals(IconHandler.EL)) { - MutableIcon icon = new MutableIcon(); - getInstance().add(icon); - new IconHandler(icon, this); - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class IconHandler extends DeviceDescriptorHandler { - - public static final ELEMENT EL = ELEMENT.icon; - - public IconHandler(MutableIcon instance, DeviceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - switch (element) { - case width: - getInstance().width = Integer.valueOf(getCharacters()); - break; - case height: - getInstance().height = Integer.valueOf(getCharacters()); - break; - case depth: - try { - getInstance().depth = Integer.valueOf(getCharacters()); - } catch(NumberFormatException ex) { - log.warning("Invalid icon depth '" + getCharacters() + "', using 16 as default: " + ex); - getInstance().depth = 16; - } - break; - case url: - getInstance().uri = parseURI(getCharacters()); - break; - case mimetype: - try { - getInstance().mimeType = getCharacters(); - MimeType.valueOf(getInstance().mimeType); - } catch(IllegalArgumentException ex) { - log.warning("Ignoring invalid icon mime type: " + getInstance().mimeType); - getInstance().mimeType = ""; - } - break; - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class ServiceListHandler extends DeviceDescriptorHandler> { - - public static final ELEMENT EL = ELEMENT.serviceList; - - public ServiceListHandler(List instance, DeviceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - if (element.equals(ServiceHandler.EL)) { - MutableService service = new MutableService(); - getInstance().add(service); - new ServiceHandler(service, this); - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - boolean last = element.equals(EL); - if (last) { - Iterator it = getInstance().iterator(); - while (it.hasNext()) { - MutableService service = it.next(); - if (service.serviceType == null || service.serviceId == null) - it.remove(); - } - } - return last; - } - } - - protected static class ServiceHandler extends DeviceDescriptorHandler { - - public static final ELEMENT EL = ELEMENT.service; - - public ServiceHandler(MutableService instance, DeviceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - try { - switch (element) { - case serviceType: - getInstance().serviceType = ServiceType.valueOf(getCharacters()); - break; - case serviceId: - getInstance().serviceId = ServiceId.valueOf(getCharacters()); - break; - case SCPDURL: - getInstance().descriptorURI = parseURI(getCharacters()); - break; - case controlURL: - getInstance().controlURI = parseURI(getCharacters()); - break; - case eventSubURL: - getInstance().eventSubscriptionURI = parseURI(getCharacters()); - break; - } - } catch (InvalidValueException ex) { - log.warning( - "UPnP specification violation, skipping invalid service declaration. " + ex.getMessage() - ); - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class DeviceListHandler extends DeviceDescriptorHandler> { - - public static final ELEMENT EL = ELEMENT.deviceList; - - public DeviceListHandler(List instance, DeviceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - if (element.equals(DeviceHandler.EL)) { - MutableDevice device = new MutableDevice(); - getInstance().add(device); - new DeviceHandler(device, this); - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class DeviceDescriptorHandler extends SAXParser.Handler { - - public DeviceDescriptorHandler(I instance) { - super(instance); - } - - public DeviceDescriptorHandler(I instance, SAXParser parser) { - super(instance, parser); - } - - public DeviceDescriptorHandler(I instance, DeviceDescriptorHandler parent) { - super(instance, parent); - } - - public DeviceDescriptorHandler(I instance, SAXParser parser, DeviceDescriptorHandler parent) { - super(instance, parser, parent); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - super.startElement(uri, localName, qName, attributes); - ELEMENT el = ELEMENT.valueOrNullOf(localName); - if (el == null) return; - startElement(el, attributes); - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - super.endElement(uri, localName, qName); - ELEMENT el = ELEMENT.valueOrNullOf(localName); - if (el == null) return; - endElement(el); - } - - @Override - protected boolean isLastElement(String uri, String localName, String qName) { - ELEMENT el = ELEMENT.valueOrNullOf(localName); - return el != null && isLastElement(el); - } - - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - - } - - public void endElement(ELEMENT element) throws SAXException { - - } - - public boolean isLastElement(ELEMENT element) { - return false; - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10ServiceDescriptorBinderImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10ServiceDescriptorBinderImpl.java deleted file mode 100644 index b1d3498..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10ServiceDescriptorBinderImpl.java +++ /dev/null @@ -1,504 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.xml; - -import org.fourthline.cling.binding.staging.MutableAction; -import org.fourthline.cling.binding.staging.MutableActionArgument; -import org.fourthline.cling.binding.staging.MutableAllowedValueRange; -import org.fourthline.cling.binding.staging.MutableService; -import org.fourthline.cling.binding.staging.MutableStateVariable; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.XMLUtil; -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.meta.ActionArgument; -import org.fourthline.cling.model.meta.QueryStateVariableAction; -import org.fourthline.cling.model.meta.RemoteService; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.meta.StateVariableEventDetails; -import org.fourthline.cling.model.types.CustomDatatype; -import org.fourthline.cling.model.types.Datatype; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.logging.Logger; - -import static org.fourthline.cling.binding.xml.Descriptor.Service.ATTRIBUTE; -import static org.fourthline.cling.binding.xml.Descriptor.Service.ELEMENT; -import static org.fourthline.cling.model.XMLUtil.appendNewElement; -import static org.fourthline.cling.model.XMLUtil.appendNewElementIfNotNull; - -/** - * Implementation based on JAXP DOM. - * - * @author Christian Bauer - */ -public class UDA10ServiceDescriptorBinderImpl implements ServiceDescriptorBinder, ErrorHandler { - - private static Logger log = Logger.getLogger(ServiceDescriptorBinder.class.getName()); - - public S describe(S undescribedService, String descriptorXml) throws DescriptorBindingException, ValidationException { - if (descriptorXml == null || descriptorXml.length() == 0) { - throw new DescriptorBindingException("Null or empty descriptor"); - } - - try { - log.fine("Populating service from XML descriptor: " + undescribedService); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - DocumentBuilder documentBuilder = factory.newDocumentBuilder(); - documentBuilder.setErrorHandler(this); - - Document d = documentBuilder.parse( - new InputSource( - // TODO: UPNP VIOLATION: Virgin Media Superhub sends trailing spaces/newlines after last XML element, need to trim() - new StringReader(descriptorXml.trim()) - ) - ); - - return describe(undescribedService, d); - - } catch (ValidationException ex) { - throw ex; - } catch (Exception ex) { - throw new DescriptorBindingException("Could not parse service descriptor: " + ex.toString(), ex); - } - } - - public S describe(S undescribedService, Document dom) throws DescriptorBindingException, ValidationException { - try { - log.fine("Populating service from DOM: " + undescribedService); - - // Read the XML into a mutable descriptor graph - MutableService descriptor = new MutableService(); - - hydrateBasic(descriptor, undescribedService); - - Element rootElement = dom.getDocumentElement(); - hydrateRoot(descriptor, rootElement); - - // Build the immutable descriptor graph - return buildInstance(undescribedService, descriptor); - - } catch (ValidationException ex) { - throw ex; - } catch (Exception ex) { - throw new DescriptorBindingException("Could not parse service DOM: " + ex.toString(), ex); - } - } - - protected S buildInstance(S undescribedService, MutableService descriptor) throws ValidationException { - return (S)descriptor.build(undescribedService.getDevice()); - } - - protected void hydrateBasic(MutableService descriptor, Service undescribedService) { - descriptor.serviceId = undescribedService.getServiceId(); - descriptor.serviceType = undescribedService.getServiceType(); - if (undescribedService instanceof RemoteService) { - RemoteService rs = (RemoteService) undescribedService; - descriptor.controlURI = rs.getControlURI(); - descriptor.eventSubscriptionURI = rs.getEventSubscriptionURI(); - descriptor.descriptorURI = rs.getDescriptorURI(); - } - } - - protected void hydrateRoot(MutableService descriptor, Element rootElement) - throws DescriptorBindingException { - - // We don't check the XMLNS, nobody bothers anyway... - - if (!ELEMENT.scpd.equals(rootElement)) { - throw new DescriptorBindingException("Root element name is not : " + rootElement.getNodeName()); - } - - NodeList rootChildren = rootElement.getChildNodes(); - - for (int i = 0; i < rootChildren.getLength(); i++) { - Node rootChild = rootChildren.item(i); - - if (rootChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.specVersion.equals(rootChild)) { - // We don't care about UDA major/minor specVersion anymore - whoever had the brilliant idea that - // the spec versions can be declared on devices _AND_ on their services should have their fingers - // broken so they never touch a keyboard again. - // hydrateSpecVersion(descriptor, rootChild); - } else if (ELEMENT.actionList.equals(rootChild)) { - hydrateActionList(descriptor, rootChild); - } else if (ELEMENT.serviceStateTable.equals(rootChild)) { - hydrateServiceStateTableList(descriptor, rootChild); - } else { - log.finer("Ignoring unknown element: " + rootChild.getNodeName()); - } - } - - } - - /* - public void hydrateSpecVersion(MutableService descriptor, Node specVersionNode) - throws DescriptorBindingException { - - NodeList specVersionChildren = specVersionNode.getChildNodes(); - for (int i = 0; i < specVersionChildren.getLength(); i++) { - Node specVersionChild = specVersionChildren.item(i); - - if (specVersionChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - MutableUDAVersion version = new MutableUDAVersion(); - if (ELEMENT.major.equals(specVersionChild)) { - version.major = Integer.valueOf(XMLUtil.getTextContent(specVersionChild)); - } else if (ELEMENT.minor.equals(specVersionChild)) { - version.minor = Integer.valueOf(XMLUtil.getTextContent(specVersionChild)); - } - } - } - */ - - public void hydrateActionList(MutableService descriptor, Node actionListNode) throws DescriptorBindingException { - - NodeList actionListChildren = actionListNode.getChildNodes(); - for (int i = 0; i < actionListChildren.getLength(); i++) { - Node actionListChild = actionListChildren.item(i); - - if (actionListChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.action.equals(actionListChild)) { - MutableAction action = new MutableAction(); - hydrateAction(action, actionListChild); - descriptor.actions.add(action); - } - } - } - - public void hydrateAction(MutableAction action, Node actionNode) { - - NodeList actionNodeChildren = actionNode.getChildNodes(); - for (int i = 0; i < actionNodeChildren.getLength(); i++) { - Node actionNodeChild = actionNodeChildren.item(i); - - if (actionNodeChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.name.equals(actionNodeChild)) { - action.name = XMLUtil.getTextContent(actionNodeChild); - } else if (ELEMENT.argumentList.equals(actionNodeChild)) { - - - NodeList argumentChildren = actionNodeChild.getChildNodes(); - for (int j = 0; j < argumentChildren.getLength(); j++) { - Node argumentChild = argumentChildren.item(j); - - if (argumentChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - MutableActionArgument actionArgument = new MutableActionArgument(); - hydrateActionArgument(actionArgument, argumentChild); - action.arguments.add(actionArgument); - } - } - } - - } - - public void hydrateActionArgument(MutableActionArgument actionArgument, Node actionArgumentNode) { - - NodeList argumentNodeChildren = actionArgumentNode.getChildNodes(); - for (int i = 0; i < argumentNodeChildren.getLength(); i++) { - Node argumentNodeChild = argumentNodeChildren.item(i); - - if (argumentNodeChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.name.equals(argumentNodeChild)) { - actionArgument.name = XMLUtil.getTextContent(argumentNodeChild); - } else if (ELEMENT.direction.equals(argumentNodeChild)) { - String directionString = XMLUtil.getTextContent(argumentNodeChild); - try { - actionArgument.direction = ActionArgument.Direction.valueOf(directionString.toUpperCase(Locale.ROOT)); - } catch (IllegalArgumentException ex) { - // TODO: UPNP VIOLATION: Pelco SpectraIV-IP uses illegal value INOUT - log.warning("UPnP specification violation: Invalid action argument direction, assuming 'IN': " + directionString); - actionArgument.direction = ActionArgument.Direction.IN; - } - } else if (ELEMENT.relatedStateVariable.equals(argumentNodeChild)) { - actionArgument.relatedStateVariable = XMLUtil.getTextContent(argumentNodeChild); - } else if (ELEMENT.retval.equals(argumentNodeChild)) { - actionArgument.retval = true; - } - } - } - - public void hydrateServiceStateTableList(MutableService descriptor, Node serviceStateTableNode) { - - NodeList serviceStateTableChildren = serviceStateTableNode.getChildNodes(); - for (int i = 0; i < serviceStateTableChildren.getLength(); i++) { - Node serviceStateTableChild = serviceStateTableChildren.item(i); - - if (serviceStateTableChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.stateVariable.equals(serviceStateTableChild)) { - MutableStateVariable stateVariable = new MutableStateVariable(); - hydrateStateVariable(stateVariable, (Element) serviceStateTableChild); - descriptor.stateVariables.add(stateVariable); - } - } - } - - public void hydrateStateVariable(MutableStateVariable stateVariable, Element stateVariableElement) { - - stateVariable.eventDetails = new StateVariableEventDetails( - stateVariableElement.getAttribute("sendEvents") != null && - stateVariableElement.getAttribute(ATTRIBUTE.sendEvents.toString()).toUpperCase(Locale.ROOT).equals("YES") - ); - - NodeList stateVariableChildren = stateVariableElement.getChildNodes(); - for (int i = 0; i < stateVariableChildren.getLength(); i++) { - Node stateVariableChild = stateVariableChildren.item(i); - - if (stateVariableChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.name.equals(stateVariableChild)) { - stateVariable.name = XMLUtil.getTextContent(stateVariableChild); - } else if (ELEMENT.dataType.equals(stateVariableChild)) { - String dtName = XMLUtil.getTextContent(stateVariableChild); - Datatype.Builtin builtin = Datatype.Builtin.getByDescriptorName(dtName); - stateVariable.dataType = builtin != null ? builtin.getDatatype() : new CustomDatatype(dtName); - } else if (ELEMENT.defaultValue.equals(stateVariableChild)) { - stateVariable.defaultValue = XMLUtil.getTextContent(stateVariableChild); - } else if (ELEMENT.allowedValueList.equals(stateVariableChild)) { - - List allowedValues = new ArrayList<>(); - - NodeList allowedValueListChildren = stateVariableChild.getChildNodes(); - for (int j = 0; j < allowedValueListChildren.getLength(); j++) { - Node allowedValueListChild = allowedValueListChildren.item(j); - - if (allowedValueListChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.allowedValue.equals(allowedValueListChild)) - allowedValues.add(XMLUtil.getTextContent(allowedValueListChild)); - } - - stateVariable.allowedValues = allowedValues; - - } else if (ELEMENT.allowedValueRange.equals(stateVariableChild)) { - - MutableAllowedValueRange range = new MutableAllowedValueRange(); - - NodeList allowedValueRangeChildren = stateVariableChild.getChildNodes(); - for (int j = 0; j < allowedValueRangeChildren.getLength(); j++) { - Node allowedValueRangeChild = allowedValueRangeChildren.item(j); - - if (allowedValueRangeChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (ELEMENT.minimum.equals(allowedValueRangeChild)) { - try { - range.minimum = Long.valueOf(XMLUtil.getTextContent(allowedValueRangeChild)); - } catch (Exception ex) { - } - } else if (ELEMENT.maximum.equals(allowedValueRangeChild)) { - try { - range.maximum = Long.valueOf(XMLUtil.getTextContent(allowedValueRangeChild)); - } catch (Exception ex) { - } - } else if (ELEMENT.step.equals(allowedValueRangeChild)) { - try { - range.step = Long.valueOf(XMLUtil.getTextContent(allowedValueRangeChild)); - } catch (Exception ex) { - } - } - } - - stateVariable.allowedValueRange = range; - } - } - } - - public String generate(Service service) throws DescriptorBindingException { - try { - log.fine("Generating XML descriptor from service model: " + service); - - return XMLUtil.documentToString(buildDOM(service)); - - } catch (Exception ex) { - throw new DescriptorBindingException("Could not build DOM: " + ex.getMessage(), ex); - } - } - - public Document buildDOM(Service service) throws DescriptorBindingException { - - try { - log.fine("Generating XML descriptor from service model: " + service); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - - Document d = factory.newDocumentBuilder().newDocument(); - generateScpd(service, d); - - return d; - - } catch (Exception ex) { - throw new DescriptorBindingException("Could not generate service descriptor: " + ex.getMessage(), ex); - } - } - - private void generateScpd(Service serviceModel, Document descriptor) { - - Element scpdElement = descriptor.createElementNS(Descriptor.Service.NAMESPACE_URI, ELEMENT.scpd.toString()); - descriptor.appendChild(scpdElement); - - generateSpecVersion(serviceModel, descriptor, scpdElement); - if (serviceModel.hasActions()) { - generateActionList(serviceModel, descriptor, scpdElement); - } - generateServiceStateTable(serviceModel, descriptor, scpdElement); - } - - private void generateSpecVersion(Service serviceModel, Document descriptor, Element rootElement) { - Element specVersionElement = appendNewElement(descriptor, rootElement, ELEMENT.specVersion); - appendNewElementIfNotNull(descriptor, specVersionElement, ELEMENT.major, serviceModel.getDevice().getVersion().getMajor()); - appendNewElementIfNotNull(descriptor, specVersionElement, ELEMENT.minor, serviceModel.getDevice().getVersion().getMinor()); - } - - private void generateActionList(Service serviceModel, Document descriptor, Element scpdElement) { - - Element actionListElement = appendNewElement(descriptor, scpdElement, ELEMENT.actionList); - - for (Action action : serviceModel.getActions()) { - if (!action.getName().equals(QueryStateVariableAction.ACTION_NAME)) - generateAction(action, descriptor, actionListElement); - } - } - - private void generateAction(Action action, Document descriptor, Element actionListElement) { - - Element actionElement = appendNewElement(descriptor, actionListElement, ELEMENT.action); - - appendNewElementIfNotNull(descriptor, actionElement, ELEMENT.name, action.getName()); - - if (action.hasArguments()) { - Element argumentListElement = appendNewElement(descriptor, actionElement, ELEMENT.argumentList); - for (ActionArgument actionArgument : action.getArguments()) { - generateActionArgument(actionArgument, descriptor, argumentListElement); - } - } - } - - private void generateActionArgument(ActionArgument actionArgument, Document descriptor, Element actionElement) { - - Element actionArgumentElement = appendNewElement(descriptor, actionElement, ELEMENT.argument); - - appendNewElementIfNotNull(descriptor, actionArgumentElement, ELEMENT.name, actionArgument.getName()); - appendNewElementIfNotNull(descriptor, actionArgumentElement, ELEMENT.direction, actionArgument.getDirection().toString().toLowerCase(Locale.ROOT)); - if (actionArgument.isReturnValue()) { - // TODO: UPNP VIOLATION: WMP12 will discard RenderingControl service if it contains tags - log.warning("UPnP specification violation: Not producing element to be compatible with WMP12: " + actionArgument); - // appendNewElement(descriptor, actionArgumentElement, ELEMENT.retval); - } - appendNewElementIfNotNull(descriptor, actionArgumentElement, ELEMENT.relatedStateVariable, actionArgument.getRelatedStateVariableName()); - } - - private void generateServiceStateTable(Service serviceModel, Document descriptor, Element scpdElement) { - - Element serviceStateTableElement = appendNewElement(descriptor, scpdElement, ELEMENT.serviceStateTable); - - for (StateVariable stateVariable : serviceModel.getStateVariables()) { - generateStateVariable(stateVariable, descriptor, serviceStateTableElement); - } - } - - private void generateStateVariable(StateVariable stateVariable, Document descriptor, Element serviveStateTableElement) { - - Element stateVariableElement = appendNewElement(descriptor, serviveStateTableElement, ELEMENT.stateVariable); - - appendNewElementIfNotNull(descriptor, stateVariableElement, ELEMENT.name, stateVariable.getName()); - - if (stateVariable.getTypeDetails().getDatatype() instanceof CustomDatatype) { - appendNewElementIfNotNull(descriptor, stateVariableElement, ELEMENT.dataType, - ((CustomDatatype)stateVariable.getTypeDetails().getDatatype()).getName()); - } else { - appendNewElementIfNotNull(descriptor, stateVariableElement, ELEMENT.dataType, - stateVariable.getTypeDetails().getDatatype().getBuiltin().getDescriptorName()); - } - - appendNewElementIfNotNull(descriptor, stateVariableElement, ELEMENT.defaultValue, - stateVariable.getTypeDetails().getDefaultValue()); - - // The default is 'yes' but we generate it anyway just to be sure - if (stateVariable.getEventDetails().isSendEvents()) { - stateVariableElement.setAttribute(ATTRIBUTE.sendEvents.toString(), "yes"); - } else { - stateVariableElement.setAttribute(ATTRIBUTE.sendEvents.toString(), "no"); - } - - if (stateVariable.getTypeDetails().getAllowedValues() != null) { - Element allowedValueListElement = appendNewElement(descriptor, stateVariableElement, ELEMENT.allowedValueList); - for (String allowedValue : stateVariable.getTypeDetails().getAllowedValues()) { - appendNewElementIfNotNull(descriptor, allowedValueListElement, ELEMENT.allowedValue, allowedValue); - } - } - - if (stateVariable.getTypeDetails().getAllowedValueRange() != null) { - Element allowedValueRangeElement = appendNewElement(descriptor, stateVariableElement, ELEMENT.allowedValueRange); - appendNewElementIfNotNull( - descriptor, allowedValueRangeElement, ELEMENT.minimum, stateVariable.getTypeDetails().getAllowedValueRange().getMinimum() - ); - appendNewElementIfNotNull( - descriptor, allowedValueRangeElement, ELEMENT.maximum, stateVariable.getTypeDetails().getAllowedValueRange().getMaximum() - ); - if (stateVariable.getTypeDetails().getAllowedValueRange().getStep() >= 1l) { - appendNewElementIfNotNull( - descriptor, allowedValueRangeElement, ELEMENT.step, stateVariable.getTypeDetails().getAllowedValueRange().getStep() - ); - } - } - - } - - public void warning(SAXParseException e) throws SAXException { - log.warning(e.toString()); - } - - public void error(SAXParseException e) throws SAXException { - throw e; - } - - public void fatalError(SAXParseException e) throws SAXException { - throw e; - } -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10ServiceDescriptorBinderSAXImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10ServiceDescriptorBinderSAXImpl.java deleted file mode 100644 index 989c575..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/binding/xml/UDA10ServiceDescriptorBinderSAXImpl.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.binding.xml; - -import org.fourthline.cling.binding.staging.MutableAction; -import org.fourthline.cling.binding.staging.MutableActionArgument; -import org.fourthline.cling.binding.staging.MutableAllowedValueRange; -import org.fourthline.cling.binding.staging.MutableService; -import org.fourthline.cling.binding.staging.MutableStateVariable; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.meta.ActionArgument; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.meta.StateVariableEventDetails; -import org.fourthline.cling.model.types.CustomDatatype; -import org.fourthline.cling.model.types.Datatype; -import org.seamless.xml.SAXParser; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.logging.Logger; - -import static org.fourthline.cling.binding.xml.Descriptor.Service.ATTRIBUTE; -import static org.fourthline.cling.binding.xml.Descriptor.Service.ELEMENT; - -/** - * Implementation based on JAXP SAX. - * - * @author Christian Bauer - */ -public class UDA10ServiceDescriptorBinderSAXImpl extends UDA10ServiceDescriptorBinderImpl { - - private static Logger log = Logger.getLogger(ServiceDescriptorBinder.class.getName()); - - @Override - public S describe(S undescribedService, String descriptorXml) throws DescriptorBindingException, ValidationException { - - if (descriptorXml == null || descriptorXml.length() == 0) { - throw new DescriptorBindingException("Null or empty descriptor"); - } - - try { - log.fine("Reading service from XML descriptor"); - - SAXParser parser = new SAXParser(); - - MutableService descriptor = new MutableService(); - - hydrateBasic(descriptor, undescribedService); - - new RootHandler(descriptor, parser); - - parser.parse( - new InputSource( - // TODO: UPNP VIOLATION: Virgin Media Superhub sends trailing spaces/newlines after last XML element, need to trim() - new StringReader(descriptorXml.trim()) - ) - ); - - // Build the immutable descriptor graph - return (S)descriptor.build(undescribedService.getDevice()); - - } catch (ValidationException ex) { - throw ex; - } catch (Exception ex) { - throw new DescriptorBindingException("Could not parse service descriptor: " + ex.toString(), ex); - } - } - - protected static class RootHandler extends ServiceDescriptorHandler { - - public RootHandler(MutableService instance, SAXParser parser) { - super(instance, parser); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - - /* - if (element.equals(SpecVersionHandler.EL)) { - MutableUDAVersion udaVersion = new MutableUDAVersion(); - getInstance().udaVersion = udaVersion; - new SpecVersionHandler(udaVersion, this); - } - */ - - if (element.equals(ActionListHandler.EL)) { - List actions = new ArrayList<>(); - getInstance().actions = actions; - new ActionListHandler(actions, this); - } - - if (element.equals(StateVariableListHandler.EL)) { - List stateVariables = new ArrayList<>(); - getInstance().stateVariables = stateVariables; - new StateVariableListHandler(stateVariables, this); - } - - } - } - - /* - protected static class SpecVersionHandler extends ServiceDescriptorHandler { - - public static final ELEMENT EL = ELEMENT.specVersion; - - public SpecVersionHandler(MutableUDAVersion instance, ServiceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - switch (element) { - case major: - getInstance().major = Integer.valueOf(getCharacters()); - break; - case minor: - getInstance().minor = Integer.valueOf(getCharacters()); - break; - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - */ - - protected static class ActionListHandler extends ServiceDescriptorHandler> { - - public static final ELEMENT EL = ELEMENT.actionList; - - public ActionListHandler(List instance, ServiceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - if (element.equals(ActionHandler.EL)) { - MutableAction action = new MutableAction(); - getInstance().add(action); - new ActionHandler(action, this); - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class ActionHandler extends ServiceDescriptorHandler { - - public static final ELEMENT EL = ELEMENT.action; - - public ActionHandler(MutableAction instance, ServiceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - if (element.equals(ActionArgumentListHandler.EL)) { - List arguments = new ArrayList<>(); - getInstance().arguments = arguments; - new ActionArgumentListHandler(arguments, this); - } - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - switch (element) { - case name: - getInstance().name = getCharacters(); - break; - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class ActionArgumentListHandler extends ServiceDescriptorHandler> { - - public static final ELEMENT EL = ELEMENT.argumentList; - - public ActionArgumentListHandler(List instance, ServiceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - if (element.equals(ActionArgumentHandler.EL)) { - MutableActionArgument argument = new MutableActionArgument(); - getInstance().add(argument); - new ActionArgumentHandler(argument, this); - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class ActionArgumentHandler extends ServiceDescriptorHandler { - - public static final ELEMENT EL = ELEMENT.argument; - - public ActionArgumentHandler(MutableActionArgument instance, ServiceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - switch (element) { - case name: - getInstance().name = getCharacters(); - break; - case direction: - String directionString = getCharacters(); - try { - getInstance().direction = ActionArgument.Direction.valueOf(directionString.toUpperCase(Locale.ROOT)); - } catch (IllegalArgumentException ex) { - // TODO: UPNP VIOLATION: Pelco SpectraIV-IP uses illegal value INOUT - log.warning("UPnP specification violation: Invalid action argument direction, assuming 'IN': " + directionString); - getInstance().direction = ActionArgument.Direction.IN; - } - break; - case relatedStateVariable: - getInstance().relatedStateVariable = getCharacters(); - break; - case retval: - getInstance().retval = true; - break; - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class StateVariableListHandler extends ServiceDescriptorHandler> { - - public static final ELEMENT EL = ELEMENT.serviceStateTable; - - public StateVariableListHandler(List instance, ServiceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - if (element.equals(StateVariableHandler.EL)) { - MutableStateVariable stateVariable = new MutableStateVariable(); - - String sendEventsAttributeValue = attributes.getValue(ATTRIBUTE.sendEvents.toString()); - stateVariable.eventDetails = new StateVariableEventDetails( - sendEventsAttributeValue != null && sendEventsAttributeValue.toUpperCase(Locale.ROOT).equals("YES") - ); - - getInstance().add(stateVariable); - new StateVariableHandler(stateVariable, this); - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class StateVariableHandler extends ServiceDescriptorHandler { - - public static final ELEMENT EL = ELEMENT.stateVariable; - - public StateVariableHandler(MutableStateVariable instance, ServiceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - if (element.equals(AllowedValueListHandler.EL)) { - List allowedValues = new ArrayList<>(); - getInstance().allowedValues = allowedValues; - new AllowedValueListHandler(allowedValues, this); - } - - if (element.equals(AllowedValueRangeHandler.EL)) { - MutableAllowedValueRange allowedValueRange = new MutableAllowedValueRange(); - getInstance().allowedValueRange = allowedValueRange; - new AllowedValueRangeHandler(allowedValueRange, this); - } - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - switch (element) { - case name: - getInstance().name = getCharacters(); - break; - case dataType: - String dtName = getCharacters(); - Datatype.Builtin builtin = Datatype.Builtin.getByDescriptorName(dtName); - getInstance().dataType = builtin != null ? builtin.getDatatype() : new CustomDatatype(dtName); - break; - case defaultValue: - getInstance().defaultValue = getCharacters(); - break; - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class AllowedValueListHandler extends ServiceDescriptorHandler> { - - public static final ELEMENT EL = ELEMENT.allowedValueList; - - public AllowedValueListHandler(List instance, ServiceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - switch (element) { - case allowedValue: - getInstance().add(getCharacters()); - break; - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class AllowedValueRangeHandler extends ServiceDescriptorHandler { - - public static final ELEMENT EL = ELEMENT.allowedValueRange; - - public AllowedValueRangeHandler(MutableAllowedValueRange instance, ServiceDescriptorHandler parent) { - super(instance, parent); - } - - @Override - public void endElement(ELEMENT element) throws SAXException { - try { - switch (element) { - case minimum: - getInstance().minimum = Long.valueOf(getCharacters()); - break; - case maximum: - getInstance().maximum = Long.valueOf(getCharacters()); - break; - case step: - getInstance().step = Long.valueOf(getCharacters()); - break; - } - } catch (Exception ex) { - // Ignore - } - } - - @Override - public boolean isLastElement(ELEMENT element) { - return element.equals(EL); - } - } - - protected static class ServiceDescriptorHandler extends SAXParser.Handler { - - public ServiceDescriptorHandler(I instance) { - super(instance); - } - - public ServiceDescriptorHandler(I instance, SAXParser parser) { - super(instance, parser); - } - - public ServiceDescriptorHandler(I instance, ServiceDescriptorHandler parent) { - super(instance, parent); - } - - public ServiceDescriptorHandler(I instance, SAXParser parser, ServiceDescriptorHandler parent) { - super(instance, parser, parent); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - super.startElement(uri, localName, qName, attributes); - ELEMENT el = ELEMENT.valueOrNullOf(localName); - if (el == null) return; - startElement(el, attributes); - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - super.endElement(uri, localName, qName); - ELEMENT el = ELEMENT.valueOrNullOf(localName); - if (el == null) return; - endElement(el); - } - - @Override - protected boolean isLastElement(String uri, String localName, String qName) { - ELEMENT el = ELEMENT.valueOrNullOf(localName); - return el != null && isLastElement(el); - } - - public void startElement(ELEMENT element, Attributes attributes) throws SAXException { - - } - - public void endElement(ELEMENT element) throws SAXException { - - } - - public boolean isLastElement(ELEMENT element) { - return false; - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ActionCallback.java b/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ActionCallback.java deleted file mode 100644 index c734083..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ActionCallback.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.controlpoint; - -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.control.IncomingActionResponseMessage; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.RemoteService; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.protocol.sync.SendingAction; - -import java.net.URL; - -/** - * Execute actions on any service. - *

- * Usage example for asynchronous execution in a background thread: - *

- *
- * Service service = device.findService(new UDAServiceId("SwitchPower"));
- * Action getStatusAction = service.getAction("GetStatus");
- * ActionInvocation getStatusInvocation = new ActionInvocation(getStatusAction);
- *
- * ActionCallback getStatusCallback = new ActionCallback(getStatusInvocation) {
- *
- *      public void success(ActionInvocation invocation) {
- *          ActionArgumentValue status  = invocation.getOutput("ResultStatus");
- *          assertEquals((Boolean) status.getValue(), Boolean.valueOf(false));
- *      }
- *
- *      public void failure(ActionInvocation invocation, UpnpResponse res) {
- *          System.err.println(
- *              createDefaultFailureMessage(invocation, res)
- *          );
- *      }
- * };
- *
- * upnpService.getControlPoint().execute(getStatusCallback)
- * 
- *

- * You can also execute the action synchronously in the same thread using the - * {@link org.fourthline.cling.controlpoint.ActionCallback.Default} implementation: - *

- *
- * myActionInvocation.setInput("foo", bar);
- * new ActionCallback.Default(myActionInvocation, upnpService.getControlPoint()).run();
- * myActionInvocation.getOutput("baz");
- * 
- * - * @author Christian Bauer - */ -public abstract class ActionCallback implements Runnable { - - /** - * Empty implementation of callback methods, simplifies synchronous - * execution of an {@link org.fourthline.cling.model.action.ActionInvocation}. - */ - public static final class Default extends ActionCallback { - - public Default(ActionInvocation actionInvocation, ControlPoint controlPoint) { - super(actionInvocation, controlPoint); - } - - @Override - public void success(ActionInvocation invocation) { - } - - @Override - public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) { - - } - } - - protected final ActionInvocation actionInvocation; - - protected ControlPoint controlPoint; - - protected ActionCallback(ActionInvocation actionInvocation, ControlPoint controlPoint) { - this.actionInvocation = actionInvocation; - this.controlPoint = controlPoint; - } - - protected ActionCallback(ActionInvocation actionInvocation) { - this.actionInvocation = actionInvocation; - } - - public ActionInvocation getActionInvocation() { - return actionInvocation; - } - - synchronized public ControlPoint getControlPoint() { - return controlPoint; - } - - synchronized public ActionCallback setControlPoint(ControlPoint controlPoint) { - this.controlPoint = controlPoint; - return this; - } - - public void run() { - Service service = actionInvocation.getAction().getService(); - - // Local execution - if (service instanceof LocalService) { - LocalService localService = (LocalService)service; - - // Executor validates input inside the execute() call immediately - localService.getExecutor(actionInvocation.getAction()).execute(actionInvocation); - - if (actionInvocation.getFailure() != null) { - failure(actionInvocation, null); - } else { - success(actionInvocation); - } - - // Remote execution - } else if (service instanceof RemoteService){ - - if (getControlPoint() == null) { - throw new IllegalStateException("Callback must be executed through ControlPoint"); - } - - RemoteService remoteService = (RemoteService)service; - - // Figure out the remote URL where we'd like to send the action request to - URL controLURL; - try { - controLURL = remoteService.getDevice().normalizeURI(remoteService.getControlURI()); - } catch(IllegalArgumentException e) { - failure(actionInvocation, null, "bad control URL: " + remoteService.getControlURI()); - return ; - } - - // Do it - SendingAction prot = getControlPoint().getProtocolFactory().createSendingAction(actionInvocation, controLURL); - prot.run(); - - IncomingActionResponseMessage response = prot.getOutputMessage(); - - if (response == null) { - failure(actionInvocation, null); - } else if (response.getOperation().isFailed()) { - failure(actionInvocation, response.getOperation()); - } else { - success(actionInvocation); - } - } - } - - protected String createDefaultFailureMessage(ActionInvocation invocation, UpnpResponse operation) { - String message = "Error: "; - final ActionException exception = invocation.getFailure(); - if (exception != null) { - message = message + exception.getMessage(); - } - if (operation != null) { - message = message + " (HTTP response was: " + operation.getResponseDetails() + ")"; - } - return message; - } - - protected void failure(ActionInvocation invocation, UpnpResponse operation) { - failure(invocation, operation, createDefaultFailureMessage(invocation, operation)); - } - - /** - * Called when the action invocation succeeded. - * - * @param invocation The successful invocation, call its getOutput() method for results. - */ - public abstract void success(ActionInvocation invocation); - - /** - * Called when the action invocation failed. - * - * @param invocation The failed invocation, call its getFailure() method for more details. - * @param operation If the invocation was on a remote service, the response message, otherwise null. - * @param defaultMsg A user-friendly error message generated from the invocation exception and response. - * @see #createDefaultFailureMessage - */ - public abstract void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg); - - @Override - public String toString() { - return "(ActionCallback) " + actionInvocation; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ControlPoint.java b/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ControlPoint.java deleted file mode 100644 index 2fa3a14..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ControlPoint.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.controlpoint; - -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.registry.Registry; - -import java.util.concurrent.Future; - -/** - * Unified API for the asynchronous execution of network searches, actions, event subscriptions. - * - * @author Christian Bauer - */ -public interface ControlPoint { - - public UpnpServiceConfiguration getConfiguration(); - public ProtocolFactory getProtocolFactory(); - public Registry getRegistry(); - - public void search(); - public void search(UpnpHeader searchType); - public void search(int mxSeconds); - public void search(UpnpHeader searchType, int mxSeconds); - public Future execute(ActionCallback callback); - public void execute(SubscriptionCallback callback); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ControlPointImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ControlPointImpl.java deleted file mode 100644 index e8fa85f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/ControlPointImpl.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.controlpoint; - -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.controlpoint.event.ExecuteAction; -import org.fourthline.cling.controlpoint.event.Search; -import org.fourthline.cling.model.message.header.MXHeader; -import org.fourthline.cling.model.message.header.STAllHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.registry.Registry; - -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.event.Observes; -import javax.inject.Inject; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.logging.Logger; - -/** - * Default implementation. - *

- * This implementation uses the executor returned by - * {@link org.fourthline.cling.UpnpServiceConfiguration#getSyncProtocolExecutorService()}. - *

- * - * @author Christian Bauer - */ -@ApplicationScoped -public class ControlPointImpl implements ControlPoint { - - private static Logger log = Logger.getLogger(ControlPointImpl.class.getName()); - - protected UpnpServiceConfiguration configuration; - protected ProtocolFactory protocolFactory; - protected Registry registry; - - protected ControlPointImpl() { - } - - @Inject - public ControlPointImpl(UpnpServiceConfiguration configuration, ProtocolFactory protocolFactory, Registry registry) { - log.fine("Creating ControlPoint: " + getClass().getName()); - - this.configuration = configuration; - this.protocolFactory = protocolFactory; - this.registry = registry; - } - - public UpnpServiceConfiguration getConfiguration() { - return configuration; - } - - public ProtocolFactory getProtocolFactory() { - return protocolFactory; - } - - public Registry getRegistry() { - return registry; - } - - public void search(@Observes Search search) { - search(search.getSearchType(), search.getMxSeconds()); - } - - public void search() { - search(new STAllHeader(), MXHeader.DEFAULT_VALUE); - } - - public void search(UpnpHeader searchType) { - search(searchType, MXHeader.DEFAULT_VALUE); - } - - public void search(int mxSeconds) { - search(new STAllHeader(), mxSeconds); - } - - public void search(UpnpHeader searchType, int mxSeconds) { - log.fine("Sending asynchronous search for: " + searchType.getString()); - getConfiguration().getAsyncProtocolExecutor().execute( - getProtocolFactory().createSendingSearch(searchType, mxSeconds) - ); - } - - public void execute(ExecuteAction executeAction) { - execute(executeAction.getCallback()); - } - - public Future execute(ActionCallback callback) { - log.fine("Invoking action in background: " + callback); - callback.setControlPoint(this); - ExecutorService executor = getConfiguration().getSyncProtocolExecutorService(); - return executor.submit(callback); - } - - public void execute(SubscriptionCallback callback) { - log.fine("Invoking subscription in background: " + callback); - callback.setControlPoint(this); - getConfiguration().getSyncProtocolExecutorService().execute(callback); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/SubscriptionCallback.java b/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/SubscriptionCallback.java deleted file mode 100644 index 5825a76..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/SubscriptionCallback.java +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.controlpoint; - -import org.fourthline.cling.model.UnsupportedDataException; -import org.fourthline.cling.model.UserConstants; -import org.fourthline.cling.model.gena.CancelReason; -import org.fourthline.cling.model.gena.GENASubscription; -import org.fourthline.cling.model.gena.LocalGENASubscription; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.RemoteService; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.protocol.ProtocolCreationException; -import org.fourthline.cling.protocol.sync.SendingSubscribe; -import org.seamless.util.Exceptions; - -import java.util.Collections; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Subscribe and receive events from a service through GENA. - *

- * Usage example, establishing a subscription with a {@link org.fourthline.cling.model.meta.Service}: - *

- *
- * SubscriptionCallback callback = new SubscriptionCallback(service, 600) { // Timeout in seconds
- *
- *      public void established(GENASubscription sub) {
- *          System.out.println("Established: " + sub.getSubscriptionId());
- *      }
- *
- *      public void failed(GENASubscription sub, UpnpResponse response, Exception ex) {
- *          System.err.println(
- *              createDefaultFailureMessage(response, ex)
- *          );
- *      }
- *
- *      public void ended(GENASubscription sub, CancelReason reason, UpnpResponse response) {
- *          // Reason should be null, or it didn't end regularly
- *      }
- *
- *      public void eventReceived(GENASubscription sub) {
- *          System.out.println("Event: " + sub.getCurrentSequence().getValue());
- *          Map<String, StateVariableValue> values = sub.getCurrentValues();
- *          StateVariableValue status = values.get("Status");
- *          System.out.println("Status is: " + status.toString());
- *      }
- *
- *      public void eventsMissed(GENASubscription sub, int numberOfMissedEvents) {
- *          System.out.println("Missed events: " + numberOfMissedEvents);
- *      }
- * };
- *
- * upnpService.getControlPoint().execute(callback);
- * 
- * - * @author Christian Bauer - */ -public abstract class SubscriptionCallback implements Runnable { - - protected static Logger log = Logger.getLogger(SubscriptionCallback.class.getName()); - - protected final Service service; - protected final Integer requestedDurationSeconds; - - private ControlPoint controlPoint; - private GENASubscription subscription; - - protected SubscriptionCallback(Service service) { - this.service = service; - this.requestedDurationSeconds = UserConstants.DEFAULT_SUBSCRIPTION_DURATION_SECONDS; - } - - protected SubscriptionCallback(Service service, int requestedDurationSeconds) { - this.service = service; - this.requestedDurationSeconds = requestedDurationSeconds; - } - - public Service getService() { - return service; - } - - synchronized public ControlPoint getControlPoint() { - return controlPoint; - } - - synchronized public void setControlPoint(ControlPoint controlPoint) { - this.controlPoint = controlPoint; - } - - synchronized public GENASubscription getSubscription() { - return subscription; - } - - synchronized public void setSubscription(GENASubscription subscription) { - this.subscription = subscription; - } - - synchronized public void run() { - if (getControlPoint() == null) { - throw new IllegalStateException("Callback must be executed through ControlPoint"); - } - - if (getService() instanceof LocalService) { - establishLocalSubscription((LocalService) service); - } else if (getService() instanceof RemoteService) { - establishRemoteSubscription((RemoteService) service); - } - } - - private void establishLocalSubscription(LocalService service) { - - if (getControlPoint().getRegistry().getLocalDevice(service.getDevice().getIdentity().getUdn(), false) == null) { - log.fine("Local device service is currently not registered, failing subscription immediately"); - failed(null, null, new IllegalStateException("Local device is not registered")); - return; - } - - // Local execution of subscription on local service re-uses the procedure and lifecycle that is - // used for inbound subscriptions from remote control points on local services! - // Except that it doesn't ever expire, we override the requested duration with Integer.MAX_VALUE! - - LocalGENASubscription localSubscription = null; - try { - localSubscription = - new LocalGENASubscription(service, Integer.MAX_VALUE, Collections.EMPTY_LIST) { - - public void failed(Exception ex) { - synchronized (SubscriptionCallback.this) { - SubscriptionCallback.this.setSubscription(null); - SubscriptionCallback.this.failed(null, null, ex); - } - } - - public void established() { - synchronized (SubscriptionCallback.this) { - SubscriptionCallback.this.setSubscription(this); - SubscriptionCallback.this.established(this); - } - } - - public void ended(CancelReason reason) { - synchronized (SubscriptionCallback.this) { - SubscriptionCallback.this.setSubscription(null); - SubscriptionCallback.this.ended(this, reason, null); - } - } - - public void eventReceived() { - synchronized (SubscriptionCallback.this) { - log.fine("Local service state updated, notifying callback, sequence is: " + getCurrentSequence()); - SubscriptionCallback.this.eventReceived(this); - incrementSequence(); - } - } - }; - - log.fine("Local device service is currently registered, also registering subscription"); - getControlPoint().getRegistry().addLocalSubscription(localSubscription); - - log.fine("Notifying subscription callback of local subscription availablity"); - localSubscription.establish(); - - log.fine("Simulating first initial event for local subscription callback, sequence: " + localSubscription.getCurrentSequence()); - eventReceived(localSubscription); - localSubscription.incrementSequence(); - - log.fine("Starting to monitor state changes of local service"); - localSubscription.registerOnService(); - - } catch (Exception ex) { - log.fine("Local callback creation failed: " + ex.toString()); - log.log(Level.FINE, "Exception root cause: ", Exceptions.unwrap(ex)); - if (localSubscription != null) - getControlPoint().getRegistry().removeLocalSubscription(localSubscription); - failed(localSubscription, null, ex); - } - } - - private void establishRemoteSubscription(RemoteService service) { - RemoteGENASubscription remoteSubscription = - new RemoteGENASubscription(service, requestedDurationSeconds) { - - public void failed(UpnpResponse responseStatus) { - synchronized (SubscriptionCallback.this) { - SubscriptionCallback.this.setSubscription(null); - SubscriptionCallback.this.failed(this, responseStatus, null); - } - } - - public void established() { - synchronized (SubscriptionCallback.this) { - SubscriptionCallback.this.setSubscription(this); - SubscriptionCallback.this.established(this); - } - } - - public void ended(CancelReason reason, UpnpResponse responseStatus) { - synchronized (SubscriptionCallback.this) { - SubscriptionCallback.this.setSubscription(null); - SubscriptionCallback.this.ended(this, reason, responseStatus); - } - } - - public void eventReceived() { - synchronized (SubscriptionCallback.this) { - SubscriptionCallback.this.eventReceived(this); - } - } - - public void eventsMissed(int numberOfMissedEvents) { - synchronized (SubscriptionCallback.this) { - SubscriptionCallback.this.eventsMissed(this, numberOfMissedEvents); - } - } - - public void invalidMessage(UnsupportedDataException ex) { - synchronized (SubscriptionCallback.this) { - SubscriptionCallback.this.invalidMessage(this, ex); - } - } - }; - - SendingSubscribe protocol; - try { - protocol = getControlPoint().getProtocolFactory().createSendingSubscribe(remoteSubscription); - } catch (ProtocolCreationException ex) { - failed(subscription, null, ex); - return; - } - protocol.run(); - } - - synchronized public void end() { - if (subscription == null) return; - if (subscription instanceof LocalGENASubscription) { - endLocalSubscription((LocalGENASubscription)subscription); - } else if (subscription instanceof RemoteGENASubscription) { - endRemoteSubscription((RemoteGENASubscription)subscription); - } - } - - private void endLocalSubscription(LocalGENASubscription subscription) { - log.fine("Removing local subscription and ending it in callback: " + subscription); - getControlPoint().getRegistry().removeLocalSubscription(subscription); - subscription.end(null); // No reason, on controlpoint request - } - - private void endRemoteSubscription(RemoteGENASubscription subscription) { - log.fine("Ending remote subscription: " + subscription); - getControlPoint().getConfiguration().getSyncProtocolExecutorService().execute( - getControlPoint().getProtocolFactory().createSendingUnsubscribe(subscription) - ); - } - - protected void failed(GENASubscription subscription, UpnpResponse responseStatus, Exception exception) { - failed(subscription, responseStatus, exception, createDefaultFailureMessage(responseStatus, exception)); - } - - /** - * Called when establishing a local or remote subscription failed. To get a nice error message that - * transparently detects local or remote errors use createDefaultFailureMessage(). - * - * @param subscription The failed subscription object, not very useful at this point. - * @param responseStatus For a remote subscription, if a response was received at all, this is it, otherwise null. - * @param exception For a local subscription and failed creation of a remote subscription protocol (before - * sending the subscribe request), any exception that caused the failure, otherwise null. - * @param defaultMsg A user-friendly error message. - * @see #createDefaultFailureMessage - */ - protected abstract void failed(GENASubscription subscription, UpnpResponse responseStatus, Exception exception, String defaultMsg); - - /** - * Called when a local or remote subscription was successfully established. - * - * @param subscription The successful subscription. - */ - protected abstract void established(GENASubscription subscription); - - /** - * Called when a local or remote subscription ended, either on user request or because of a failure. - * - * @param subscription The ended subscription instance. - * @param reason If the subscription ended regularly (through end()), this is null. - * @param responseStatus For a remote subscription, if the cause implies a remopte response and it was - * received, this is it (e.g. renewal failure response). - */ - protected abstract void ended(GENASubscription subscription, CancelReason reason, UpnpResponse responseStatus); - - /** - * Called when an event for an established subscription has been received. - *

- * Use the {@link org.fourthline.cling.model.gena.GENASubscription#getCurrentValues()} method to obtain - * the evented state variable values. - *

- * - * @param subscription The established subscription with fresh state variable values. - */ - protected abstract void eventReceived(GENASubscription subscription); - - /** - * Called when a received event was out of sequence, indicating that events have been missed. - *

- * It's up to you if you want to react to missed events or if you (can) silently ignore them. - *

- * @param subscription The established subscription. - * @param numberOfMissedEvents The number of missed events. - */ - protected abstract void eventsMissed(GENASubscription subscription, int numberOfMissedEvents); - - /** - * @param responseStatus The (HTTP) response or null if there was no response. - * @param exception The exception or null if there was no exception. - * @return A human-friendly error message. - */ - public static String createDefaultFailureMessage(UpnpResponse responseStatus, Exception exception) { - String message = "Subscription failed: "; - if (responseStatus != null) { - message = message + " HTTP response was: " + responseStatus.getResponseDetails(); - } else if (exception != null) { - message = message + " Exception occured: " + exception; - } else { - message = message + " No response received."; - } - return message; - } - - /** - * Called when a received event message could not be parsed successfully. - *

- * This typically indicates a broken device which is not UPnP compliant. You can - * react to this failure in any way you like, for example, you could terminate - * the subscription or simply create an error report/log. - *

- *

- * The default implementation will log the exception at INFO level, and - * the invalid XML at FINE level. - *

- * - * @param remoteGENASubscription The established subscription. - * @param ex Call {@link org.fourthline.cling.model.UnsupportedDataException#getData()} to access the invalid XML. - */ - protected void invalidMessage(RemoteGENASubscription remoteGENASubscription, - UnsupportedDataException ex) { - log.info("Invalid event message received, causing: " + ex); - if (log.isLoggable(Level.FINE)) { - log.fine("------------------------------------------------------------------------------"); - log.fine(ex.getData() != null ? ex.getData().toString() : "null"); - log.fine("------------------------------------------------------------------------------"); - } - } - - @Override - public String toString() { - return "(SubscriptionCallback) " + getService(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/event/ExecuteAction.java b/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/event/ExecuteAction.java deleted file mode 100644 index 65838bc..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/event/ExecuteAction.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.controlpoint.event; - -import org.fourthline.cling.controlpoint.ActionCallback; - -/** - * @author Christian Bauer - */ -public class ExecuteAction { - - protected ActionCallback callback; - - public ExecuteAction(ActionCallback callback) { - this.callback = callback; - } - - public ActionCallback getCallback() { - return callback; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/event/Search.java b/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/event/Search.java deleted file mode 100644 index 7002523..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/controlpoint/event/Search.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.controlpoint.event; - -import org.fourthline.cling.model.message.header.MXHeader; -import org.fourthline.cling.model.message.header.STAllHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -/** - * @author Christian Bauer - */ -public class Search { - - protected UpnpHeader searchType = new STAllHeader(); - protected int mxSeconds = MXHeader.DEFAULT_VALUE; - - public Search() { - } - - public Search(UpnpHeader searchType) { - this.searchType = searchType; - } - - public Search(UpnpHeader searchType, int mxSeconds) { - this.searchType = searchType; - this.mxSeconds = mxSeconds; - } - - public Search(int mxSeconds) { - this.mxSeconds = mxSeconds; - } - - public UpnpHeader getSearchType() { - return searchType; - } - - public int getMxSeconds() { - return mxSeconds; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/mock/MockProtocolFactory.java b/clinglibrary/src/main/java/org/fourthline/cling/mock/MockProtocolFactory.java deleted file mode 100644 index 292b49f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/mock/MockProtocolFactory.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.mock; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.gena.LocalGENASubscription; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.protocol.ProtocolCreationException; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.protocol.ReceivingAsync; -import org.fourthline.cling.protocol.ReceivingSync; -import org.fourthline.cling.protocol.async.SendingNotificationAlive; -import org.fourthline.cling.protocol.async.SendingNotificationByebye; -import org.fourthline.cling.protocol.async.SendingSearch; -import org.fourthline.cling.protocol.sync.SendingAction; -import org.fourthline.cling.protocol.sync.SendingEvent; -import org.fourthline.cling.protocol.sync.SendingRenewal; -import org.fourthline.cling.protocol.sync.SendingSubscribe; -import org.fourthline.cling.protocol.sync.SendingUnsubscribe; - -import javax.enterprise.inject.Alternative; -import java.net.URL; - -/** - * @author Christian Bauer - */ -@Alternative -public class MockProtocolFactory implements ProtocolFactory { - - @Override - public UpnpService getUpnpService() { - return null; - } - - @Override - public ReceivingAsync createReceivingAsync(IncomingDatagramMessage message) throws ProtocolCreationException { - return null; - } - - @Override - public ReceivingSync createReceivingSync(StreamRequestMessage requestMessage) throws ProtocolCreationException { - return null; - } - - @Override - public SendingNotificationAlive createSendingNotificationAlive(LocalDevice localDevice) { - return null; - } - - @Override - public SendingNotificationByebye createSendingNotificationByebye(LocalDevice localDevice) { - return null; - } - - @Override - public SendingSearch createSendingSearch(UpnpHeader searchTarget, int mxSeconds) { - return null; - } - - @Override - public SendingAction createSendingAction(ActionInvocation actionInvocation, URL controlURL) { - return null; - } - - @Override - public SendingSubscribe createSendingSubscribe(RemoteGENASubscription subscription) { - return null; - } - - @Override - public SendingRenewal createSendingRenewal(RemoteGENASubscription subscription) { - return null; - } - - @Override - public SendingUnsubscribe createSendingUnsubscribe(RemoteGENASubscription subscription) { - return null; - } - - @Override - public SendingEvent createSendingEvent(LocalGENASubscription subscription) { - return null; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/mock/MockRouter.java b/clinglibrary/src/main/java/org/fourthline/cling/mock/MockRouter.java deleted file mode 100644 index 7d4326b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/mock/MockRouter.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.mock; - -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.model.NetworkAddress; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.OutgoingDatagramMessage; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.transport.Router; -import org.fourthline.cling.transport.RouterException; -import org.fourthline.cling.transport.impl.NetworkAddressFactoryImpl; -import org.fourthline.cling.transport.spi.InitializationException; -import org.fourthline.cling.transport.spi.NetworkAddressFactory; -import org.fourthline.cling.transport.spi.UpnpStream; - -import javax.enterprise.inject.Alternative; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - *

- * This is not a real network transport layer, it collects all messages instead and makes - * them available for testing with {@link #getOutgoingDatagramMessages()}, - * {@link #getSentStreamRequestMessages()}, etc. Mock responses for TCP (HTTP) stream requests - * can be returned by overriding {@link #getStreamResponseMessage(org.fourthline.cling.model.message.StreamRequestMessage)} - * or {@link #getStreamResponseMessages()} if you know the order of requests. - *

- * - * @author Christian Bauer - */ -@Alternative -public class MockRouter implements Router { - - public int counter = -1; - public List incomingDatagramMessages = new ArrayList<>(); - public List outgoingDatagramMessages = new ArrayList<>(); - public List receivedUpnpStreams = new ArrayList<>(); - public List sentStreamRequestMessages = new ArrayList<>(); - public List broadcastedBytes = new ArrayList<>(); - - protected UpnpServiceConfiguration configuration; - protected ProtocolFactory protocolFactory; - - public MockRouter(UpnpServiceConfiguration configuration, - ProtocolFactory protocolFactory) { - this.configuration = configuration; - this.protocolFactory = protocolFactory; - } - - @Override - public UpnpServiceConfiguration getConfiguration() { - return configuration; - } - - @Override - public ProtocolFactory getProtocolFactory() { - return protocolFactory; - } - - @Override - public boolean enable() throws RouterException { - return false; - } - - @Override - public boolean disable() throws RouterException { - return false; - } - - @Override - public void shutdown() throws RouterException { - } - - @Override - public boolean isEnabled() throws RouterException { - return false; - } - - @Override - public void handleStartFailure(InitializationException ex) throws InitializationException { - } - - @Override - public List getActiveStreamServers(InetAddress preferredAddress) throws RouterException { - // Simulate an active stream server, otherwise the notification/search response - // protocols won't even run - try { - return Arrays.asList( - new NetworkAddress( - InetAddress.getByName("127.0.0.1"), - NetworkAddressFactoryImpl.DEFAULT_TCP_HTTP_LISTEN_PORT - ) - ); - } catch (UnknownHostException ex) { - throw new RuntimeException(ex); - } - } - - public void received(IncomingDatagramMessage msg) { - incomingDatagramMessages.add(msg); - } - - public void received(UpnpStream stream) { - receivedUpnpStreams.add(stream); - } - - public void send(OutgoingDatagramMessage msg) throws RouterException { - outgoingDatagramMessages.add(msg); - } - - public StreamResponseMessage send(StreamRequestMessage msg) throws RouterException { - sentStreamRequestMessages.add(msg); - counter++; - return getStreamResponseMessages() != null - ? getStreamResponseMessages()[counter] - : getStreamResponseMessage(msg); - } - - public void broadcast(byte[] bytes) { - broadcastedBytes.add(bytes); - } - - public void resetStreamRequestMessageCounter() { - counter = -1; - } - - public List getIncomingDatagramMessages() { - return incomingDatagramMessages; - } - - public List getOutgoingDatagramMessages() { - return outgoingDatagramMessages; - } - - public List getReceivedUpnpStreams() { - return receivedUpnpStreams; - } - - public List getSentStreamRequestMessages() { - return sentStreamRequestMessages; - } - - public List getBroadcastedBytes() { - return broadcastedBytes; - } - - public StreamResponseMessage[] getStreamResponseMessages() { - return null; - } - - public StreamResponseMessage getStreamResponseMessage(StreamRequestMessage request) { - return null; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/mock/MockUpnpService.java b/clinglibrary/src/main/java/org/fourthline/cling/mock/MockUpnpService.java deleted file mode 100644 index 3e4e602..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/mock/MockUpnpService.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.mock; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.controlpoint.ControlPointImpl; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.protocol.ProtocolFactoryImpl; -import org.fourthline.cling.protocol.async.SendingNotificationAlive; -import org.fourthline.cling.protocol.async.SendingSearch; -import org.fourthline.cling.registry.Registry; -import org.fourthline.cling.registry.RegistryImpl; -import org.fourthline.cling.registry.RegistryMaintainer; -import org.fourthline.cling.transport.RouterException; -import org.fourthline.cling.transport.spi.NetworkAddressFactory; - -import javax.enterprise.inject.Alternative; - -/** - * Simplifies testing of core and non-core modules. - *

- * It uses the {@link org.fourthline.cling.mock.MockUpnpService.MockProtocolFactory}. - *

- * - * @author Christian Bauer - */ -@Alternative -public class MockUpnpService implements UpnpService { - - protected final UpnpServiceConfiguration configuration; - protected final ControlPoint controlPoint; - protected final ProtocolFactory protocolFactory; - protected final Registry registry; - protected final MockRouter router; - - protected final NetworkAddressFactory networkAddressFactory; - - /** - * Single-thread of execution for the whole UPnP stack, no ALIVE messages or registry maintenance. - */ - public MockUpnpService() { - this(false, new MockUpnpServiceConfiguration(false, false)); - } - - /** - * No ALIVE messages. - */ - public MockUpnpService(MockUpnpServiceConfiguration configuration) { - this(false, configuration); - } - - /** - * Single-thread of execution for the whole UPnP stack, except one background registry maintenance thread. - */ - public MockUpnpService(final boolean sendsAlive, final boolean maintainsRegistry) { - this(sendsAlive, new MockUpnpServiceConfiguration(maintainsRegistry, false)); - } - - public MockUpnpService(final boolean sendsAlive, final boolean maintainsRegistry, final boolean multiThreaded) { - this(sendsAlive, new MockUpnpServiceConfiguration(maintainsRegistry, multiThreaded)); - } - - public MockUpnpService(final boolean sendsAlive, final MockUpnpServiceConfiguration configuration) { - - this.configuration = configuration; - - this.protocolFactory = createProtocolFactory(this, sendsAlive); - - this.registry = new RegistryImpl(this) { - @Override - protected RegistryMaintainer createRegistryMaintainer() { - return configuration.isMaintainsRegistry() ? super.createRegistryMaintainer() : null; - } - }; - - this.networkAddressFactory = this.configuration.createNetworkAddressFactory(); - - this.router = createRouter(); - - this.controlPoint = new ControlPointImpl(configuration, protocolFactory, registry); - } - - protected ProtocolFactory createProtocolFactory(UpnpService service, boolean sendsAlive) { - return new MockProtocolFactory(service, sendsAlive); - } - - protected MockRouter createRouter() { - return new MockRouter(getConfiguration(), getProtocolFactory()); - } - - /** - * This factory customizes several protocols. - *

- * The {@link org.fourthline.cling.protocol.async.SendingNotificationAlive} protocol - * only sends messages if this feature is enabled when instantiating the factory. - *

- *

- * The {@link org.fourthline.cling.protocol.async.SendingSearch} protocol doesn't wait between - * sending search message bulks, this speeds up testing. - *

- */ - public static class MockProtocolFactory extends ProtocolFactoryImpl { - - private boolean sendsAlive; - - public MockProtocolFactory(UpnpService upnpService, boolean sendsAlive) { - super(upnpService); - this.sendsAlive = sendsAlive; - } - - @Override - public SendingNotificationAlive createSendingNotificationAlive(LocalDevice localDevice) { - return new SendingNotificationAlive(getUpnpService(), localDevice) { - @Override - protected void execute() throws RouterException { - if (sendsAlive) super.execute(); - } - }; - } - - @Override - public SendingSearch createSendingSearch(UpnpHeader searchTarget, int mxSeconds) { - return new SendingSearch(getUpnpService(), searchTarget, mxSeconds) { - @Override - public int getBulkIntervalMilliseconds() { - return 0; // Don't wait - } - }; - } - } - - public UpnpServiceConfiguration getConfiguration() { - return configuration; - } - - public ControlPoint getControlPoint() { - return controlPoint; - } - - public ProtocolFactory getProtocolFactory() { - return protocolFactory; - } - - public Registry getRegistry() { - return registry; - } - - public MockRouter getRouter() { - return router; - } - - public void shutdown() { - getRegistry().shutdown(); - getConfiguration().shutdown(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/mock/MockUpnpServiceConfiguration.java b/clinglibrary/src/main/java/org/fourthline/cling/mock/MockUpnpServiceConfiguration.java deleted file mode 100644 index 80aff81..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/mock/MockUpnpServiceConfiguration.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.mock; - -import org.fourthline.cling.DefaultUpnpServiceConfiguration; -import org.fourthline.cling.transport.impl.NetworkAddressFactoryImpl; -import org.fourthline.cling.transport.spi.NetworkAddressFactory; - -import javax.enterprise.inject.Alternative; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.List; -import java.util.concurrent.AbstractExecutorService; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; - -/** - * @author Christian Bauer - */ -@Alternative -public class MockUpnpServiceConfiguration extends DefaultUpnpServiceConfiguration { - - final protected boolean maintainsRegistry; - final protected boolean multiThreaded; - - /** - * Does not maintain registry, single threaded execution. - */ - public MockUpnpServiceConfiguration() { - this(false, false); - } - - /** - * Single threaded execution. - */ - public MockUpnpServiceConfiguration(boolean maintainsRegistry) { - this(maintainsRegistry, false); - } - - public MockUpnpServiceConfiguration(boolean maintainsRegistry, boolean multiThreaded) { - super(false); - this.maintainsRegistry = maintainsRegistry; - this.multiThreaded = multiThreaded; - } - - public boolean isMaintainsRegistry() { - return maintainsRegistry; - } - - public boolean isMultiThreaded() { - return multiThreaded; - } - - @Override - protected NetworkAddressFactory createNetworkAddressFactory(int streamListenPort) { - // We are only interested in 127.0.0.1 - return new NetworkAddressFactoryImpl(streamListenPort) { - @Override - protected boolean isUsableNetworkInterface(NetworkInterface iface) throws Exception { - return (iface.isLoopback()); - } - - @Override - protected boolean isUsableAddress(NetworkInterface networkInterface, InetAddress address) { - return (address.isLoopbackAddress() && address instanceof Inet4Address); - } - - }; - } - - @Override - public Executor getRegistryMaintainerExecutor() { - if (isMaintainsRegistry()) { - return new Executor() { - public void execute(Runnable runnable) { - new Thread(runnable).start(); - } - }; - } - return getDefaultExecutorService(); - } - - @Override - protected ExecutorService getDefaultExecutorService() { - if (isMultiThreaded()) { - return super.getDefaultExecutorService(); - } - return new AbstractExecutorService() { - - boolean terminated; - - public void shutdown() { - terminated = true; - } - - public List shutdownNow() { - shutdown(); - return null; - } - - public boolean isShutdown() { - return terminated; - } - - public boolean isTerminated() { - return terminated; - } - - public boolean awaitTermination(long l, TimeUnit timeUnit) throws InterruptedException { - shutdown(); - return terminated; - } - - public void execute(Runnable runnable) { - runnable.run(); - } - }; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/Command.java b/clinglibrary/src/main/java/org/fourthline/cling/model/Command.java deleted file mode 100644 index 21e9dc8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/Command.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -/** - * Executable procedure, invoked and potentially decorated by the {@link org.fourthline.cling.model.ServiceManager}. - * - * @author Christian Bauer - */ -public interface Command { - - public void execute(ServiceManager manager) throws Exception; -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/Constants.java b/clinglibrary/src/main/java/org/fourthline/cling/model/Constants.java deleted file mode 100644 index 326db1d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/Constants.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -/** - * Shared and immutable settings. - * - * @author Christian Bauer - */ -public interface Constants { - - public static final String SYSTEM_PROPERTY_ANNOUNCE_MAC_ADDRESS = "org.fourthline.cling.network.announceMACAddress"; - - public static final int UPNP_MULTICAST_PORT = 1900; - - public static final String IPV4_UPNP_MULTICAST_GROUP = "239.255.255.250"; - - public static final String IPV6_UPNP_LINK_LOCAL_ADDRESS = "FF02::C"; - public static final String IPV6_UPNP_SUBNET_ADDRESS = "FF03::C"; - public static final String IPV6_UPNP_ADMINISTRATIVE_ADDRESS = "FF04::C"; - public static final String IPV6_UPNP_SITE_LOCAL_ADDRESS = "FF05::C"; - public static final String IPV6_UPNP_GLOBAL_ADDRESS = "FF0E::C"; - - public static final int MIN_ADVERTISEMENT_AGE_SECONDS = 1800; - - // Parsing rules for: deviceType, serviceType, serviceId (UDA 1.0, section 2.5) - - // TODO: UPNP VIOLATION: Microsoft Windows Media Player Sharing 4.0, X_MS_MediaReceiverRegistrar service has type with periods instead of hyphens in the namespace! - // UDA 1.0 spec: "Period characters in the vendor domain name MUST be replaced with hyphens in accordance with RFC 2141" - // TODO: UPNP VIOLATION: Azureus/Vuze 4.2.0.2 sends a URN as a service identifier, so we need to match colons! - // TODO: UPNP VIOLATION: Intel UPnP Tools send dots in the service identifier suffix, match that... - - public static final String REGEX_NAMESPACE = "[a-zA-Z0-9\\-\\.]+"; - public static final String REGEX_TYPE = "[a-zA-Z_0-9\\-]{1,64}"; - public static final String REGEX_ID = "[a-zA-Z_0-9\\-:\\.]{1,64}"; - - /* - Must not contain a hyphen character (-, 2D Hex in UTF- 8). First character must be a USASCII letter (A-Z, a-z), - USASCII digit (0-9), an underscore ("_"), or a non-experimental Unicode letter or digit greater than U+007F. - Succeeding characters must be a USASCII letter (A-Z, a-z), USASCII digit (0-9), an underscore ("_"), a - period ("."), a Unicode combiningchar, an extender, or a non-experimental Unicode letter or digit greater - than U+007F. The first three letters must not be "XML" in any combination of case. Case sensitive. - */ - // TODO: I have no idea how to match or what even is a "unicode extender character", neither does the Unicode book - public static final String REGEX_UDA_NAME = "[a-zA-Z0-9^-_\\p{L}\\p{N}]{1}[a-zA-Z0-9^-_\\.\\\\p{L}\\\\p{N}\\p{Mc}\\p{Sk}]*"; - - // Random patentable "inventions" by MSFT - public static final String SOAP_NS_ENVELOPE = "http://schemas.xmlsoap.org/soap/envelope/"; - public static final String SOAP_URI_ENCODING_STYLE = "http://schemas.xmlsoap.org/soap/encoding/"; - public static final String NS_UPNP_CONTROL_10 = "urn:schemas-upnp-org:control-1-0"; - public static final String NS_UPNP_EVENT_10 = "urn:schemas-upnp-org:event-1-0"; - - // State variable prefixes - public static final String ARG_TYPE_PREFIX = "A_ARG_TYPE_"; - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/DefaultServiceManager.java b/clinglibrary/src/main/java/org/fourthline/cling/model/DefaultServiceManager.java deleted file mode 100644 index facde0c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/DefaultServiceManager.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.state.StateVariableAccessor; -import org.fourthline.cling.model.state.StateVariableValue; -import org.seamless.util.Exceptions; -import org.seamless.util.Reflections; - -/** - * Default implementation, creates and manages a single instance of a plain Java bean. - *

- * Creates instance of the defined service class when it is first needed (acts as a factory), - * manages the instance in a field (it's shared), and synchronizes (locks) all - * multi-threaded access. A locking attempt will timeout after 500 milliseconds with - * a runtime exception if another operation is already in progress. Override - * {@link #getLockTimeoutMillis()} to customize this behavior, e.g. if your service - * bean is slow and requires more time for typical action executions or state - * variable reading. - *

- * - * @author Christian Bauer - */ -public class DefaultServiceManager implements ServiceManager { - - private static Logger log = Logger.getLogger(DefaultServiceManager.class.getName()); - - final protected LocalService service; - final protected Class serviceClass; - final protected ReentrantLock lock = new ReentrantLock(true); - - // Locking! - protected T serviceImpl; - protected PropertyChangeSupport propertyChangeSupport; - - protected DefaultServiceManager(LocalService service) { - this(service, null); - } - - public DefaultServiceManager(LocalService service, Class serviceClass) { - this.service = service; - this.serviceClass = serviceClass; - } - - // The monitor entry and exit methods - - protected void lock() { - try { - if (lock.tryLock(getLockTimeoutMillis(), TimeUnit.MILLISECONDS)) { - if (log.isLoggable(Level.FINEST)) - log.finest("Acquired lock"); - } else { - throw new RuntimeException("Failed to acquire lock in milliseconds: " + getLockTimeoutMillis()); - } - } catch (InterruptedException e) { - throw new RuntimeException("Failed to acquire lock:" + e); - } - } - - protected void unlock() { - if (log.isLoggable(Level.FINEST)) - log.finest("Releasing lock"); - lock.unlock(); - } - - protected int getLockTimeoutMillis() { - return 500; - } - - public LocalService getService() { - return service; - } - - public T getImplementation() { - lock(); - try { - if (serviceImpl == null) { - init(); - } - return serviceImpl; - } finally { - unlock(); - } - } - - public PropertyChangeSupport getPropertyChangeSupport() { - lock(); - try { - if (propertyChangeSupport == null) { - init(); - } - return propertyChangeSupport; - } finally { - unlock(); - } - } - - public void execute(Command cmd) throws Exception { - lock(); - try { - cmd.execute(this); - } finally { - unlock(); - } - } - - @Override - public Collection getCurrentState() throws Exception { - lock(); - try { - Collection values = readInitialEventedStateVariableValues(); - if (values != null) { - log.fine("Obtained initial state variable values for event, skipping individual state variable accessors"); - return values; - } - values = new ArrayList<>(); - for (StateVariable stateVariable : getService().getStateVariables()) { - if (stateVariable.getEventDetails().isSendEvents()) { - StateVariableAccessor accessor = getService().getAccessor(stateVariable); - if (accessor == null) - throw new IllegalStateException("No accessor for evented state variable"); - values.add(accessor.read(stateVariable, getImplementation())); - } - } - return values; - } finally { - unlock(); - } - } - - protected Collection getCurrentState(String[] variableNames) throws Exception { - lock(); - try { - Collection values = new ArrayList<>(); - for (String variableName : variableNames) { - variableName = variableName.trim(); - - StateVariable stateVariable = getService().getStateVariable(variableName); - if (stateVariable == null || !stateVariable.getEventDetails().isSendEvents()) { - log.fine("Ignoring unknown or non-evented state variable: " + variableName); - continue; - } - - StateVariableAccessor accessor = getService().getAccessor(stateVariable); - if (accessor == null) { - log.warning("Ignoring evented state variable without accessor: " + variableName); - continue; - } - values.add(accessor.read(stateVariable, getImplementation())); - } - return values; - } finally { - unlock(); - } - } - - protected void init() { - log.fine("No service implementation instance available, initializing..."); - try { - // The actual instance we ware going to use and hold a reference to (1:1 instance for manager) - serviceImpl = createServiceInstance(); - - // How the implementation instance will tell us about property changes - propertyChangeSupport = createPropertyChangeSupport(serviceImpl); - propertyChangeSupport.addPropertyChangeListener(createPropertyChangeListener(serviceImpl)); - - } catch (Exception ex) { - throw new RuntimeException("Could not initialize implementation: " + ex, ex); - } - } - - protected T createServiceInstance() throws Exception { - if (serviceClass == null) { - throw new IllegalStateException("Subclass has to provide service class or override createServiceInstance()"); - } - try { - // Use this constructor if possible - return serviceClass.getConstructor(LocalService.class).newInstance(getService()); - } catch (NoSuchMethodException ex) { - log.fine("Creating new service implementation instance with no-arg constructor: " + serviceClass.getName()); - return serviceClass.newInstance(); - } - } - - protected PropertyChangeSupport createPropertyChangeSupport(T serviceImpl) throws Exception { - Method m; - if ((m = Reflections.getGetterMethod(serviceImpl.getClass(), "propertyChangeSupport")) != null && - PropertyChangeSupport.class.isAssignableFrom(m.getReturnType())) { - log.fine("Service implementation instance offers PropertyChangeSupport, using that: " + serviceImpl.getClass().getName()); - return (PropertyChangeSupport) m.invoke(serviceImpl); - } - log.fine("Creating new PropertyChangeSupport for service implementation: " + serviceImpl.getClass().getName()); - return new PropertyChangeSupport(serviceImpl); - } - - protected PropertyChangeListener createPropertyChangeListener(T serviceImpl) throws Exception { - return new DefaultPropertyChangeListener(); - } - - protected Collection readInitialEventedStateVariableValues() throws Exception { - return null; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") Implementation: " + serviceImpl; - } - - protected class DefaultPropertyChangeListener implements PropertyChangeListener { - - public void propertyChange(PropertyChangeEvent e) { - log.finer("Property change event on local service: " + e.getPropertyName()); - - // Prevent recursion - if (e.getPropertyName().equals(EVENTED_STATE_VARIABLES)) return; - - String[] variableNames = ModelUtil.fromCommaSeparatedList(e.getPropertyName()); - log.fine("Changed variable names: " + Arrays.toString(variableNames)); - - try { - Collection currentValues = getCurrentState(variableNames); - - if (!currentValues.isEmpty()) { - getPropertyChangeSupport().firePropertyChange( - EVENTED_STATE_VARIABLES, - null, - currentValues - ); - } - - } catch (Exception ex) { - // TODO: Is it OK to only log this error? It means we keep running although we couldn't send events? - log.log( - Level.SEVERE, - "Error reading state of service after state variable update event: " + Exceptions.unwrap(ex), - ex - ); - } - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/DiscoveryOptions.java b/clinglibrary/src/main/java/org/fourthline/cling/model/DiscoveryOptions.java deleted file mode 100644 index 54e68e0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/DiscoveryOptions.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -/** - * Options for discovery processing by the {@link org.fourthline.cling.registry.Registry}. - * - * @author Christian Bauer - */ -public class DiscoveryOptions { - - protected boolean advertised; - protected boolean byeByeBeforeFirstAlive; - - /** - * @param advertised If false, no alive notifications will be announced for - * this device and it will not appear in search responses. - */ - public DiscoveryOptions(boolean advertised) { - this.advertised = advertised; - } - - /** - * - * @param advertised If false, no alive notifications will be announced for - * this device and it will not appear in search responses. - * @param byeByeBeforeFirstAlive If true, a byebye NOTIFY message will be send before the - * first alive NOTIFY message. - */ - public DiscoveryOptions(boolean advertised, boolean byeByeBeforeFirstAlive) { - this.advertised = advertised; - this.byeByeBeforeFirstAlive = byeByeBeforeFirstAlive; - } - - /** - * @return true for regular advertisement with alive - * messages and in search responses. - */ - public boolean isAdvertised() { - return advertised; - } - - /** - * @return true if a byebye NOTIFY message will be send before the - * first alive NOTIFY message. - */ - public boolean isByeByeBeforeFirstAlive() { - return byeByeBeforeFirstAlive; - } - - // Performance optimization on Android - private static String simpleName = DiscoveryOptions.class.getSimpleName(); - @Override - public String toString() { - return "(" + simpleName + ")" + " advertised: " + isAdvertised() + " byebyeBeforeFirstAlive: " + isByeByeBeforeFirstAlive(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/ExpirationDetails.java b/clinglibrary/src/main/java/org/fourthline/cling/model/ExpirationDetails.java deleted file mode 100644 index c29c1b6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/ExpirationDetails.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import java.util.Date; - -/** - * @author Christian Bauer - */ -public class ExpirationDetails { - - public static final int UNLIMITED_AGE = 0; - - private int maxAgeSeconds = UNLIMITED_AGE; - private long lastRefreshTimestampSeconds = getCurrentTimestampSeconds(); - - public ExpirationDetails() { - } - - public ExpirationDetails(int maxAgeSeconds) { - this.maxAgeSeconds = maxAgeSeconds; - } - - public int getMaxAgeSeconds() { - return maxAgeSeconds; - } - - public long getLastRefreshTimestampSeconds() { - return lastRefreshTimestampSeconds; - } - - public void setLastRefreshTimestampSeconds(long lastRefreshTimestampSeconds) { - this.lastRefreshTimestampSeconds = lastRefreshTimestampSeconds; - } - - public void stampLastRefresh() { - setLastRefreshTimestampSeconds(getCurrentTimestampSeconds()); - } - - public boolean hasExpired() { - return hasExpired(false); - } - - /** - * @param halfTime If true then half maximum age is used to determine expiration. - * @return true if the maximum age has been reached. - */ - public boolean hasExpired(boolean halfTime) { - // Note: Uses direct field access for performance reasons on Android - return maxAgeSeconds != UNLIMITED_AGE && - (lastRefreshTimestampSeconds + (maxAgeSeconds/(halfTime ? 2 : 1))) < getCurrentTimestampSeconds(); - } - - public long getSecondsUntilExpiration() { - // Note: Uses direct field access for performance reasons on Android - return maxAgeSeconds == UNLIMITED_AGE - ? Integer.MAX_VALUE - : (lastRefreshTimestampSeconds + maxAgeSeconds) - getCurrentTimestampSeconds(); - } - - protected long getCurrentTimestampSeconds() { - return new Date().getTime()/1000; - } - - // Performance optimization on Android - private static String simpleName = ExpirationDetails.class.getSimpleName(); - @Override - public String toString() { - return "(" + simpleName + ")" + " MAX AGE: " + maxAgeSeconds; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/Location.java b/clinglibrary/src/main/java/org/fourthline/cling/model/Location.java deleted file mode 100644 index 83f0227..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/Location.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import java.net.InetAddress; -import java.net.URI; -import java.net.URL; - -/** - * The IP address/port, MAC address, and URI path of a (network) location. - *

- * Used when sending messages about local devices and services to - * other UPnP participants on the network, such as where our device/service - * descriptors can be found or what callback address to use for event message - * delivery. We also let them know our MAC hardware address so they - * can wake us up from sleep with Wake-On-LAN if necessary. - *

- * - * @author Christian Bauer - */ -public class Location { - - protected final NetworkAddress networkAddress; - protected final String path; - protected final URL url; - - public Location(NetworkAddress networkAddress, String path) { - this.networkAddress = networkAddress; - this.path = path; - this.url = createAbsoluteURL(networkAddress.getAddress(), networkAddress.getPort(), path); - } - - public NetworkAddress getNetworkAddress() { - return networkAddress; - } - - public String getPath() { - return path; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Location location = (Location) o; - - if (!networkAddress.equals(location.networkAddress)) return false; - if (!path.equals(location.path)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = networkAddress.hashCode(); - result = 31 * result + path.hashCode(); - return result; - } - - /** - * @return An HTTP URL with the address, port, and path of this location. - */ - public URL getURL() { - return url; - } - - // Performance optimization on Android - private static URL createAbsoluteURL(InetAddress address, int localStreamPort, String path) { - try { - return new URL("http", address.getHostAddress(), localStreamPort, path); - } catch (Exception ex) { - throw new IllegalArgumentException("Address, port, and URI can not be converted to URL", ex); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/ModelUtil.java b/clinglibrary/src/main/java/org/fourthline/cling/model/ModelUtil.java deleted file mode 100644 index c45de7e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/ModelUtil.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.Collections; -import java.util.Enumeration; -import java.util.Set; -import java.util.Locale; - -/** - * Shared trivial procedures. - * - * @author Christian Bauer - */ -public class ModelUtil { - - /** - * True if this class is executing on an Android runtime - */ - final public static boolean ANDROID_RUNTIME; - static { - boolean foundAndroid = false; - try { - Class androidBuild = Thread.currentThread().getContextClassLoader().loadClass("android.os.Build"); - foundAndroid = androidBuild.getField("ID").get(null) != null; - } catch (Exception ex) { - // Ignore - } - ANDROID_RUNTIME = foundAndroid; - } - - /** - * True if this class is executing on an Android emulator runtime. - */ - final public static boolean ANDROID_EMULATOR; - static { - boolean foundEmulator = false; - try { - Class androidBuild = Thread.currentThread().getContextClassLoader().loadClass("android.os.Build"); - String product = (String)androidBuild.getField("PRODUCT").get(null); - if ("google_sdk".equals(product) || ("sdk".equals(product))) - foundEmulator = true; - } catch (Exception ex) { - // Ignore - } - ANDROID_EMULATOR = foundEmulator; - } - - /** - * @param stringConvertibleTypes A collection of interfaces. - * @param clazz An interface to test. - * @return true if the given interface is an Enum, or if the collection contains a super-interface. - */ - public static boolean isStringConvertibleType(Set stringConvertibleTypes, Class clazz) { - if (clazz.isEnum()) return true; - for (Class toStringOutputType : stringConvertibleTypes) { - if (toStringOutputType.isAssignableFrom(clazz)) { - return true; - } - } - return false; - } - - /** - * @param name A UPnP device architecture "name" string. - * @return true if the name is not empty, doesn't start with "xml", and - * matches {@link org.fourthline.cling.model.Constants#REGEX_UDA_NAME}. - */ - public static boolean isValidUDAName(String name) { - if (ANDROID_RUNTIME) { - return name != null && name.length() != 0; - } - return name != null && name.length() != 0 && !name.toLowerCase(Locale.ROOT).startsWith("xml") && name.matches(Constants.REGEX_UDA_NAME); - } - - /** - * Wraps the checked exception in a runtime exception. - */ - public static InetAddress getInetAddressByName(String name) { - try { - return InetAddress.getByName(name); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - /** - * Converts the given instances into comma-separated elements of a string, - * escaping commas with backslashes. - */ - public static String toCommaSeparatedList(Object[] o) { - return toCommaSeparatedList(o, true, false); - } - - /** - * Converts the given instances into comma-separated elements of a string, - * optionally escapes commas and double quotes with backslahses. - */ - public static String toCommaSeparatedList(Object[] o, boolean escapeCommas, boolean escapeDoubleQuotes) { - if (o == null) { - return ""; - } - StringBuilder sb = new StringBuilder(); - for (Object obj : o) { - String objString = obj.toString(); - objString = objString.replaceAll("\\\\", "\\\\\\\\"); // Replace one backslash with two (nice, eh?) - if (escapeCommas) { - objString = objString.replaceAll(",", "\\\\,"); - } - if (escapeDoubleQuotes) { - objString = objString.replaceAll("\"", "\\\""); - } - sb.append(objString).append(","); - } - if (sb.length() > 1) { - sb.deleteCharAt(sb.length() - 1); - } - return sb.toString(); - - } - - /** - * Converts the comma-separated elements of a string into an array of strings, - * unescaping backslashed commas. - */ - public static String[] fromCommaSeparatedList(String s) { - return fromCommaSeparatedList(s, true); - } - - /** - * Converts the comma-separated elements of a string into an array of strings, - * optionally unescaping backslashed commas. - */ - public static String[] fromCommaSeparatedList(String s, boolean unescapeCommas) { - if (s == null || s.length() == 0) { - return null; - } - - final String QUOTED_COMMA_PLACEHOLDER = "XXX1122334455XXX"; - if (unescapeCommas) { - s = s.replaceAll("\\\\,", QUOTED_COMMA_PLACEHOLDER); - } - - String[] split = s.split(","); - for (int i = 0; i < split.length; i++) { - split[i] = split[i].replaceAll(QUOTED_COMMA_PLACEHOLDER, ","); - split[i] = split[i].replaceAll("\\\\\\\\", "\\\\"); - } - return split; - } - - /** - * @param seconds The number of seconds to convert. - * @return A string representing hours, minutes, seconds, e.g. 11:23:44 - */ - public static String toTimeString(long seconds) { - long hours = seconds / 3600, - remainder = seconds % 3600, - minutes = remainder / 60, - secs = remainder % 60; - - return ((hours < 10 ? "0" : "") + hours - + ":" + (minutes < 10 ? "0" : "") + minutes - + ":" + (secs < 10 ? "0" : "") + secs); - } - - /** - * @param s A string representing hours, minutes, seconds, e.g. 11:23:44 - * @return The converted number of seconds. - */ - public static long fromTimeString(String s) { - // Handle "00:00:00.000" pattern, drop the milliseconds - if (s.lastIndexOf(".") != -1) - s = s.substring(0, s.lastIndexOf(".")); - String[] split = s.split(":"); - if (split.length != 3) - throw new IllegalArgumentException("Can't parse time string: " + s); - return (Long.parseLong(split[0]) * 3600) + - (Long.parseLong(split[1]) * 60) + - (Long.parseLong(split[2])); - } - - /** - * @param s A string with commas. - * @return The same string, a newline appended after every comma. - */ - public static String commaToNewline(String s) { - StringBuilder sb = new StringBuilder(); - String[] split = s.split(","); - for (String splitString : split) { - sb.append(splitString).append(",").append("\n"); - } - if (sb.length() > 2) { - sb.deleteCharAt(sb.length() - 2); - } - return sb.toString(); - } - - /** - * DNS reverse name lookup. - * - * @param includeDomain true if the whole FQDN should be returned, instead of just the first (host) part. - * @return The resolved host (and domain-) name, or "UNKNOWN HOST" if resolution failed. - */ - public static String getLocalHostName(boolean includeDomain) { - try { - String hostname = InetAddress.getLocalHost().getHostName(); - return includeDomain - ? hostname - : hostname.indexOf(".") != -1 ? hostname.substring(0, hostname.indexOf(".")) : hostname; - - } catch (Exception ex) { - // Return a dummy String - return "UNKNOWN HOST"; - } - } - - /** - * @return The MAC hardware address of the first network interface of this host. - */ - public static byte[] getFirstNetworkInterfaceHardwareAddress() { - try { - Enumeration interfaceEnumeration = NetworkInterface.getNetworkInterfaces(); - for (NetworkInterface iface : Collections.list(interfaceEnumeration)) { - if (!iface.isLoopback() && iface.isUp() && iface.getHardwareAddress() != null) { - return iface.getHardwareAddress(); - } - } - } catch (Exception ex) { - throw new RuntimeException("Could not discover first network interface hardware address"); - } - throw new RuntimeException("Could not discover first network interface hardware address"); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/Namespace.java b/clinglibrary/src/main/java/org/fourthline/cling/model/Namespace.java deleted file mode 100644 index dab4df1..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/Namespace.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.logging.Logger; - -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.meta.Icon; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.resource.Resource; -import org.seamless.util.URIUtil; - -/** - * Enforces path conventions for all locally offered resources (descriptors, icons, etc.) - *

- * Every descriptor, icon, event callback, or action message is send to a URL. This namespace - * defines how the path of this URL will look like and it will build the path for a given - * resource. - *

- *

- * By default, the namespace is organized as follows: - *

- *
{@code
- * http://host:port/dev//desc.xml
- * http://host:port/dev//svc///desc.xml
- * http://host:port/dev//svc///action
- * http://host:port/dev//svc///event
- * http://host:port/dev//svc///event/cb.xml
- * http://host:port/dev//svc///action
- * ...
- * }
- *

- * The namespace is also used to discover and create all {@link org.fourthline.cling.model.resource.Resource}s - * given a {@link org.fourthline.cling.model.meta.Device}'s metadata. This procedure is typically - * invoked once, when the device is added to the {@link org.fourthline.cling.registry.Registry}. - *

- * - * @author Christian Bauer - */ -public class Namespace { - - final private static Logger log = Logger.getLogger(Namespace.class.getName()); - - public static final String DEVICE = "/dev"; - public static final String SERVICE = "/svc"; - public static final String CONTROL = "/action"; - public static final String EVENTS = "/event"; - public static final String DESCRIPTOR_FILE = "/desc"; - public static final String CALLBACK_FILE = "/cb"; - - final protected URI basePath; - final protected String decodedPath; - - public Namespace() { - this(""); - } - - public Namespace(String basePath) { - this(URI.create(basePath)); - } - - public Namespace(URI basePath) { - this.basePath = basePath; - this.decodedPath = basePath.getPath(); - } - - public URI getBasePath() { - return basePath; - } - - public URI getPath(Device device) { - return appendPathToBaseURI(getDevicePath(device)); - } - - public URI getPath(Service service) { - return appendPathToBaseURI(getServicePath(service)); - } - - public URI getDescriptorPath(Device device) { - return appendPathToBaseURI(getDevicePath(device.getRoot()) + DESCRIPTOR_FILE); - } - - /** - * Performance optimization, avoids URI manipulation. - */ - public String getDescriptorPathString(Device device) { - return decodedPath + getDevicePath(device.getRoot()) + DESCRIPTOR_FILE; - } - - public URI getDescriptorPath(Service service) { - return appendPathToBaseURI(getServicePath(service) + DESCRIPTOR_FILE); - } - - public URI getControlPath(Service service) { - return appendPathToBaseURI(getServicePath(service) + CONTROL); - } - - public URI getIconPath(Icon icon) { - return appendPathToBaseURI(getDevicePath(icon.getDevice()) + "/" + icon.getUri().toString()); - } - - public URI getEventSubscriptionPath(Service service) { - return appendPathToBaseURI(getServicePath(service) + EVENTS); - } - - public URI getEventCallbackPath(Service service) { - return appendPathToBaseURI(getServicePath(service) + EVENTS + CALLBACK_FILE); - } - - /** - * Performance optimization, avoids URI manipulation. - */ - public String getEventCallbackPathString(Service service) { - return decodedPath + getServicePath(service) + EVENTS + CALLBACK_FILE; - } - - public URI prefixIfRelative(Device device, URI uri) { - if (!uri.isAbsolute() && !uri.getPath().startsWith("/")) { - return appendPathToBaseURI(getDevicePath(device) + "/" + uri); - } - return uri; - } - - public boolean isControlPath(URI uri) { - return uri.toString().endsWith(Namespace.CONTROL); - } - - public boolean isEventSubscriptionPath(URI uri) { - return uri.toString().endsWith(Namespace.EVENTS); - } - - public boolean isEventCallbackPath(URI uri) { - return uri.toString().endsWith(Namespace.CALLBACK_FILE); - } - - public Resource[] getResources(Device device) throws ValidationException { - if (!device.isRoot()) return null; - - Set resources = new HashSet<>(); - List errors = new ArrayList<>(); - - log.fine("Discovering local resources of device graph"); - Resource[] discoveredResources = device.discoverResources(this); - for (Resource resource : discoveredResources) { - log.finer("Discovered: " + resource); - if (!resources.add(resource)) { - log.finer("Local resource already exists, queueing validation error"); - errors.add(new ValidationError( - getClass(), - "resources", - "Local URI namespace conflict between resources of device: " + resource - )); - } - } - if (errors.size() > 0) { - throw new ValidationException("Validation of device graph failed, call getErrors() on exception", errors); - } - return resources.toArray(new Resource[resources.size()]); - } - - protected URI appendPathToBaseURI(String path) { - try { - // not calling getBasePath() on purpose since we're not sure if all DalvikVMs will inline it correctly - return - new URI( - basePath.getScheme(), - null, - basePath.getHost(), - basePath.getPort(), - decodedPath + path, - null, - null - ); - } catch (URISyntaxException e) { - return URI.create(basePath + path); - } - } - - protected String getDevicePath(Device device) { - if (device.getIdentity().getUdn() == null) { - throw new IllegalStateException("Can't generate local URI prefix without UDN"); - } - StringBuilder s = new StringBuilder(); - s.append(DEVICE).append("/"); - - s.append(URIUtil.encodePathSegment(device.getIdentity().getUdn().getIdentifierString())); - return s.toString(); - } - - protected String getServicePath(Service service) { - if (service.getServiceId() == null) { - throw new IllegalStateException("Can't generate local URI prefix without service ID"); - } - StringBuilder s = new StringBuilder(); - s.append(SERVICE); - s.append("/"); - s.append(service.getServiceId().getNamespace()); - s.append("/"); - s.append(service.getServiceId().getId()); - return getDevicePath(service.getDevice()) + s.toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/NetworkAddress.java b/clinglibrary/src/main/java/org/fourthline/cling/model/NetworkAddress.java deleted file mode 100644 index 837d6aa..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/NetworkAddress.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import java.net.InetAddress; -import java.util.Arrays; - -/** - * IP address, port, and optional interface hardware address (MAC) of a network service. - * - * @author Christian Bauer - */ -public class NetworkAddress { - - protected InetAddress address; - protected int port; - protected byte[] hardwareAddress; - - public NetworkAddress(InetAddress address, int port) { - this(address, port, null); - } - - public NetworkAddress(InetAddress address, int port, byte[] hardwareAddress) { - this.address = address; - this.port = port; - this.hardwareAddress = hardwareAddress; - } - - public InetAddress getAddress() { - return address; - } - - public int getPort() { - return port; - } - - public byte[] getHardwareAddress() { - return hardwareAddress; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - NetworkAddress that = (NetworkAddress) o; - - if (port != that.port) return false; - if (!address.equals(that.address)) return false; - if (!Arrays.equals(hardwareAddress, that.hardwareAddress)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = address.hashCode(); - result = 31 * result + port; - result = 31 * result + (hardwareAddress != null ? Arrays.hashCode(hardwareAddress) : 0); - return result; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/ServerClientTokens.java b/clinglibrary/src/main/java/org/fourthline/cling/model/ServerClientTokens.java deleted file mode 100644 index 1779bef..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/ServerClientTokens.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -/** - * The agent string of the UPnP stack in network messages, either as a server or client. - *

- * Tries to detect the operating system name and version, defaults to {@link UserConstants} - * for product name and version. - *

- * - * @author Christian Bauer - */ -public class ServerClientTokens { - - public static final String UNKNOWN_PLACEHOLDER = "UNKNOWN"; - - // TODO: This means we default to UDA 1.0 - private int majorVersion = 1; - private int minorVersion = 0; - - private String osName = System.getProperty("os.name").replaceAll("[^a-zA-Z0-9\\.\\-_]", ""); - private String osVersion = System.getProperty("os.version").replaceAll("[^a-zA-Z0-9\\.\\-_]", ""); - private String productName = UserConstants.PRODUCT_TOKEN_NAME; - private String productVersion = UserConstants.PRODUCT_TOKEN_VERSION; - - public ServerClientTokens() { - } - - public ServerClientTokens(int majorVersion, int minorVersion) { - this.majorVersion = majorVersion; - this.minorVersion = minorVersion; - } - - public ServerClientTokens(String productName, String productVersion) { - this.productName = productName; - this.productVersion = productVersion; - } - - public ServerClientTokens(int majorVersion, int minorVersion, String osName, String osVersion, String productName, String productVersion) { - this.majorVersion = majorVersion; - this.minorVersion = minorVersion; - this.osName = osName; - this.osVersion = osVersion; - this.productName = productName; - this.productVersion = productVersion; - } - - public int getMajorVersion() { - return majorVersion; - } - - public void setMajorVersion(int majorVersion) { - this.majorVersion = majorVersion; - } - - public int getMinorVersion() { - return minorVersion; - } - - public void setMinorVersion(int minorVersion) { - this.minorVersion = minorVersion; - } - - public String getOsName() { - return osName; - } - - public void setOsName(String osName) { - this.osName = osName; - } - - public String getOsVersion() { - return osVersion; - } - - public void setOsVersion(String osVersion) { - this.osVersion = osVersion; - } - - public String getProductName() { - return productName; - } - - public void setProductName(String productName) { - this.productName = productName; - } - - public String getProductVersion() { - return productVersion; - } - - public void setProductVersion(String productVersion) { - this.productVersion = productVersion; - } - - @Override - public String toString() { - return getOsName()+"/"+getOsVersion() - + " UPnP/" + getMajorVersion() + "." + getMinorVersion() + " " - + getProductName() + "/" + getProductVersion(); - } - - public String getHttpToken() { - StringBuilder sb = new StringBuilder(256); - sb.append(osName.indexOf(' ') != -1 ? osName.replace(' ', '_') : osName); - sb.append('/'); - sb.append(osVersion.indexOf(' ') != -1 ? osVersion.replace(' ', '_') : osVersion); - sb.append(" UPnP/"); - sb.append(majorVersion); - sb.append('.'); - sb.append(minorVersion); - sb.append(' '); - sb.append(productName.indexOf(' ') != -1 ? productName.replace(' ', '_') : productName); - sb.append('/'); - sb.append(productVersion.indexOf(' ') != -1 ? productVersion.replace(' ', '_') : productVersion); - - return sb.toString(); - } - - public String getOsToken() { - return getOsName().replaceAll(" ", "_")+"/"+getOsVersion().replaceAll(" ", "_"); - } - - public String getProductToken() { - return getProductName().replaceAll(" ", "_") + "/" + getProductVersion().replaceAll(" ", "_"); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ServerClientTokens that = (ServerClientTokens) o; - - if (majorVersion != that.majorVersion) return false; - if (minorVersion != that.minorVersion) return false; - if (!osName.equals(that.osName)) return false; - if (!osVersion.equals(that.osVersion)) return false; - if (!productName.equals(that.productName)) return false; - if (!productVersion.equals(that.productVersion)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = majorVersion; - result = 31 * result + minorVersion; - result = 31 * result + osName.hashCode(); - result = 31 * result + osVersion.hashCode(); - result = 31 * result + productName.hashCode(); - result = 31 * result + productVersion.hashCode(); - return result; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/ServiceManager.java b/clinglibrary/src/main/java/org/fourthline/cling/model/ServiceManager.java deleted file mode 100644 index c0941fc..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/ServiceManager.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.state.StateVariableValue; - -import java.beans.PropertyChangeSupport; -import java.util.Collection; - -/** - * Binds the metadata of a service to a service implementation, unified interface for accessing local services. - *

- * The UPnP core will always access a local service implementation through - * this manager, available with {@link org.fourthline.cling.model.meta.LocalService#getManager()}: - *

- *
    - *
  • - * The {@link org.fourthline.cling.model.action.ActionExecutor}s use the manager to process - * UPnP control invocations. It's the service manager's job to translate - * such an action invocation into an actual method invocation, or any other procedure - * that satisfies the requirements. The {@link org.fourthline.cling.model.action.ActionExecutor} - * works together with the manager, for example, the - * {@link org.fourthline.cling.model.action.MethodActionExecutor} expects that an action - * method can be invoked through reflection on the instance returned by the manager's - * {@link #getImplementation()} method. This is possible with the - * the {@link org.fourthline.cling.model.DefaultServiceManager}. A different service manager - * might require a different set of action executors, and vice versa. - *
  • - *
  • - * The {@link org.fourthline.cling.model.state.StateVariableAccessor}s use the manager - * to process UPnP state variable queries and GENA eventing. It's the service manager's - * job to return an actual value when a state variable has to be read. The - * {@link org.fourthline.cling.model.state.StateVariableAccessor} works together with - * the service manager, for example, the {@link org.fourthline.cling.model.state.FieldStateVariableAccessor} - * expects that a state variable value can be read through reflection on a field, of - * the instance returned by {@link #getImplementation()}. This is possible with the - * {@link org.fourthline.cling.model.DefaultServiceManager}. A different service manager - * might require a different set of state variable accessors, and vice versa. - *
  • - *
  • - * A service manager has to notify the UPnP core, and especially the GENA eventing system, - * whenever the state of any evented UPnP state variable changes. For new subscriptions - * GENA also has to read the current state of the service manually, when the subscription - * has been established and an initial event message has to be send to the subscriber. - *
  • - *
- *

- * A service manager can implement these concerns in any way imaginable. It has to - * be thread-safe. - *

- * - * @param The interface expected by the - * bound {@link org.fourthline.cling.model.action.ActionExecutor}s - * and {@link org.fourthline.cling.model.state.StateVariableAccessor}s. - * - * @author Christian Bauer - */ -public interface ServiceManager { - - /** - * Use this property name when propagating change events that affect any evented UPnP - * state variable. This name is detected by the GENA subsystem. - */ - public static final String EVENTED_STATE_VARIABLES = "_EventedStateVariables"; - - /** - * @return The metadata of the service to which this manager is assigned. - */ - public LocalService getService(); - - /** - * @return An instance with the interface expected by the - * bound {@link org.fourthline.cling.model.action.ActionExecutor}s - * and {@link org.fourthline.cling.model.state.StateVariableAccessor}s. - */ - public T getImplementation(); - - /** - * Double-dispatch of arbitrary commands, used by action executors and state variable accessors. - *

- * The service manager will execute the given {@link org.fourthline.cling.model.Command} and it - * might decorate the execution, for example, by locking/unlocking access to a shared service - * implementation before and after the execution. - *

- * @param cmd The command to execute. - * @throws Exception Any exception, without wrapping, as thrown by {@link org.fourthline.cling.model.Command#execute(ServiceManager)} - */ - public void execute(Command cmd) throws Exception; - - /** - * Provides the capability to monitor the service for state changes. - *

- * The GENA subsystem expects that this adapter will notify its listeners whenever - * any evented UPnP state variable of the service has changed its state. The - * following change event is expected: - *

- *
    - *
  • The property name is the constant {@link #EVENTED_STATE_VARIABLES}.
  • - *
  • The "old value" can be null, only the current state has to be included.
  • - *
  • The "new value" is a Collection of {@link org.fourthline.cling.model.state.StateVariableValue}, - * representing the current state of the service after the change.
  • - *
- *

- * The collection has to include values for all state variables, no - * matter what state variable was updated. Any other event is ignored (e.g. individual property - * changes). - *

- * - * @return An adapter that will notify its listeners whenever any evented state variable changes. - */ - public PropertyChangeSupport getPropertyChangeSupport(); - - /** - * Reading the state of a service manually. - * - * @return A Collection of {@link org.fourthline.cling.model.state.StateVariableValue}, representing - * the current state of the service, that is, all evented state variable values. - * @throws Exception Any error that occurred when the service's state was accessed. - */ - public Collection getCurrentState() throws Exception; - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/ServiceReference.java b/clinglibrary/src/main/java/org/fourthline/cling/model/ServiceReference.java deleted file mode 100644 index b4a7a87..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/ServiceReference.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.UDN; - -/** - * Combines a {@link org.fourthline.cling.model.types.UDN} and a {@link org.fourthline.cling.model.types.ServiceId}. - *

- * A service reference is useful to remember a service. For example, if a control point has accessed - * a service once, it can remember the service with {@link org.fourthline.cling.model.meta.Service#getReference()}. - * Before every action invocation, it can now resolve the reference to an actually registered service with - * {@link org.fourthline.cling.registry.Registry#getService(ServiceReference)}. If the registry doesn't return - * a service for the given reference, the service is currently not available. - *

- *

- * This simplifies implementing disconnect/reconnect behavior in a control point. - *

- * - * @author Christian Bauer - */ -public class ServiceReference { - - public static final String DELIMITER = "/"; - - final private UDN udn; - final private ServiceId serviceId; - - public ServiceReference(String s) { - String[] split = s.split("/"); - if (split.length == 2) { - this.udn = UDN.valueOf(split[0]); - this.serviceId = ServiceId.valueOf(split[1]); - } else { - this.udn = null; - this.serviceId = null; - } - } - - public ServiceReference(UDN udn, ServiceId serviceId) { - this.udn = udn; - this.serviceId = serviceId; - } - - public UDN getUdn() { - return udn; - } - - public ServiceId getServiceId() { - return serviceId; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ServiceReference that = (ServiceReference) o; - - if (!serviceId.equals(that.serviceId)) return false; - if (!udn.equals(that.udn)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = udn.hashCode(); - result = 31 * result + serviceId.hashCode(); - return result; - } - - @Override - public String toString() { - return udn == null || serviceId == null ? "" : udn.toString() + DELIMITER + serviceId.toString(); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/UnsupportedDataException.java b/clinglibrary/src/main/java/org/fourthline/cling/model/UnsupportedDataException.java deleted file mode 100644 index 2dfe0cc..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/UnsupportedDataException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -/** - * Thrown by processors/converters when errors occurred. - *

- * This exception indicates that received data was in an invalid format and/or could - * not be parsed or converted. You typically can recover from this failure after - * catching (and logging?) the exception. - *

- * - * @author Christian Bauer - */ -public class UnsupportedDataException extends RuntimeException { - - private static final long serialVersionUID = 661795454401413339L; - - protected Object data; - - public UnsupportedDataException(String s) { - super(s); - } - - public UnsupportedDataException(String s, Throwable throwable) { - super(s, throwable); - } - - public UnsupportedDataException(String s, Throwable throwable, Object data) { - super(s, throwable); - this.data = data; - } - - public Object getData() { - return data; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/UserConstants.java b/clinglibrary/src/main/java/org/fourthline/cling/model/UserConstants.java deleted file mode 100644 index 1120238..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/UserConstants.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -/** - * Settings you can modify if you know what you are doing. - * - * @author Michael Pujos - */ -public class UserConstants { - - public static final String PRODUCT_TOKEN_NAME = "Cling"; - - public static final String PRODUCT_TOKEN_VERSION = "2.0"; - - public static final int DEFAULT_SUBSCRIPTION_DURATION_SECONDS = 1800; - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/Validatable.java b/clinglibrary/src/main/java/org/fourthline/cling/model/Validatable.java deleted file mode 100644 index 768ef4f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/Validatable.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import java.util.List; - -/** - * Marker for types with integrity rules that require validation. - * - * @author Christian Bauer - */ -public interface Validatable { - - /** - * @return An empty List if all rules validated properly, otherwise, the detected errors. - */ - public List validate(); -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/ValidationError.java b/clinglibrary/src/main/java/org/fourthline/cling/model/ValidationError.java deleted file mode 100644 index a987040..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/ValidationError.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -/** - * Representing an integrity rule validation failure. - * - * @author Christian Bauer - */ -public class ValidationError { - private Class clazz; - private String propertyName; - private String message; - - public ValidationError(Class clazz, String message) { - this.clazz = clazz; - this.message = message; - } - - public ValidationError(Class clazz, String propertyName, String message) { - this.clazz = clazz; - this.propertyName = propertyName; - this.message = message; - } - - public Class getClazz() { - return clazz; - } - - public String getPropertyName() { - return propertyName; - } - - public String getMessage() { - return message; - } - - @Override - public String toString() { - return getClass().getSimpleName() - + " (Class: " + getClazz().getSimpleName() - + ", propertyName: " + getPropertyName() + "): " - + message; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/ValidationException.java b/clinglibrary/src/main/java/org/fourthline/cling/model/ValidationException.java deleted file mode 100644 index 8636820..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/ValidationException.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - - -import java.util.List; - -/** - * Thrown if integrity rule violations are exceptional, encapsulating the errors. - * - * @author Christian Bauer - */ -public class ValidationException extends Exception { - - public List errors; - - public ValidationException(String s) { - super(s); - } - - public ValidationException(String s, Throwable throwable) { - super(s, throwable); - } - - public ValidationException(String s, List errors) { - super(s); - this.errors = errors; - } - - public List getErrors() { - return errors; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/VariableValue.java b/clinglibrary/src/main/java/org/fourthline/cling/model/VariableValue.java deleted file mode 100644 index 540a2e4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/VariableValue.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import java.util.logging.Logger; - -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * Encapsulates a variable or argument value, validates and transforms it from/to a string representaion. - * - * @author Christian Bauer - */ -public class VariableValue { - - final private static Logger log = Logger.getLogger(VariableValue.class.getName()); - - final private Datatype datatype; - final private Object value; - - /** - * Creates and validates a variable value. - *

- * If the given value is a String, it will be converted - * with {@link org.fourthline.cling.model.types.Datatype#valueOf(String)}. Any - * other value will be checked, whether it matches the datatype and if its - * string representation is valid in XML documents (unicode character test). - *

- *

- * Note that for performance reasons, validation of a non-string value - * argument is skipped if executed on an Android runtime! - *

- * - * @param datatype The type of the variable. - * @param value The value of the variable. - * @throws InvalidValueException If the value is invalid for the given datatype, or if - * its string representation is invalid in XML. - */ - public VariableValue(Datatype datatype, Object value) throws InvalidValueException { - this.datatype = datatype; - this.value = value instanceof String ? datatype.valueOf((String) value) : value; - - if (ModelUtil.ANDROID_RUNTIME) return; // Skipping validation on Android - - // We can skip this validation because we can catch invalid values - // of any remote service (action invocation, event value) before, they are - // strings. The datatype's valueOf() will take care of that. The validations - // are really only used when a developer prepares input arguments for an action - // invocation or when a local service returns a wrong value. - - // In the first case the developer will get an exception when executing the - // action, if his action input argument value was of the wrong type. Or, - // an XML processing error will occur as soon as the SOAP message is handled, - // if the value contained invalid characters. - - // The second case indicates a bug in the local service, either metadata (state - // variable type) or implementation (action method return value). This will - // most likely be caught by the metadata/annotation binder when the service is - // created. - - if (!getDatatype().isValid(getValue())) - throw new InvalidValueException("Invalid value for " + getDatatype() +": " + getValue()); - - logInvalidXML(toString()); - } - - public Datatype getDatatype() { - return datatype; - } - - public Object getValue() { - return value; - } - - protected void logInvalidXML(String s) { - // Just display warnings. PS3 Media server sends null char in DIDL-Lite - // http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char - int cp; - int i = 0; - while (i < s.length()) { - cp = s.codePointAt(i); - if (!(cp == 0x9 || cp == 0xA || cp == 0xD || - (cp >= 0x20 && cp <= 0xD7FF) || - (cp >= 0xE000 && cp <= 0xFFFD) || - (cp >= 0x10000 && cp <= 0x10FFFF))) { - log.warning("Found invalid XML char code: " + cp); - } - i += Character.charCount(cp); - } - } - - @Override - public String toString() { - return getDatatype().getString(getValue()); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/XMLUtil.java b/clinglibrary/src/main/java/org/fourthline/cling/model/XMLUtil.java deleted file mode 100644 index 7abe7ec..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/XMLUtil.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model; - -import org.w3c.dom.*; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * XML handling and printing shortcuts. - *

- * This class exists because Android 2.1 does not offer any way to print an org.w3c.dom.Document, - * and it also doesn't implement the most trivial methods to build a DOM (although the API is provided, they - * fail at runtime). We might be able to remove this class once compatibility for Android 2.1 can be - * dropped. - *

- * - * @author Christian Bauer - */ -public class XMLUtil { - - /* TODO: How it should be done (nice API, eh?) - public static String documentToString(Document document) throws Exception { - TransformerFactory transFactory = TransformerFactory.newInstance(); - transFactory.setAttribute("indent-number", 4); - Transformer transformer = transFactory.newTransformer(); - transformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); - StringWriter out = new StringWriter(); - transformer.transform(new DOMSource(d), new StreamResult(out)); - return out.toString(); - } - */ - - // TODO: Evil methods to print XML on Android 2.1 (there is no TransformerFactory) - - public static String documentToString(Document document) throws Exception { - return documentToString(document, true); - } - - public static String documentToString(Document document, boolean standalone) throws Exception { - String prol = ""; - return prol + nodeToString(document.getDocumentElement(), new HashSet(), document.getDocumentElement().getNamespaceURI()); - } - - public static String documentToFragmentString(Document document) throws Exception { - return nodeToString(document.getDocumentElement(), new HashSet(), document.getDocumentElement().getNamespaceURI()); - } - - protected static String nodeToString(Node node, Set parentPrefixes, String namespaceURI) throws Exception { - StringBuilder b = new StringBuilder(); - - if (node == null) { - return ""; - } - - if (node instanceof Element) { - Element element = (Element) node; - b.append("<"); - b.append(element.getNodeName()); - - Map thisLevelPrefixes = new HashMap<>(); - if (element.getPrefix() != null && !parentPrefixes.contains(element.getPrefix())) { - thisLevelPrefixes.put(element.getPrefix(), element.getNamespaceURI()); - } - - if (element.hasAttributes()) { - NamedNodeMap map = element.getAttributes(); - for (int i = 0; i < map.getLength(); i++) { - Node attr = map.item(i); - if (attr.getNodeName().startsWith("xmlns")) continue; - if (attr.getPrefix() != null && !parentPrefixes.contains(attr.getPrefix())) { - thisLevelPrefixes.put(attr.getPrefix(), element.getNamespaceURI()); - } - b.append(" "); - b.append(attr.getNodeName()); - b.append("=\""); - b.append(attr.getNodeValue()); - b.append("\""); - } - } - - if (namespaceURI != null && !thisLevelPrefixes.containsValue(namespaceURI) && - !namespaceURI.equals(element.getParentNode().getNamespaceURI())) { - b.append(" xmlns=\"").append(namespaceURI).append("\""); - } - - for (Map.Entry entry : thisLevelPrefixes.entrySet()) { - b.append(" xmlns:").append(entry.getKey()).append("=\"").append(entry.getValue()).append("\""); - parentPrefixes.add(entry.getKey()); - } - - NodeList children = element.getChildNodes(); - boolean hasOnlyAttributes = true; - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - if (child.getNodeType() != Node.ATTRIBUTE_NODE) { - hasOnlyAttributes = false; - break; - } - } - if (!hasOnlyAttributes) { - b.append(">"); - for (int i = 0; i < children.getLength(); i++) { - b.append(nodeToString(children.item(i), parentPrefixes, children.item(i).getNamespaceURI())); - } - b.append(""); - } else { - b.append("/>"); - } - - for (String thisLevelPrefix : thisLevelPrefixes.keySet()) { - parentPrefixes.remove(thisLevelPrefix); - } - - } else if (node.getNodeValue() != null) { - b.append(encodeText(node.getNodeValue(), node instanceof Attr)); - } - - return b.toString(); - } - - public static String encodeText(String s) { - return encodeText(s, true); - } - - public static String encodeText(String s, boolean encodeQuotes) { - s = s.replaceAll("&", "&"); - s = s.replaceAll("<", "<"); - s = s.replaceAll(">", ">"); - if(encodeQuotes) { - s = s.replaceAll("'", "'"); - s = s.replaceAll("\"", """); - } - return s; - } - - public static Element appendNewElement(Document document, Element parent, Enum el) { - return appendNewElement(document, parent, el.toString()); - } - - public static Element appendNewElement(Document document, Element parent, String element) { - Element child = document.createElement(element); - parent.appendChild(child); - return child; - } - - public static Element appendNewElementIfNotNull(Document document, Element parent, Enum el, Object content) { - return appendNewElementIfNotNull(document, parent, el, content, null); - } - - public static Element appendNewElementIfNotNull(Document document, Element parent, Enum el, Object content, String namespace) { - return appendNewElementIfNotNull(document, parent, el.toString(), content, namespace); - } - - public static Element appendNewElementIfNotNull(Document document, Element parent, String element, Object content) { - return appendNewElementIfNotNull(document, parent, element, content, null); - } - - public static Element appendNewElementIfNotNull(Document document, Element parent, String element, Object content, String namespace) { - if (content == null) return parent; - return appendNewElement(document, parent, element, content, namespace); - } - - public static Element appendNewElement(Document document, Element parent, String element, Object content) { - return appendNewElement(document, parent, element, content, null); - } - - public static Element appendNewElement(Document document, Element parent, String element, Object content, String namespace) { - Element childElement; - if (namespace != null) { - childElement = document.createElementNS(namespace, element); - } else { - childElement = document.createElement(element); - } - - if (content != null) { - // TODO: We'll have that on Android 2.2: - // childElement.setTextContent(content.toString()); - // Meanwhile: - childElement.appendChild(document.createTextNode(content.toString())); - } - - parent.appendChild(childElement); - return childElement; - } - - // TODO: Of course, there is no Element.getTextContent() either... - public static String getTextContent(Node node) { - StringBuffer buffer = new StringBuffer(); - NodeList childList = node.getChildNodes(); - for (int i = 0; i < childList.getLength(); i++) { - Node child = childList.item(i); - if (child.getNodeType() != Node.TEXT_NODE) - continue; // skip non-text nodes - buffer.append(child.getNodeValue()); - } - return buffer.toString(); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/action/AbstractActionExecutor.java b/clinglibrary/src/main/java/org/fourthline/cling/model/action/AbstractActionExecutor.java deleted file mode 100644 index 13af56f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/action/AbstractActionExecutor.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.action; - -import org.fourthline.cling.model.Command; -import org.fourthline.cling.model.ServiceManager; -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.meta.ActionArgument; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.state.StateVariableAccessor; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.InvalidValueException; -import org.seamless.util.Exceptions; - -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Shared procedures for action executors based on an actual service implementation instance. - * - * @author Christian Bauer - */ -public abstract class AbstractActionExecutor implements ActionExecutor { - - private static Logger log = Logger.getLogger(AbstractActionExecutor.class.getName()); - - protected Map, StateVariableAccessor> outputArgumentAccessors = - new HashMap<>(); - - protected AbstractActionExecutor() { - } - - protected AbstractActionExecutor(Map, StateVariableAccessor> outputArgumentAccessors) { - this.outputArgumentAccessors = outputArgumentAccessors; - } - - public Map, StateVariableAccessor> getOutputArgumentAccessors() { - return outputArgumentAccessors; - } - - /** - * Obtains the service implementation instance from the {@link org.fourthline.cling.model.ServiceManager}, handles exceptions. - */ - public void execute(final ActionInvocation actionInvocation) { - - log.fine("Invoking on local service: " + actionInvocation); - - final LocalService service = actionInvocation.getAction().getService(); - - try { - - if (service.getManager() == null) { - throw new IllegalStateException("Service has no implementation factory, can't get service instance"); - } - - service.getManager().execute(new Command() { - public void execute(ServiceManager serviceManager) throws Exception { - AbstractActionExecutor.this.execute( - actionInvocation, - serviceManager.getImplementation() - ); - } - - @Override - public String toString() { - return "Action invocation: " + actionInvocation.getAction(); - } - }); - - } catch (ActionException ex) { - if (log.isLoggable(Level.FINE)) { - log.fine("ActionException thrown by service, wrapping in invocation and returning: " + ex); - log.log(Level.FINE, "Exception root cause: ", Exceptions.unwrap(ex)); - } - actionInvocation.setFailure(ex); - } catch (InterruptedException ex) { - if (log.isLoggable(Level.FINE)) { - log.fine("InterruptedException thrown by service, wrapping in invocation and returning: " + ex); - log.log(Level.FINE, "Exception root cause: ", Exceptions.unwrap(ex)); - } - actionInvocation.setFailure(new ActionCancelledException(ex)); - } catch (Throwable t) { - Throwable rootCause = Exceptions.unwrap(t); - if (log.isLoggable(Level.FINE)) { - log.fine("Execution has thrown, wrapping root cause in ActionException and returning: " + t); - log.log(Level.FINE, "Exception root cause: ", rootCause); - } - actionInvocation.setFailure( - new ActionException( - ErrorCode.ACTION_FAILED, - (rootCause.getMessage() != null ? rootCause.getMessage() : rootCause.toString()), - rootCause - ) - ); - } - } - - protected abstract void execute(ActionInvocation actionInvocation, Object serviceImpl) throws Exception; - - /** - * Reads the output arguments after an action execution using accessors. - * - * @param action The action of which the output arguments are read. - * @param instance The instance on which the accessors will be invoked. - * @return null if the action has no output arguments, a single instance if it has one, an - * Object[] otherwise. - * @throws Exception - */ - protected Object readOutputArgumentValues(Action action, Object instance) throws Exception { - Object[] results = new Object[action.getOutputArguments().length]; - log.fine("Attempting to retrieve output argument values using accessor: " + results.length); - - int i = 0; - for (ActionArgument outputArgument : action.getOutputArguments()) { - log.finer("Calling acccessor method for: " + outputArgument); - - StateVariableAccessor accessor = getOutputArgumentAccessors().get(outputArgument); - if (accessor != null) { - log.fine("Calling accessor to read output argument value: " + accessor); - results[i++] = accessor.read(instance); - } else { - throw new IllegalStateException("No accessor bound for: " + outputArgument); - } - } - - if (results.length == 1) { - return results[0]; - } - return results.length > 0 ? results : null; - } - - /** - * Sets the output argument value on the {@link org.fourthline.cling.model.action.ActionInvocation}, considers string conversion. - */ - protected void setOutputArgumentValue(ActionInvocation actionInvocation, ActionArgument argument, Object result) - throws ActionException { - - LocalService service = actionInvocation.getAction().getService(); - - if (result != null) { - try { - if (service.isStringConvertibleType(result)) { - log.fine("Result of invocation matches convertible type, setting toString() single output argument value"); - actionInvocation.setOutput(new ActionArgumentValue(argument, result.toString())); - } else { - log.fine("Result of invocation is Object, setting single output argument value"); - actionInvocation.setOutput(new ActionArgumentValue(argument, result)); - } - } catch (InvalidValueException ex) { - throw new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, - "Wrong type or invalid value for '" + argument.getName() + "': " + ex.getMessage(), - ex - ); - } - } else { - - log.fine("Result of invocation is null, not setting any output argument value(s)"); - } - - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionArgumentValue.java b/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionArgumentValue.java deleted file mode 100644 index 41d4122..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionArgumentValue.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.action; - -import org.fourthline.cling.model.VariableValue; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.meta.ActionArgument; -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * Represents the value of an action input or output argument. - * - * @author Christian Bauer - */ -public class ActionArgumentValue extends VariableValue { - - final private ActionArgument argument; - - public ActionArgumentValue(ActionArgument argument, Object value) throws InvalidValueException { - super(argument.getDatatype(), value != null && value.getClass().isEnum() ? value.toString() : value); - this.argument = argument; - } - - public ActionArgument getArgument() { - return argument; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionCancelledException.java b/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionCancelledException.java deleted file mode 100644 index a9774f0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionCancelledException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.model.action; - -import org.fourthline.cling.model.types.ErrorCode; - -/** - * @author Christian Bauer - */ -public class ActionCancelledException extends ActionException { - - public ActionCancelledException(InterruptedException cause) { - super(ErrorCode.ACTION_FAILED, "Action execution interrupted", cause); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionException.java b/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionException.java deleted file mode 100644 index e03e9d3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionException.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.action; - -import org.fourthline.cling.model.types.ErrorCode; - -/** - * Thrown (or encapsulated in {@link org.fourthline.cling.model.action.ActionInvocation} when an action execution failed. - * - * @author Christian Bauer - */ -public class ActionException extends Exception { - - private int errorCode; - - public ActionException(int errorCode, String message) { - super(message); - this.errorCode = errorCode; - } - - public ActionException(int errorCode, String message, Throwable cause) { - super(message, cause); - this.errorCode = errorCode; - } - - public ActionException(ErrorCode errorCode) { - this(errorCode.getCode(), errorCode.getDescription()); - } - - public ActionException(ErrorCode errorCode, String message) { - this(errorCode, message, true); - } - - public ActionException(ErrorCode errorCode, String message, boolean concatMessages) { - this(errorCode.getCode(), concatMessages ? (errorCode.getDescription() + ". " + message + ".") : message); - } - - public ActionException(ErrorCode errorCode, String message, Throwable cause) { - this(errorCode.getCode(), errorCode.getDescription() + ". " + message + ".", cause); - } - - public int getErrorCode() { - return errorCode; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionExecutor.java b/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionExecutor.java deleted file mode 100644 index 3c89861..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionExecutor.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.action; - -import org.fourthline.cling.model.meta.LocalService; - -/** - * Executes an {@link org.fourthline.cling.model.action.ActionInvocation}. - * - * @author Christian Bauer - */ -public interface ActionExecutor { - - public void execute(final ActionInvocation actionInvocation); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionInvocation.java b/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionInvocation.java deleted file mode 100644 index 7be4908..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/action/ActionInvocation.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.action; - -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.meta.ActionArgument; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.profile.ClientInfo; -import org.fourthline.cling.model.types.InvalidValueException; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * The input, output, and failure values of an action invocation. - * - * @author Christian Bauer - */ -public class ActionInvocation { - - final protected Action action; - final protected ClientInfo clientInfo; - - // We don't necessarily have to preserve insertion order but it's nicer if the arrays returned - // by the getters are reliable - protected Map> input = new LinkedHashMap<>(); - protected Map> output = new LinkedHashMap<>(); - - protected ActionException failure = null; - - public ActionInvocation(Action action) { - this(action, null, null, null); - } - - public ActionInvocation(Action action, - ClientInfo clientInfo) { - this(action, null, null, clientInfo); - } - - public ActionInvocation(Action action, - ActionArgumentValue[] input) { - this(action, input, null, null); - } - - public ActionInvocation(Action action, - ActionArgumentValue[] input, - ClientInfo clientInfo) { - this(action, input, null, clientInfo); - } - - public ActionInvocation(Action action, - ActionArgumentValue[] input, - ActionArgumentValue[] output) { - this(action, input, output, null); - } - - public ActionInvocation(Action action, - ActionArgumentValue[] input, - ActionArgumentValue[] output, - ClientInfo clientInfo) { - if (action == null) { - throw new IllegalArgumentException("Action can not be null"); - } - this.action = action; - - setInput(input); - setOutput(output); - - this.clientInfo = clientInfo; - } - - public ActionInvocation(ActionException failure) { - this.action = null; - this.input = null; - this.output = null; - this.failure = failure; - this.clientInfo = null; - } - - public Action getAction() { - return action; - } - - public ActionArgumentValue[] getInput() { - return input.values().toArray(new ActionArgumentValue[input.size()]); - } - - public ActionArgumentValue getInput(String argumentName) { - return getInput(getInputArgument(argumentName)); - } - - public ActionArgumentValue getInput(ActionArgument argument) { - return input.get(argument.getName()); - } - - public Map> getInputMap() { - return Collections.unmodifiableMap(input); - } - - public ActionArgumentValue[] getOutput() { - return output.values().toArray(new ActionArgumentValue[output.size()]); - } - - public ActionArgumentValue getOutput(String argumentName) { - return getOutput(getOutputArgument(argumentName)); - } - - public Map> getOutputMap() { - return Collections.unmodifiableMap(output); - } - - public ActionArgumentValue getOutput(ActionArgument argument) { - return output.get(argument.getName()); - } - - public void setInput(String argumentName, Object value) throws InvalidValueException { - setInput(new ActionArgumentValue(getInputArgument(argumentName), value)); - } - - public void setInput(ActionArgumentValue value) { - input.put(value.getArgument().getName(), value); - } - - public void setInput(ActionArgumentValue[] input) { - if (input == null) return; - for (ActionArgumentValue argumentValue : input) { - this.input.put(argumentValue.getArgument().getName(), argumentValue); - } - } - - public void setOutput(String argumentName, Object value) throws InvalidValueException { - setOutput(new ActionArgumentValue(getOutputArgument(argumentName), value)); - } - - public void setOutput(ActionArgumentValue value){ - output.put(value.getArgument().getName(), value); - } - - public void setOutput(ActionArgumentValue[] output) { - if (output == null) return; - for (ActionArgumentValue argumentValue : output) { - this.output.put(argumentValue.getArgument().getName(), argumentValue); - } - } - - protected ActionArgument getInputArgument(String name) { - ActionArgument argument = getAction().getInputArgument(name); - if (argument == null) throw new IllegalArgumentException("Argument not found: " + name); - return argument; - } - - protected ActionArgument getOutputArgument(String name) { - ActionArgument argument = getAction().getOutputArgument(name); - if (argument == null) throw new IllegalArgumentException("Argument not found: " + name); - return argument; - } - - /** - * @return null if execution was successful, failure details otherwise. - */ - public ActionException getFailure() { - return failure; - } - - public void setFailure(ActionException failure) { - this.failure = failure; - } - - /** - * @return null if no info was provided for a local invocation. - */ - public ClientInfo getClientInfo() { - return clientInfo; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") " + getAction(); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/action/MethodActionExecutor.java b/clinglibrary/src/main/java/org/fourthline/cling/model/action/MethodActionExecutor.java deleted file mode 100644 index 7fadfe1..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/action/MethodActionExecutor.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.action; - -import org.fourthline.cling.model.meta.ActionArgument; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.profile.RemoteClientInfo; -import org.fourthline.cling.model.state.StateVariableAccessor; -import org.fourthline.cling.model.types.ErrorCode; -import org.seamless.util.Reflections; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -/** - * Invokes methods on a service implementation instance with reflection. - * - *

- * If the method has an additional last parameter of type - * {@link org.fourthline.cling.model.profile.RemoteClientInfo}, the details - * of the control point client will be provided to the action method. You can use this - * to get the client's address and request headers, and to provide extra response headers. - *

- * - * @author Christian Bauer - */ -public class MethodActionExecutor extends AbstractActionExecutor { - - private static Logger log = Logger.getLogger(MethodActionExecutor.class.getName()); - - protected Method method; - - public MethodActionExecutor(Method method) { - this.method = method; - } - - public MethodActionExecutor(Map, StateVariableAccessor> outputArgumentAccessors, Method method) { - super(outputArgumentAccessors); - this.method = method; - } - - public Method getMethod() { - return method; - } - - @Override - protected void execute(ActionInvocation actionInvocation, Object serviceImpl) throws Exception { - - // Find the "real" parameters of the method we want to call, and create arguments - Object[] inputArgumentValues = createInputArgumentValues(actionInvocation, method); - - // Simple case: no output arguments - if (!actionInvocation.getAction().hasOutputArguments()) { - log.fine("Calling local service method with no output arguments: " + method); - Reflections.invoke(method, serviceImpl, inputArgumentValues); - return; - } - - boolean isVoid = method.getReturnType().equals(Void.TYPE); - - log.fine("Calling local service method with output arguments: " + method); - Object result; - boolean isArrayResultProcessed = true; - if (isVoid) { - - log.fine("Action method is void, calling declared accessors(s) on service instance to retrieve ouput argument(s)"); - Reflections.invoke(method, serviceImpl, inputArgumentValues); - result = readOutputArgumentValues(actionInvocation.getAction(), serviceImpl); - - } else if (isUseOutputArgumentAccessors(actionInvocation)) { - - log.fine("Action method is not void, calling declared accessor(s) on returned instance to retrieve ouput argument(s)"); - Object returnedInstance = Reflections.invoke(method, serviceImpl, inputArgumentValues); - result = readOutputArgumentValues(actionInvocation.getAction(), returnedInstance); - - } else { - - log.fine("Action method is not void, using returned value as (single) output argument"); - result = Reflections.invoke(method, serviceImpl, inputArgumentValues); - isArrayResultProcessed = false; // We never want to process e.g. byte[] as individual variable values - } - - ActionArgument[] outputArgs = actionInvocation.getAction().getOutputArguments(); - - if (isArrayResultProcessed && result instanceof Object[]) { - Object[] results = (Object[]) result; - log.fine("Accessors returned Object[], setting output argument values: " + results.length); - for (int i = 0; i < outputArgs.length; i++) { - setOutputArgumentValue(actionInvocation, outputArgs[i], results[i]); - } - } else if (outputArgs.length == 1) { - setOutputArgumentValue(actionInvocation, outputArgs[0], result); - } else { - throw new ActionException( - ErrorCode.ACTION_FAILED, - "Method return does not match required number of output arguments: " + outputArgs.length - ); - } - - } - - protected boolean isUseOutputArgumentAccessors(ActionInvocation actionInvocation) { - for (ActionArgument argument : actionInvocation.getAction().getOutputArguments()) { - // If there is one output argument for which we have an accessor, all arguments need accessors - if (getOutputArgumentAccessors().get(argument) != null) { - return true; - } - } - return false; - } - - protected Object[] createInputArgumentValues(ActionInvocation actionInvocation, Method method) throws ActionException { - - LocalService service = actionInvocation.getAction().getService(); - - List values = new ArrayList<>(); - int i = 0; - for (ActionArgument argument : actionInvocation.getAction().getInputArguments()) { - - Class methodParameterType = method.getParameterTypes()[i]; - - ActionArgumentValue inputValue = actionInvocation.getInput(argument); - - // If it's a primitive argument, we need a value - if (methodParameterType.isPrimitive() && (inputValue == null || inputValue.toString().length() == 0)) - throw new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, - "Primitive action method argument '" + argument.getName() + "' requires input value, can't be null or empty string" - ); - - // It's not primitive and we have no value, that's fine too - if (inputValue == null) { - values.add(i++, null); - continue; - } - - // If it's not null, maybe it was a string-convertible type, if so, try to instantiate it - String inputCallValueString = inputValue.toString(); - // Empty string means null and we can't instantiate Enums! - if (inputCallValueString.length() > 0 && service.isStringConvertibleType(methodParameterType) && !methodParameterType.isEnum()) { - try { - Constructor ctor = methodParameterType.getConstructor(String.class); - log.finer("Creating new input argument value instance with String.class constructor of type: " + methodParameterType); - Object o = ctor.newInstance(inputCallValueString); - values.add(i++, o); - } catch (Exception ex) { - log.warning("Error preparing action method call: " + method); - log.warning("Can't convert input argument string to desired type of '" + argument.getName() + "': " + ex); - throw new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, "Can't convert input argument string to desired type of '" + argument.getName() + "': " + ex - ); - } - } else { - // Or if it wasn't, just use the value without any conversion - values.add(i++, inputValue.getValue()); - } - } - - if (method.getParameterTypes().length > 0 - && RemoteClientInfo.class.isAssignableFrom(method.getParameterTypes()[method.getParameterTypes().length-1])) { - if (actionInvocation instanceof RemoteActionInvocation && - ((RemoteActionInvocation)actionInvocation).getRemoteClientInfo() != null) { - log.finer("Providing remote client info as last action method input argument: " + method); - values.add(i, ((RemoteActionInvocation)actionInvocation).getRemoteClientInfo()); - } else { - // Local call, no client info available - values.add(i, null); - } - } - - return values.toArray(new Object[values.size()]); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/action/QueryStateVariableExecutor.java b/clinglibrary/src/main/java/org/fourthline/cling/model/action/QueryStateVariableExecutor.java deleted file mode 100644 index 4ea6b74..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/action/QueryStateVariableExecutor.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.action; - -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.QueryStateVariableAction; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.state.StateVariableAccessor; -import org.fourthline.cling.model.types.ErrorCode; - -/** - * Special executor for one action, the deprecated "query the value of the any state variable" action. - * - * @author Christian Bauer - */ -public class QueryStateVariableExecutor extends AbstractActionExecutor { - - @Override - protected void execute(ActionInvocation actionInvocation, Object serviceImpl) throws Exception { - - // Querying a state variable doesn't mean an actual "action" method on this instance gets invoked - if (actionInvocation.getAction() instanceof QueryStateVariableAction) { - if (!actionInvocation.getAction().getService().isSupportsQueryStateVariables()) { - actionInvocation.setFailure( - new ActionException(ErrorCode.INVALID_ACTION, "This service does not support querying state variables") - ); - } else { - executeQueryStateVariable(actionInvocation, serviceImpl); - } - } else { - throw new IllegalStateException( - "This class can only execute QueryStateVariableAction's, not: " + actionInvocation.getAction() - ); - } - } - - protected void executeQueryStateVariable(ActionInvocation actionInvocation, Object serviceImpl) throws Exception { - - LocalService service = actionInvocation.getAction().getService(); - - String stateVariableName = actionInvocation.getInput("varName").toString(); - StateVariable stateVariable = service.getStateVariable(stateVariableName); - - if (stateVariable == null) { - throw new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, "No state variable found: " + stateVariableName - ); - } - - StateVariableAccessor accessor; - if ((accessor = service.getAccessor(stateVariable.getName())) == null) { - throw new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, "No accessor for state variable, can't read state: " + stateVariableName - ); - } - - try { - setOutputArgumentValue( - actionInvocation, - actionInvocation.getAction().getOutputArgument("return"), - accessor.read(stateVariable, serviceImpl).toString() - ); - } catch (Exception ex) { - throw new ActionException(ErrorCode.ACTION_FAILED, ex.getMessage()); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/action/RemoteActionInvocation.java b/clinglibrary/src/main/java/org/fourthline/cling/model/action/RemoteActionInvocation.java deleted file mode 100644 index 6a031c6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/action/RemoteActionInvocation.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.action; - -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.profile.RemoteClientInfo; - -/** - * An action invocation by a remote control point. - * - * @author Christian Bauer - */ -public class RemoteActionInvocation extends ActionInvocation { - - final protected RemoteClientInfo remoteClientInfo; - - public RemoteActionInvocation(Action action, - ActionArgumentValue[] input, - ActionArgumentValue[] output, - RemoteClientInfo remoteClientInfo) { - super(action, input, output, null); - this.remoteClientInfo = remoteClientInfo; - } - - public RemoteActionInvocation(Action action, - RemoteClientInfo remoteClientInfo) { - super(action); - this.remoteClientInfo = remoteClientInfo; - } - - public RemoteActionInvocation(ActionException failure, - RemoteClientInfo remoteClientInfo) { - super(failure); - this.remoteClientInfo = remoteClientInfo; - } - - public RemoteClientInfo getRemoteClientInfo() { - return remoteClientInfo; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/gena/CancelReason.java b/clinglibrary/src/main/java/org/fourthline/cling/model/gena/CancelReason.java deleted file mode 100644 index 34200ca..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/gena/CancelReason.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.gena; - -/** - * The reason why a {@link org.fourthline.cling.model.gena.GENASubscription} has ended unexpectedly. - * - * @author Christian Bauer - */ -public enum CancelReason { - - RENEWAL_FAILED, - DEVICE_WAS_REMOVED, - UNSUBSCRIBE_FAILED, - EXPIRED -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/gena/GENASubscription.java b/clinglibrary/src/main/java/org/fourthline/cling/model/gena/GENASubscription.java deleted file mode 100644 index ade3ea4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/gena/GENASubscription.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.gena; - -import java.util.LinkedHashMap; -import java.util.Map; - -import org.fourthline.cling.model.UserConstants; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.state.StateVariableValue; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -/** - * An established subscription, with identifer, expiration duration, sequence handling, and state variable values. - *

- * For every subscription, no matter if it's an incoming subscription to a local service, - * or a local control point subscribing to a remote servce, an instance is maintained by - * the {@link org.fourthline.cling.registry.Registry}. - *

- * - * @author Christian Bauer - */ -public abstract class GENASubscription { - - protected S service; - protected String subscriptionId; - protected int requestedDurationSeconds = UserConstants.DEFAULT_SUBSCRIPTION_DURATION_SECONDS; - protected int actualDurationSeconds; - protected UnsignedIntegerFourBytes currentSequence; - protected Map> currentValues = new LinkedHashMap<>(); - - /** - * Defaults to {@link org.fourthline.cling.model.UserConstants#DEFAULT_SUBSCRIPTION_DURATION_SECONDS}. - */ - protected GENASubscription(S service) { - this.service = service; - } - - public GENASubscription(S service, int requestedDurationSeconds) { - this(service); - this.requestedDurationSeconds = requestedDurationSeconds; - } - - synchronized public S getService() { - return service; - } - - synchronized public String getSubscriptionId() { - return subscriptionId; - } - - synchronized public void setSubscriptionId(String subscriptionId) { - this.subscriptionId = subscriptionId; - } - - synchronized public int getRequestedDurationSeconds() { - return requestedDurationSeconds; - } - - synchronized public int getActualDurationSeconds() { - return actualDurationSeconds; - } - - synchronized public void setActualSubscriptionDurationSeconds(int seconds) { - this.actualDurationSeconds = seconds; - } - - synchronized public UnsignedIntegerFourBytes getCurrentSequence() { - return currentSequence; - } - - synchronized public Map> getCurrentValues() { - return currentValues; - } - - public abstract void established(); - public abstract void eventReceived(); - - @Override - public String toString() { - return "(GENASubscription, SID: " + getSubscriptionId() + ", SEQUENCE: " + getCurrentSequence() + ")"; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/gena/LocalGENASubscription.java b/clinglibrary/src/main/java/org/fourthline/cling/model/gena/LocalGENASubscription.java deleted file mode 100644 index 4b8a811..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/gena/LocalGENASubscription.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.gena; - -import org.fourthline.cling.model.ServiceManager; -import org.fourthline.cling.model.UserConstants; -import org.fourthline.cling.model.message.header.SubscriptionIdHeader; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.state.StateVariableValue; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.seamless.util.Exceptions; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.net.URL; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * An incoming subscription to a local service. - *

- * Uses the {@link org.fourthline.cling.model.ServiceManager} to read the initial state of - * the {@link org.fourthline.cling.model.meta.LocalService} on instantation. Typically, the - * {@link #registerOnService()} method is called next, and from this point forward all - * {@link org.fourthline.cling.model.ServiceManager#EVENTED_STATE_VARIABLES} property change - * events are detected by this subscription. After moderation of state variable values - * (frequency and range of changes), the {@link #eventReceived()} method is called. - * Delivery of the event message to the subscriber is not part of this class, but the - * implementor of {@link #eventReceived()}. - *

- * - * @author Christian Bauer - */ -public abstract class LocalGENASubscription extends GENASubscription implements PropertyChangeListener { - - private static Logger log = Logger.getLogger(LocalGENASubscription.class.getName()); - - final List callbackURLs; - - // Moderation history - final Map lastSentTimestamp = new HashMap<>(); - final Map lastSentNumericValue = new HashMap<>(); - - protected LocalGENASubscription(LocalService service, List callbackURLs) throws Exception { - super(service); - this.callbackURLs = callbackURLs; - } - - public LocalGENASubscription(LocalService service, - Integer requestedDurationSeconds, List callbackURLs) throws Exception { - super(service); - - setSubscriptionDuration(requestedDurationSeconds); - - log.fine("Reading initial state of local service at subscription time"); - long currentTime = new Date().getTime(); - this.currentValues.clear(); - - Collection values = getService().getManager().getCurrentState(); - - log.finer("Got evented state variable values: " + values.size()); - - for (StateVariableValue value : values) { - this.currentValues.put(value.getStateVariable().getName(), value); - - if (log.isLoggable(Level.FINEST)) { - log.finer("Read state variable value '" + value.getStateVariable().getName() + "': " + value.toString()); - } - - // Preserve "last sent" state for future moderation - lastSentTimestamp.put(value.getStateVariable().getName(), currentTime); - if (value.getStateVariable().isModeratedNumericType()) { - lastSentNumericValue.put(value.getStateVariable().getName(), Long.valueOf(value.toString())); - } - } - - this.subscriptionId = SubscriptionIdHeader.PREFIX + UUID.randomUUID(); - this.currentSequence = new UnsignedIntegerFourBytes(0); - this.callbackURLs = callbackURLs; - } - - synchronized public List getCallbackURLs() { - return callbackURLs; - } - - /** - * Adds a property change listener on the {@link org.fourthline.cling.model.ServiceManager}. - */ - synchronized public void registerOnService() { - getService().getManager().getPropertyChangeSupport().addPropertyChangeListener(this); - } - - synchronized public void establish() { - established(); - } - - /** - * Removes a property change listener on the {@link org.fourthline.cling.model.ServiceManager}. - */ - synchronized public void end(CancelReason reason) { - try { - getService().getManager().getPropertyChangeSupport().removePropertyChangeListener(this); - } catch (Exception ex) { - log.warning("Removal of local service property change listener failed: " + Exceptions.unwrap(ex)); - } - ended(reason); - } - - /** - * Moderates {@link org.fourthline.cling.model.ServiceManager#EVENTED_STATE_VARIABLES} events and state variable - * values, calls {@link #eventReceived()}. - */ - synchronized public void propertyChange(PropertyChangeEvent e) { - if (!e.getPropertyName().equals(ServiceManager.EVENTED_STATE_VARIABLES)) return; - - log.fine("Eventing triggered, getting state for subscription: " + getSubscriptionId()); - - long currentTime = new Date().getTime(); - - Collection newValues = (Collection) e.getNewValue(); - Set excludedVariables = moderateStateVariables(currentTime, newValues); - - currentValues.clear(); - for (StateVariableValue newValue : newValues) { - String name = newValue.getStateVariable().getName(); - if (!excludedVariables.contains(name)) { - log.fine("Adding state variable value to current values of event: " + newValue.getStateVariable() + " = " + newValue); - currentValues.put(newValue.getStateVariable().getName(), newValue); - - // Preserve "last sent" state for future moderation - lastSentTimestamp.put(name, currentTime); - if (newValue.getStateVariable().isModeratedNumericType()) { - lastSentNumericValue.put(name, Long.valueOf(newValue.toString())); - } - } - } - - if (currentValues.size() > 0) { - log.fine("Propagating new state variable values to subscription: " + this); - // TODO: I'm not happy with this design, this dispatches to a separate thread which _then_ - // is supposed to lock and read the values off this instance. That obviously doesn't work - // so it's currently a hack in SendingEvent.java - eventReceived(); - } else { - log.fine("No state variable values for event (all moderated out?), not triggering event"); - } - } - - /** - * Checks whether a state variable is moderated, and if this change is within the maximum rate and range limits. - * - * @param currentTime The current unix time. - * @param values The state variable values to moderate. - * @return A collection of state variable values that although they might have changed, are excluded from the event. - */ - synchronized protected Set moderateStateVariables(long currentTime, Collection values) { - - Set excludedVariables = new HashSet<>(); - - // Moderate event variables that have a maximum rate or minimum delta - for (StateVariableValue stateVariableValue : values) { - - StateVariable stateVariable = stateVariableValue.getStateVariable(); - String stateVariableName = stateVariableValue.getStateVariable().getName(); - - if (stateVariable.getEventDetails().getEventMaximumRateMilliseconds() == 0 && - stateVariable.getEventDetails().getEventMinimumDelta() == 0) { - log.finer("Variable is not moderated: " + stateVariable); - continue; - } - - // That should actually never happen, because we always "send" it as the initial state/event - if (!lastSentTimestamp.containsKey(stateVariableName)) { - log.finer("Variable is moderated but was never sent before: " + stateVariable); - continue; - } - - if (stateVariable.getEventDetails().getEventMaximumRateMilliseconds() > 0) { - long timestampLastSent = lastSentTimestamp.get(stateVariableName); - long timestampNextSend = timestampLastSent + (stateVariable.getEventDetails().getEventMaximumRateMilliseconds()); - if (currentTime <= timestampNextSend) { - log.finer("Excluding state variable with maximum rate: " + stateVariable); - excludedVariables.add(stateVariableName); - continue; - } - } - - if (stateVariable.isModeratedNumericType() && lastSentNumericValue.get(stateVariableName) != null) { - - long oldValue = Long.valueOf(lastSentNumericValue.get(stateVariableName)); - long newValue = Long.valueOf(stateVariableValue.toString()); - long minDelta = stateVariable.getEventDetails().getEventMinimumDelta(); - - if (newValue > oldValue && newValue - oldValue < minDelta) { - log.finer("Excluding state variable with minimum delta: " + stateVariable); - excludedVariables.add(stateVariableName); - continue; - } - - if (newValue < oldValue && oldValue - newValue < minDelta) { - log.finer("Excluding state variable with minimum delta: " + stateVariable); - excludedVariables.add(stateVariableName); - } - } - - } - return excludedVariables; - } - - synchronized public void incrementSequence() { - this.currentSequence.increment(true); - } - - /** - * @param requestedDurationSeconds If null defaults to - * {@link org.fourthline.cling.model.UserConstants#DEFAULT_SUBSCRIPTION_DURATION_SECONDS} - */ - synchronized public void setSubscriptionDuration(Integer requestedDurationSeconds) { - this.requestedDurationSeconds = - requestedDurationSeconds == null - ? UserConstants.DEFAULT_SUBSCRIPTION_DURATION_SECONDS - : requestedDurationSeconds; - - setActualSubscriptionDurationSeconds(this.requestedDurationSeconds); - } - - public abstract void ended(CancelReason reason); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/gena/RemoteGENASubscription.java b/clinglibrary/src/main/java/org/fourthline/cling/model/gena/RemoteGENASubscription.java deleted file mode 100644 index 7a5520d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/gena/RemoteGENASubscription.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.gena; - -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.NetworkAddress; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.meta.RemoteService; -import org.fourthline.cling.model.state.StateVariableValue; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.model.UnsupportedDataException; - -import java.beans.PropertyChangeSupport; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * An outgoing subscription to a remote service. - *

- * Once established, calls its {@link #eventReceived()} method whenever an event has - * been received from the remote service. - *

- * - * @author Christian Bauer - */ -public abstract class RemoteGENASubscription extends GENASubscription { - - protected PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); - - protected RemoteGENASubscription(RemoteService service, - int requestedDurationSeconds) { - super(service, requestedDurationSeconds); - } - - synchronized public URL getEventSubscriptionURL() { - return getService().getDevice().normalizeURI( - getService().getEventSubscriptionURI() - ); - } - - synchronized public List getEventCallbackURLs(List activeStreamServers, Namespace namespace) { - List callbackURLs = new ArrayList<>(); - for (NetworkAddress activeStreamServer : activeStreamServers) { - callbackURLs.add( - new Location( - activeStreamServer, - namespace.getEventCallbackPathString(getService()) - ).getURL()); - } - return callbackURLs; - } - - /* The following four methods should always be called in an independent thread, not within the - message receiving thread. Otherwise the user who implements the abstract delegate methods can - block the network communication. - */ - - synchronized public void establish() { - established(); - } - - synchronized public void fail(UpnpResponse responseStatus) { - failed(responseStatus); - } - - synchronized public void end(CancelReason reason, UpnpResponse response) { - ended(reason, response); - } - - synchronized public void receive(UnsignedIntegerFourBytes sequence, Collection newValues) { - - if (this.currentSequence != null) { - - // TODO: Handle rollover to 1! - if (this.currentSequence.getValue().equals(this.currentSequence.getBits().getMaxValue()) && sequence.getValue() == 1) { - System.err.println("TODO: HANDLE ROLLOVER"); - return; - } - - if (this.currentSequence.getValue() >= sequence.getValue()) { - return; - } - - int difference; - long expectedValue = currentSequence.getValue() + 1; - if ((difference = (int) (sequence.getValue() - expectedValue)) != 0) { - eventsMissed(difference); - } - - } - - this.currentSequence = sequence; - - for (StateVariableValue newValue : newValues) { - currentValues.put(newValue.getStateVariable().getName(), newValue); - } - - eventReceived(); - } - - public abstract void invalidMessage(UnsupportedDataException ex); - - public abstract void failed(UpnpResponse responseStatus); - - public abstract void ended(CancelReason reason, UpnpResponse responseStatus); - - public abstract void eventsMissed(int numberOfMissedEvents); - - @Override - public String toString() { - return "(SID: " + getSubscriptionId() + ") " + getService(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/Connection.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/Connection.java deleted file mode 100644 index 7415edf..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/Connection.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message; - -import java.net.InetAddress; - -/** - * An API for the Cling protocol layer to access some transport layer details. - * - * @author Christian Bauer - */ -public interface Connection { - - boolean isOpen(); - - InetAddress getRemoteAddress(); - - InetAddress getLocalAddress(); - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/IncomingDatagramMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/IncomingDatagramMessage.java deleted file mode 100644 index 7d0ccf5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/IncomingDatagramMessage.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message; - -import java.net.InetAddress; - -/** - * A received UDP datagram request or response message, with source address and port. - *

- * Additionally, holds a local address that is reachable from the source - * address (in the same subnet): - *

- *
    - *
  • When an M-SEARCH is received, we send a LOCATION header back with a - * reachable (by the remote control point) local address.
  • - *
  • When a NOTIFY discovery message (can be a search response) is received we - need to memorize on which local address it was received, so that the we can - later give the remote device a reachable (from its point of view) local - GENA callback address.
  • - *
- * - * @author Christian Bauer - */ -public class IncomingDatagramMessage extends UpnpMessage { - - private InetAddress sourceAddress; - private int sourcePort; - private InetAddress localAddress; - - public IncomingDatagramMessage(O operation, InetAddress sourceAddress, int sourcePort, InetAddress localAddress) { - super(operation); - this.sourceAddress = sourceAddress; - this.sourcePort = sourcePort; - this.localAddress = localAddress; - } - - protected IncomingDatagramMessage(IncomingDatagramMessage source) { - super(source); - this.sourceAddress = source.getSourceAddress(); - this.sourcePort = source.getSourcePort(); - this.localAddress = source.getLocalAddress(); - } - - public InetAddress getSourceAddress() { - return sourceAddress; - } - - public int getSourcePort() { - return sourcePort; - } - - public InetAddress getLocalAddress() { - return localAddress; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/OutgoingDatagramMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/OutgoingDatagramMessage.java deleted file mode 100644 index ff5f154..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/OutgoingDatagramMessage.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message; - -import java.net.InetAddress; - -/** - * A UDP datagram request or response message for sending, with destination address and port. - * - * @author Christian Bauer - */ -public abstract class OutgoingDatagramMessage extends UpnpMessage { - - private InetAddress destinationAddress; - private int destinationPort; - // For performance reasons, headers of this message are not normalized - private UpnpHeaders headers = new UpnpHeaders(false); - - protected OutgoingDatagramMessage(O operation, InetAddress destinationAddress, int destinationPort) { - super(operation); - this.destinationAddress = destinationAddress; - this.destinationPort = destinationPort; - } - - protected OutgoingDatagramMessage(O operation, BodyType bodyType, Object body, InetAddress destinationAddress, int destinationPort) { - super(operation, bodyType, body); - this.destinationAddress = destinationAddress; - this.destinationPort = destinationPort; - } - - public InetAddress getDestinationAddress() { - return destinationAddress; - } - - public int getDestinationPort() { - return destinationPort; - } - - @Override - public UpnpHeaders getHeaders() { - return this.headers; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/StreamRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/StreamRequestMessage.java deleted file mode 100644 index 237462d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/StreamRequestMessage.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message; - -import java.net.URI; -import java.net.URL; - -/** - * A TCP (HTTP) stream request message. - * - * @author Christian Bauer - */ -public class StreamRequestMessage extends UpnpMessage { - - protected Connection connection; - - public StreamRequestMessage(StreamRequestMessage source) { - super(source); - this.connection = source.getConnection(); - } - - public StreamRequestMessage(UpnpRequest operation) { - super(operation); - } - - public StreamRequestMessage(UpnpRequest.Method method, URI uri) { - super(new UpnpRequest(method, uri)); - } - - public StreamRequestMessage(UpnpRequest.Method method, URL url) { - super(new UpnpRequest(method, url)); - } - - public StreamRequestMessage(UpnpRequest operation, String body) { - super(operation, BodyType.STRING, body); - } - - public StreamRequestMessage(UpnpRequest.Method method, URI uri, String body) { - super(new UpnpRequest(method, uri), BodyType.STRING, body); - } - - public StreamRequestMessage(UpnpRequest.Method method, URL url, String body) { - super(new UpnpRequest(method, url), BodyType.STRING, body); - } - - - public StreamRequestMessage(UpnpRequest operation, byte[] body) { - super(operation, BodyType.BYTES, body); - } - - public StreamRequestMessage(UpnpRequest.Method method, URI uri, byte[] body) { - super(new UpnpRequest(method, uri), BodyType.BYTES, body); - } - - public StreamRequestMessage(UpnpRequest.Method method, URL url, byte[] body) { - super(new UpnpRequest(method, url), BodyType.BYTES, body); - } - - public URI getUri() { - return getOperation().getURI(); - } - - public void setUri(URI uri) { - getOperation().setUri(uri); - } - - public void setConnection(Connection connection) { - this.connection = connection; - } - - public Connection getConnection() { - return connection; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/StreamResponseMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/StreamResponseMessage.java deleted file mode 100644 index 740b552..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/StreamResponseMessage.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message; - -import org.fourthline.cling.model.message.header.ContentTypeHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.seamless.util.MimeType; - -/** - * A TCP (HTTP) stream response message. - * - * @author Christian Bauer - */ -public class StreamResponseMessage extends UpnpMessage { - - public StreamResponseMessage(StreamResponseMessage source) { - super(source); - } - - public StreamResponseMessage(UpnpResponse.Status status) { - super(new UpnpResponse(status)); - } - - public StreamResponseMessage(UpnpResponse operation) { - super(operation); - } - - - public StreamResponseMessage(UpnpResponse operation, String body) { - super(operation, BodyType.STRING, body); - } - - public StreamResponseMessage(String body) { - super(new UpnpResponse(UpnpResponse.Status.OK),BodyType.STRING, body); - } - - - public StreamResponseMessage(UpnpResponse operation, byte[] body) { - super(operation, BodyType.BYTES, body); - } - - public StreamResponseMessage(byte[] body) { - super(new UpnpResponse(UpnpResponse.Status.OK),BodyType.BYTES, body); - } - - - public StreamResponseMessage(String body, ContentTypeHeader contentType) { - this(body); - getHeaders().add(UpnpHeader.Type.CONTENT_TYPE, contentType); - } - - public StreamResponseMessage(String body, MimeType mimeType) { - this(body, new ContentTypeHeader(mimeType)); - } - - public StreamResponseMessage(byte[] body, ContentTypeHeader contentType) { - this(body); - getHeaders().add(UpnpHeader.Type.CONTENT_TYPE, contentType); - } - - public StreamResponseMessage(byte[] body, MimeType mimeType) { - this(body, new ContentTypeHeader(mimeType)); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpHeaders.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpHeaders.java deleted file mode 100644 index 953c938..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpHeaders.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message; - -import org.seamless.http.Headers; -import org.fourthline.cling.model.message.header.UpnpHeader; - -import java.io.ByteArrayInputStream; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Provides UPnP header API in addition to plain multi-map HTTP header access. - * - * @author Christian Bauer - */ -public class UpnpHeaders extends Headers { - - private static final Logger log = Logger.getLogger(UpnpHeaders.class.getName()); - - protected Map> parsedHeaders; - - public UpnpHeaders() { - } - - public UpnpHeaders(Map> headers) { - super(headers); - } - - public UpnpHeaders(ByteArrayInputStream inputStream) { - super(inputStream); - } - - public UpnpHeaders(boolean normalizeHeaders) { - super(normalizeHeaders); - } - - protected void parseHeaders() { - // This runs as late as possible and only when necessary (getter called and map is dirty) - parsedHeaders = new LinkedHashMap<>(); - if (log.isLoggable(Level.FINE)) - log.fine("Parsing all HTTP headers for known UPnP headers: " + size()); - for (Entry> entry : entrySet()) { - - if (entry.getKey() == null) continue; // Oh yes, the JDK has 'null' HTTP headers - - UpnpHeader.Type type = UpnpHeader.Type.getByHttpName(entry.getKey()); - if (type == null) { - if (log.isLoggable(Level.FINE)) - log.fine("Ignoring non-UPNP HTTP header: " + entry.getKey()); - continue; - } - - for (String value : entry.getValue()) { - UpnpHeader upnpHeader = UpnpHeader.newInstance(type, value); - if (upnpHeader == null || upnpHeader.getValue() == null) { - if (log.isLoggable(Level.FINE)) - log.fine( - "Ignoring known but irrelevant header (value violates the UDA specification?) '" - + type.getHttpName() - + "': " - + value - ); - } else { - addParsedValue(type, upnpHeader); - } - } - } - } - - protected void addParsedValue(UpnpHeader.Type type, UpnpHeader value) { - if (log.isLoggable(Level.FINE)) - log.fine("Adding parsed header: " + value); - List list = parsedHeaders.get(type); - if (list == null) { - list = new LinkedList<>(); - parsedHeaders.put(type, list); - } - list.add(value); - } - - @Override - public List put(String key, List values) { - parsedHeaders = null; - return super.put(key, values); - } - - @Override - public void add(String key, String value) { - parsedHeaders = null; - super.add(key, value); - } - - @Override - public List remove(Object key) { - parsedHeaders = null; - return super.remove(key); - } - - @Override - public void clear() { - parsedHeaders = null; - super.clear(); - } - - public boolean containsKey(UpnpHeader.Type type) { - if (parsedHeaders == null) parseHeaders(); - return parsedHeaders.containsKey(type); - } - - public List get(UpnpHeader.Type type) { - if (parsedHeaders == null) parseHeaders(); - return parsedHeaders.get(type); - } - - public void add(UpnpHeader.Type type, UpnpHeader value) { - super.add(type.getHttpName(), value.getString()); - if (parsedHeaders != null) - addParsedValue(type, value); - } - - public void remove(UpnpHeader.Type type) { - super.remove(type.getHttpName()); - if (parsedHeaders != null) - parsedHeaders.remove(type); - } - - public UpnpHeader[] getAsArray(UpnpHeader.Type type) { - if (parsedHeaders == null) parseHeaders(); - return parsedHeaders.get(type) != null - ? parsedHeaders.get(type).toArray(new UpnpHeader[parsedHeaders.get(type).size()]) - : new UpnpHeader[0]; - } - - public UpnpHeader getFirstHeader(UpnpHeader.Type type) { - return getAsArray(type).length > 0 - ? getAsArray(type)[0] - : null; - } - - public H getFirstHeader(UpnpHeader.Type type, Class subtype) { - UpnpHeader[] headers = getAsArray(type); - if (headers.length == 0) return null; - - for (UpnpHeader header : headers) { - if (subtype.isAssignableFrom(header.getClass())) { - return (H) header; - } - } - return null; - } - - public String getFirstHeaderString(UpnpHeader.Type type) { - UpnpHeader header = getFirstHeader(type); - return header != null ? header.getString() : null; - } - - public void log() { - if (log.isLoggable(Level.FINE)) { - log.fine("############################ RAW HEADERS ###########################"); - for (Entry> entry : entrySet()) { - log.fine("=== NAME : " + entry.getKey()); - for (String v : entry.getValue()) { - log.fine("VALUE: " + v); - } - } - if (parsedHeaders != null && parsedHeaders.size() > 0) { - log.fine("########################## PARSED HEADERS ##########################"); - for (Map.Entry> entry : parsedHeaders.entrySet()) { - log.fine("=== TYPE: " + entry.getKey()); - for (UpnpHeader upnpHeader : entry.getValue()) { - log.fine("HEADER: " + upnpHeader); - } - } - } - log.fine("####################################################################"); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpMessage.java deleted file mode 100644 index 3dc7626..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpMessage.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message; - -import org.fourthline.cling.model.message.header.ContentTypeHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -import java.io.UnsupportedEncodingException; - -/** - * A non-streaming message, the interface between the transport layer and the protocols. - *

- * Defaults to UDA version 1.0 and a string body type. Message content is not streamed, - * it is always read into memory and transported as a string or bytes message body. - *

- *

- * Subtypes of this class typically implement the integrity rules for individual UPnP - * messages, for example, what headers a particular message requires. - *

- *

- * Messages are not thread-safe. - *

- * - * @author Christian Bauer - */ -public abstract class UpnpMessage { - - public static enum BodyType { - STRING, BYTES - } - - private int udaMajorVersion = 1; - private int udaMinorVersion = 0; - - private O operation; - private UpnpHeaders headers = new UpnpHeaders(); - private Object body; - private BodyType bodyType = BodyType.STRING; - - protected UpnpMessage(UpnpMessage source) { - this.operation = source.getOperation(); - this.headers = source.getHeaders(); - this.body = source.getBody(); - this.bodyType = source.getBodyType(); - this.udaMajorVersion = source.getUdaMajorVersion(); - this.udaMinorVersion = source.getUdaMinorVersion(); - } - - protected UpnpMessage(O operation) { - this.operation = operation; - } - - protected UpnpMessage(O operation, BodyType bodyType, Object body) { - this.operation = operation; - this.bodyType = bodyType; - this.body = body; - } - - public int getUdaMajorVersion() { - return udaMajorVersion; - } - - public void setUdaMajorVersion(int udaMajorVersion) { - this.udaMajorVersion = udaMajorVersion; - } - - public int getUdaMinorVersion() { - return udaMinorVersion; - } - - public void setUdaMinorVersion(int udaMinorVersion) { - this.udaMinorVersion = udaMinorVersion; - } - - public UpnpHeaders getHeaders() { - return headers; - } - - public void setHeaders(UpnpHeaders headers) { - this.headers = headers; - } - - public Object getBody() { - return body; - } - - public void setBody(String string) { - this.bodyType = BodyType.STRING; - this.body = string; - } - - public void setBody(BodyType bodyType, Object body) { - this.bodyType = bodyType; - this.body = body; - } - - public void setBodyCharacters(byte[] characterData) throws UnsupportedEncodingException { - setBody( - UpnpMessage.BodyType.STRING, - new String( - characterData, - getContentTypeCharset() != null - ? getContentTypeCharset() - : "UTF-8" - ) - ); - } - - public boolean hasBody() { - return getBody() != null; - } - - public BodyType getBodyType() { - return bodyType; - } - - public void setBodyType(BodyType bodyType) { - this.bodyType = bodyType; - } - - public String getBodyString() { - try { - if(!hasBody()) { - return null; - } - if(getBodyType().equals(BodyType.STRING)) { - String body = ((String) getBody()); - if(body.charAt(0) == '\ufeff') { /* utf8 BOM */ - body = body.substring(1); - } - return body; - } else { - return new String((byte[]) getBody(), "UTF-8"); - } - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - public byte[] getBodyBytes() { - try { - if(!hasBody()) { - return null; - } - if(getBodyType().equals(BodyType.STRING)) { - return getBodyString().getBytes(); - } else { - return (byte[]) getBody(); - } - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - public O getOperation() { - return operation; - } - - public boolean isContentTypeMissingOrText() { - ContentTypeHeader contentTypeHeader = getContentTypeHeader(); - // This is against the HTTP specification: If there is no content type we MAY assume that - // the entity body is bytes. However, to support broken UPnP devices which also violate the - // UPnP spec and do not send any content type at all, we need to assume no content type - // means a textual entity body is available. - if (contentTypeHeader == null) return true; - if (contentTypeHeader.isText()) return true; - // Only if there was any content-type header and none was text - return false; - } - - public ContentTypeHeader getContentTypeHeader() { - return getHeaders().getFirstHeader(UpnpHeader.Type.CONTENT_TYPE, ContentTypeHeader.class); - } - - public boolean isContentTypeText() { - ContentTypeHeader ct = getContentTypeHeader(); - return ct != null && ct.isText(); - } - - public boolean isContentTypeTextUDA() { - ContentTypeHeader ct = getContentTypeHeader(); - return ct != null && ct.isUDACompliantXML(); - } - - public String getContentTypeCharset() { - ContentTypeHeader ct = getContentTypeHeader(); - return ct != null ? ct.getValue().getParameters().get("charset") : null; - } - - public boolean hasHostHeader() { - return getHeaders().getFirstHeader(UpnpHeader.Type.HOST) != null; - } - - public boolean isBodyNonEmptyString() { - return hasBody() - && getBodyType().equals(UpnpMessage.BodyType.STRING) - && getBodyString().length() > 0; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") " + getOperation().toString(); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpOperation.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpOperation.java deleted file mode 100644 index 3508f4a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpOperation.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message; - -/** - * The operation, or HTTP details, of a message. - * - * @author Christian Bauer - */ -public abstract class UpnpOperation { - - private int httpMinorVersion = 1; - - public int getHttpMinorVersion() { - return httpMinorVersion; - } - - public void setHttpMinorVersion(int httpMinorVersion) { - this.httpMinorVersion = httpMinorVersion; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpRequest.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpRequest.java deleted file mode 100644 index 248752e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpRequest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message; - -import java.net.URI; -import java.net.URL; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.Map; -import java.util.Locale; - -/** - * A request message, with a method (GET, POST, NOTIFY, etc). - * - * @author Christian Bauer - */ -public class UpnpRequest extends UpnpOperation { - - public static enum Method { - - GET("GET"), - POST("POST"), - NOTIFY("NOTIFY"), - MSEARCH("M-SEARCH"), - SUBSCRIBE("SUBSCRIBE"), - UNSUBSCRIBE("UNSUBSCRIBE"), - UNKNOWN("UNKNOWN"); - - private static Map byName = new HashMap() {{ - for (Method m : Method.values()) { - put(m.getHttpName(), m); - } - }}; - - private String httpName; - - Method(String httpName) { - this.httpName = httpName; - } - - public String getHttpName() { - return httpName; - } - - public static Method getByHttpName(String httpName) { - if (httpName == null) return UNKNOWN; - Method m = byName.get(httpName.toUpperCase(Locale.ROOT)); - return m != null ? m : UNKNOWN; - } - } - - private Method method; - private URI uri; - - public UpnpRequest(Method method) { - this.method = method; - } - - public UpnpRequest(Method method, URI uri) { - this.method = method; - this.uri = uri; - } - - public UpnpRequest(Method method, URL url) { - this.method = method; - try { - if (url != null) { - this.uri = url.toURI(); - } - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - } - - public Method getMethod() { - return method; - } - - public String getHttpMethodName() { - return method.getHttpName(); - } - - public URI getURI() { - return uri; - } - - public void setUri(URI uri) { - this.uri = uri; - } - - @Override - public String toString() { - return getHttpMethodName() + (getURI() != null ? " " + getURI() : ""); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpResponse.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpResponse.java deleted file mode 100644 index 0dd9e96..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/UpnpResponse.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message; - -/** - * A response message, with a status code and message (OK, NOT FOUND, etc). - * - * @author Christian Bauer - */ -public class UpnpResponse extends UpnpOperation { - - public static enum Status { - - OK(200, "OK"), - BAD_REQUEST(400, "Bad Request"), - NOT_FOUND(404, "Not Found"), - METHOD_NOT_SUPPORTED(405, "Method Not Supported"), - PRECONDITION_FAILED(412, "Precondition Failed"), - UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"), - INTERNAL_SERVER_ERROR(500, "Internal Server Error"), - NOT_IMPLEMENTED(501, "Not Implemented"); - - private int statusCode; - private String statusMsg; - - Status(int statusCode, String statusMsg) { - this.statusCode = statusCode; - this.statusMsg = statusMsg; - } - - public int getStatusCode() { - return statusCode; - } - - public String getStatusMsg() { - return statusMsg; - } - - static public Status getByStatusCode(int statusCode) { - for (Status status : values()) { - if (status.getStatusCode() == statusCode) - return status; - } - return null; - } - } - - private int statusCode; - private String statusMessage; - - public UpnpResponse(int statusCode, String statusMessage) { - this.statusCode = statusCode; - this.statusMessage = statusMessage; - } - - public UpnpResponse(Status status) { - this.statusCode = status.getStatusCode(); - this.statusMessage = status.getStatusMsg(); - } - - public int getStatusCode() { - return statusCode; - } - - public String getStatusMessage() { - return statusMessage; - } - - /** - * @return true if the status code was equal or creater 300. - */ - public boolean isFailed() { - return statusCode >= 300; - } - - /** - * @return The concatenated string of status code and status message (same as {@link #toString()}. - */ - public String getResponseDetails() { - return getStatusCode() + " " + getStatusMessage(); - } - - @Override - public String toString() { - return getResponseDetails(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionMessage.java deleted file mode 100644 index 9d7ecc3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionMessage.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.control; - -/** - * A narrowing interface for action request/response messages. - * - * @author Christian Bauer - */ -public interface ActionMessage { - - public String getActionNamespace(); - - public boolean isBodyNonEmptyString(); - public String getBodyString(); - public void setBody(String string); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionRequestMessage.java deleted file mode 100644 index 1dfa72a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionRequestMessage.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.control; - - -/** - * @author Christian Bauer - */ -public interface ActionRequestMessage extends ActionMessage { -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionResponseMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionResponseMessage.java deleted file mode 100644 index 3e96aea..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/ActionResponseMessage.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.control; - -/** - * @author Christian Bauer - */ -public interface ActionResponseMessage extends ActionMessage { -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/IncomingActionRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/IncomingActionRequestMessage.java deleted file mode 100644 index d58ab29..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/IncomingActionRequestMessage.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.control; - -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.header.SoapActionHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.QueryStateVariableAction; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.SoapActionType; - -/** - * @author Christian Bauer - */ -public class IncomingActionRequestMessage extends StreamRequestMessage implements ActionRequestMessage { - - final private Action action; - final private String actionNamespace; - - public IncomingActionRequestMessage(StreamRequestMessage source, - LocalService service) throws ActionException { - super(source); - - SoapActionHeader soapActionHeader = getHeaders().getFirstHeader(UpnpHeader.Type.SOAPACTION, SoapActionHeader.class); - if (soapActionHeader == null) { - throw new ActionException(ErrorCode.INVALID_ACTION, "Missing SOAP action header"); - } - - SoapActionType actionType = soapActionHeader.getValue(); - - this.action = service.getAction(actionType.getActionName()); - if (this.action == null) { - throw new ActionException(ErrorCode.INVALID_ACTION, "Service doesn't implement action: " + actionType.getActionName()); - } - - if (!QueryStateVariableAction.ACTION_NAME.equals(actionType.getActionName())) { - if (!service.getServiceType().implementsVersion(actionType.getServiceType())) { - throw new ActionException(ErrorCode.INVALID_ACTION, "Service doesn't support the requested service version"); - } - } - - this.actionNamespace = actionType.getTypeString(); - } - - public Action getAction() { - return action; - } - - public String getActionNamespace() { - return actionNamespace; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/IncomingActionResponseMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/IncomingActionResponseMessage.java deleted file mode 100644 index b072255..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/IncomingActionResponseMessage.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.control; - -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpResponse; - -/** - * @author Christian Bauer - */ -public class IncomingActionResponseMessage extends StreamResponseMessage implements ActionResponseMessage { - - - public IncomingActionResponseMessage(StreamResponseMessage source) { - super(source); - } - - public IncomingActionResponseMessage(UpnpResponse operation) { - super(operation); - } - - public String getActionNamespace() { - return null; // TODO: We _could_ read this in SOAPActionProcessor and set it when we receive a response but why? - } - - public boolean isFailedNonRecoverable() { - int statusCode = getOperation().getStatusCode(); - return getOperation().isFailed() - && !(statusCode == UpnpResponse.Status.METHOD_NOT_SUPPORTED.getStatusCode() || - (statusCode == UpnpResponse.Status.INTERNAL_SERVER_ERROR.getStatusCode()) && hasBody()); - } - - public boolean isFailedRecoverable() { - return hasBody() && getOperation().getStatusCode() == UpnpResponse.Status.INTERNAL_SERVER_ERROR.getStatusCode(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/OutgoingActionRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/OutgoingActionRequestMessage.java deleted file mode 100644 index ecb68f2..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/OutgoingActionRequestMessage.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.control; - -import java.util.logging.Logger; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.action.RemoteActionInvocation; -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.meta.QueryStateVariableAction; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.header.ContentTypeHeader; -import org.fourthline.cling.model.message.header.SoapActionHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.message.header.UserAgentHeader; -import org.fourthline.cling.model.types.SoapActionType; - -import java.net.URL; - -/** - * @author Christian Bauer - */ -public class OutgoingActionRequestMessage extends StreamRequestMessage implements ActionRequestMessage { - - private static Logger log = Logger.getLogger(OutgoingActionRequestMessage.class.getName()); - - final private String actionNamespace; - - public OutgoingActionRequestMessage(ActionInvocation actionInvocation, URL controlURL) { - this(actionInvocation.getAction(), new UpnpRequest(UpnpRequest.Method.POST, controlURL)); - - // For proxy remote invocations, pass through the user agent header - if (actionInvocation instanceof RemoteActionInvocation) { - RemoteActionInvocation remoteActionInvocation = (RemoteActionInvocation) actionInvocation; - if (remoteActionInvocation.getRemoteClientInfo() != null - && remoteActionInvocation.getRemoteClientInfo().getRequestUserAgent() != null) { - getHeaders().add( - UpnpHeader.Type.USER_AGENT, - new UserAgentHeader(remoteActionInvocation.getRemoteClientInfo().getRequestUserAgent()) - ); - } - } else if (actionInvocation.getClientInfo() != null) { - getHeaders().putAll(actionInvocation.getClientInfo().getRequestHeaders()); - } - } - - public OutgoingActionRequestMessage(Action action, UpnpRequest operation) { - super(operation); - - getHeaders().add( - UpnpHeader.Type.CONTENT_TYPE, - new ContentTypeHeader(ContentTypeHeader.DEFAULT_CONTENT_TYPE_UTF8) - ); - - SoapActionHeader soapActionHeader; - if (action instanceof QueryStateVariableAction) { - log.fine("Adding magic control SOAP action header for state variable query action"); - soapActionHeader = new SoapActionHeader( - new SoapActionType( - SoapActionType.MAGIC_CONTROL_NS, SoapActionType.MAGIC_CONTROL_TYPE, null, action.getName() - ) - ); - } else { - soapActionHeader = new SoapActionHeader( - new SoapActionType( - action.getService().getServiceType(), - action.getName() - ) - ); - } - - // We need to keep it for later, convenience for writing the SOAP body XML - actionNamespace = soapActionHeader.getValue().getTypeString(); - - if (getOperation().getMethod().equals(UpnpRequest.Method.POST)) { - - getHeaders().add(UpnpHeader.Type.SOAPACTION, soapActionHeader); - log.fine("Added SOAP action header: " + soapActionHeader); - - /* TODO: Finish the M-POST crap (or not) - } else if (getOperation().getMethod().equals(UpnpRequest.Method.MPOST)) { - - getHeaders().add(UpnpHeader.Type.MAN, new MANHeader(Constants.SOAP_NS_ENVELOPE, "01")); - - getHeaders().add(UpnpHeader.Type.SOAPACTION, soapActionHeader); - getHeaders().setPrefix(UpnpHeader.Type.SOAPACTION, "01"); - log.fine("Added SOAP action header with prefix '01': " + getHeaders().getFirstHeader(UpnpHeader.Type.SOAPACTION).getString()); - */ - - } else { - throw new IllegalArgumentException("Can't send action with request method: " + getOperation().getMethod()); - } - } - - public String getActionNamespace() { - return actionNamespace; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/OutgoingActionResponseMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/OutgoingActionResponseMessage.java deleted file mode 100644 index d840e7a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/control/OutgoingActionResponseMessage.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.control; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.meta.Action; -import org.fourthline.cling.model.meta.QueryStateVariableAction; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.header.ContentTypeHeader; -import org.fourthline.cling.model.message.header.EXTHeader; -import org.fourthline.cling.model.message.header.ServerHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -/** - * @author Christian Bauer - */ -public class OutgoingActionResponseMessage extends StreamResponseMessage implements ActionResponseMessage { - - private String actionNamespace; - - public OutgoingActionResponseMessage(Action action) { - this(UpnpResponse.Status.OK, action); - } - - public OutgoingActionResponseMessage(UpnpResponse.Status status) { - this(status, null); - } - - public OutgoingActionResponseMessage(UpnpResponse.Status status, Action action) { - super(new UpnpResponse(status)); - - if (action != null) { - if (action instanceof QueryStateVariableAction) { - this.actionNamespace = Constants.NS_UPNP_CONTROL_10; - } else { - this.actionNamespace = action.getService().getServiceType().toString(); - } - } - - addHeaders(); - } - - protected void addHeaders() { - getHeaders().add( - UpnpHeader.Type.CONTENT_TYPE, - new ContentTypeHeader(ContentTypeHeader.DEFAULT_CONTENT_TYPE_UTF8) - ); - getHeaders().add( - UpnpHeader.Type.SERVER, - new ServerHeader() - ); - getHeaders().add( - UpnpHeader.Type.EXT, - new EXTHeader() - ); - } - - public String getActionNamespace() { - return actionNamespace; - } - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingNotificationRequest.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingNotificationRequest.java deleted file mode 100644 index daddcff..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingNotificationRequest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.header.DeviceUSNHeader; -import org.fourthline.cling.model.message.header.InterfaceMacHeader; -import org.fourthline.cling.model.message.header.LocationHeader; -import org.fourthline.cling.model.message.header.MaxAgeHeader; -import org.fourthline.cling.model.message.header.NTSHeader; -import org.fourthline.cling.model.message.header.ServiceUSNHeader; -import org.fourthline.cling.model.message.header.UDNHeader; -import org.fourthline.cling.model.message.header.USNRootDeviceHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.types.NamedDeviceType; -import org.fourthline.cling.model.types.NamedServiceType; -import org.fourthline.cling.model.types.NotificationSubtype; -import org.fourthline.cling.model.types.UDN; - -import java.net.URL; - -/** - * @author Christian Bauer - */ -public class IncomingNotificationRequest extends IncomingDatagramMessage { - - public IncomingNotificationRequest(IncomingDatagramMessage source) { - super(source); - } - - public boolean isAliveMessage() { - NTSHeader nts = getHeaders().getFirstHeader(UpnpHeader.Type.NTS, NTSHeader.class); - return nts != null && nts.getValue().equals(NotificationSubtype.ALIVE); - } - - public boolean isByeByeMessage() { - NTSHeader nts = getHeaders().getFirstHeader(UpnpHeader.Type.NTS, NTSHeader.class); - return nts != null && nts.getValue().equals(NotificationSubtype.BYEBYE); - } - - public URL getLocationURL() { - LocationHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.LOCATION, LocationHeader.class); - if (header != null) { - return header.getValue(); - } - return null; - } - - /** - * @return The UDN value after parsing various USN header values, or null. - */ - public UDN getUDN() { - // This processes the headers as specified in UDA 1.0, tables in section 1.1.12 - - UpnpHeader udnHeader = getHeaders().getFirstHeader(UpnpHeader.Type.USN, USNRootDeviceHeader.class); - if (udnHeader != null) return udnHeader.getValue(); - - udnHeader = getHeaders().getFirstHeader(UpnpHeader.Type.USN, UDNHeader.class); - if (udnHeader != null) return udnHeader.getValue(); - - UpnpHeader deviceTypeHeader = getHeaders().getFirstHeader(UpnpHeader.Type.USN, DeviceUSNHeader.class); - if (deviceTypeHeader != null) return deviceTypeHeader.getValue().getUdn(); - - UpnpHeader serviceTypeHeader = getHeaders().getFirstHeader(UpnpHeader.Type.USN, ServiceUSNHeader.class); - if (serviceTypeHeader != null) return serviceTypeHeader.getValue().getUdn(); - - return null; - } - - public Integer getMaxAge() { - MaxAgeHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.MAX_AGE, MaxAgeHeader.class); - if (header != null) { - return header.getValue(); - } - return null; - } - - public byte[] getInterfaceMacHeader() { - InterfaceMacHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.EXT_IFACE_MAC, InterfaceMacHeader.class); - if (header != null) { - return header.getValue(); - } - return null; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingSearchRequest.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingSearchRequest.java deleted file mode 100644 index e81e1c1..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingSearchRequest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.header.MANHeader; -import org.fourthline.cling.model.message.header.MXHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.types.NotificationSubtype; - -/** - * @author Christian Bauer - */ -public class IncomingSearchRequest extends IncomingDatagramMessage { - - public IncomingSearchRequest(IncomingDatagramMessage source) { - super(source); - } - - public UpnpHeader getSearchTarget() { - return getHeaders().getFirstHeader(UpnpHeader.Type.ST); - } - - public Integer getMX() { - MXHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.MX, MXHeader.class); - if (header != null) { - return header.getValue(); - } - return null; - } - - /** - * @return true if this message has a MAN with - * value {@link org.fourthline.cling.model.types.NotificationSubtype#DISCOVER}. - */ - public boolean isMANSSDPDiscover() { - MANHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.MAN, MANHeader.class); - return header != null && header.getValue().equals(NotificationSubtype.DISCOVER.getHeaderString()); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingSearchResponse.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingSearchResponse.java deleted file mode 100644 index bb12689..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/IncomingSearchResponse.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.header.DeviceUSNHeader; -import org.fourthline.cling.model.message.header.InterfaceMacHeader; -import org.fourthline.cling.model.message.header.LocationHeader; -import org.fourthline.cling.model.message.header.MaxAgeHeader; -import org.fourthline.cling.model.message.header.ServiceUSNHeader; -import org.fourthline.cling.model.message.header.UDNHeader; -import org.fourthline.cling.model.message.header.USNRootDeviceHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.types.NamedDeviceType; -import org.fourthline.cling.model.types.NamedServiceType; -import org.fourthline.cling.model.types.UDN; - -import java.net.URL; - -/** - * @author Christian Bauer - */ -public class IncomingSearchResponse extends IncomingDatagramMessage { - - public IncomingSearchResponse(IncomingDatagramMessage source) { - super(source); - } - - public boolean isSearchResponseMessage() { - UpnpHeader st = getHeaders().getFirstHeader(UpnpHeader.Type.ST); - UpnpHeader usn = getHeaders().getFirstHeader(UpnpHeader.Type.USN); - UpnpHeader ext = getHeaders().getFirstHeader(UpnpHeader.Type.EXT); // Has no value! - return st != null && st.getValue() != null && usn != null && usn.getValue() != null && ext != null; - } - - public UDN getRootDeviceUDN() { - // This processes the headers as specified in UDA 1.0, tables in section 1.1.12 - - UpnpHeader udnHeader = getHeaders().getFirstHeader(UpnpHeader.Type.USN, USNRootDeviceHeader.class); - if (udnHeader != null) return udnHeader.getValue(); - - udnHeader = getHeaders().getFirstHeader(UpnpHeader.Type.USN, UDNHeader.class); - if (udnHeader != null) return udnHeader.getValue(); - - UpnpHeader deviceTypeHeader = getHeaders().getFirstHeader(UpnpHeader.Type.USN, DeviceUSNHeader.class); - if (deviceTypeHeader != null) return deviceTypeHeader.getValue().getUdn(); - - UpnpHeader serviceTypeHeader = getHeaders().getFirstHeader(UpnpHeader.Type.USN, ServiceUSNHeader.class); - if (serviceTypeHeader != null) return serviceTypeHeader.getValue().getUdn(); - - return null; - } - - public URL getLocationURL() { - LocationHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.LOCATION, LocationHeader.class); - if (header != null) { - return header.getValue(); - } - return null; - } - - public Integer getMaxAge() { - MaxAgeHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.MAX_AGE, MaxAgeHeader.class); - if (header != null) { - return header.getValue(); - } - return null; - } - - public byte[] getInterfaceMacHeader() { - InterfaceMacHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.EXT_IFACE_MAC, InterfaceMacHeader.class); - if (header != null) { - return header.getValue(); - } - return null; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequest.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequest.java deleted file mode 100644 index db52ca7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.message.header.LocationHeader; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.message.OutgoingDatagramMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.header.HostHeader; -import org.fourthline.cling.model.message.header.NTSHeader; -import org.fourthline.cling.model.message.header.ServerHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.message.header.MaxAgeHeader; -import org.fourthline.cling.model.types.NotificationSubtype; - -/** - * @author Christian Bauer - */ -public abstract class OutgoingNotificationRequest extends OutgoingDatagramMessage { - - private NotificationSubtype type; - - protected OutgoingNotificationRequest(Location location, LocalDevice device, NotificationSubtype type) { - super( - new UpnpRequest(UpnpRequest.Method.NOTIFY), - ModelUtil.getInetAddressByName(Constants.IPV4_UPNP_MULTICAST_GROUP), - Constants.UPNP_MULTICAST_PORT - ); - - this.type = type; - - getHeaders().add(UpnpHeader.Type.MAX_AGE, new MaxAgeHeader(device.getIdentity().getMaxAgeSeconds())); - getHeaders().add(UpnpHeader.Type.LOCATION, new LocationHeader(location.getURL())); - - getHeaders().add(UpnpHeader.Type.SERVER, new ServerHeader()); - getHeaders().add(UpnpHeader.Type.HOST, new HostHeader()); - getHeaders().add(UpnpHeader.Type.NTS, new NTSHeader(type)); - } - - public NotificationSubtype getType() { - return type; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestDeviceType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestDeviceType.java deleted file mode 100644 index 160516e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestDeviceType.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.types.NotificationSubtype; -import org.fourthline.cling.model.message.header.DeviceTypeHeader; -import org.fourthline.cling.model.message.header.DeviceUSNHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -/** - * @author Christian Bauer - */ -public class OutgoingNotificationRequestDeviceType extends OutgoingNotificationRequest { - - public OutgoingNotificationRequestDeviceType(Location location, LocalDevice device, NotificationSubtype type) { - super(location, device, type); - - getHeaders().add(UpnpHeader.Type.NT, new DeviceTypeHeader(device.getType())); - getHeaders().add(UpnpHeader.Type.USN, new DeviceUSNHeader(device.getIdentity().getUdn(), device.getType())); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestRootDevice.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestRootDevice.java deleted file mode 100644 index 3f8dda5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestRootDevice.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.message.header.InterfaceMacHeader; -import org.fourthline.cling.model.message.header.RootDeviceHeader; -import org.fourthline.cling.model.message.header.USNRootDeviceHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.types.NotificationSubtype; - -/** - * @author Christian Bauer - */ -public class OutgoingNotificationRequestRootDevice extends OutgoingNotificationRequest { - - public OutgoingNotificationRequestRootDevice(Location location, LocalDevice device, NotificationSubtype type) { - super(location, device, type); - - getHeaders().add(UpnpHeader.Type.NT, new RootDeviceHeader()); - getHeaders().add(UpnpHeader.Type.USN, new USNRootDeviceHeader(device.getIdentity().getUdn())); - - if ("true".equals(System.getProperty(Constants.SYSTEM_PROPERTY_ANNOUNCE_MAC_ADDRESS)) - && location.getNetworkAddress().getHardwareAddress() != null) { - getHeaders().add( - UpnpHeader.Type.EXT_IFACE_MAC, - new InterfaceMacHeader(location.getNetworkAddress().getHardwareAddress()) - ); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestServiceType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestServiceType.java deleted file mode 100644 index 97ac54e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestServiceType.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.message.header.ServiceTypeHeader; -import org.fourthline.cling.model.message.header.ServiceUSNHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.types.NotificationSubtype; -import org.fourthline.cling.model.types.ServiceType; - -/** - * @author Christian Bauer - */ -public class OutgoingNotificationRequestServiceType extends OutgoingNotificationRequest { - - public OutgoingNotificationRequestServiceType(Location location, - LocalDevice device, NotificationSubtype type, - ServiceType serviceType) { - - super(location, device, type); - - getHeaders().add(UpnpHeader.Type.NT, new ServiceTypeHeader(serviceType)); - getHeaders().add(UpnpHeader.Type.USN, new ServiceUSNHeader(device.getIdentity().getUdn(), serviceType)); - } - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestUDN.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestUDN.java deleted file mode 100644 index fa6aace..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingNotificationRequestUDN.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.message.header.UDNHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.types.NotificationSubtype; - -/** - * @author Christian Bauer - */ -public class OutgoingNotificationRequestUDN extends OutgoingNotificationRequest { - - public OutgoingNotificationRequestUDN(Location location, LocalDevice device, NotificationSubtype type) { - super(location, device, type); - - getHeaders().add(UpnpHeader.Type.NT, new UDNHeader(device.getIdentity().getUdn())); - getHeaders().add(UpnpHeader.Type.USN, new UDNHeader(device.getIdentity().getUdn())); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchRequest.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchRequest.java deleted file mode 100644 index 69686f6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchRequest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.message.OutgoingDatagramMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.header.HostHeader; -import org.fourthline.cling.model.message.header.MANHeader; -import org.fourthline.cling.model.message.header.MXHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.types.NotificationSubtype; -import org.fourthline.cling.model.ModelUtil; - -/** - * @author Christian Bauer - */ -public class OutgoingSearchRequest extends OutgoingDatagramMessage { - - private UpnpHeader searchTarget; - - public OutgoingSearchRequest(UpnpHeader searchTarget, int mxSeconds) { - super( - new UpnpRequest(UpnpRequest.Method.MSEARCH), - ModelUtil.getInetAddressByName(Constants.IPV4_UPNP_MULTICAST_GROUP), - Constants.UPNP_MULTICAST_PORT - ); - - this.searchTarget = searchTarget; - - getHeaders().add(UpnpHeader.Type.MAN, new MANHeader(NotificationSubtype.DISCOVER.getHeaderString())); - getHeaders().add(UpnpHeader.Type.MX, new MXHeader(mxSeconds)); - getHeaders().add(UpnpHeader.Type.ST, searchTarget); - getHeaders().add(UpnpHeader.Type.HOST, new HostHeader()); - } - - public UpnpHeader getSearchTarget() { - return searchTarget; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponse.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponse.java deleted file mode 100644 index 9030445..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponse.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.OutgoingDatagramMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.header.EXTHeader; -import org.fourthline.cling.model.message.header.InterfaceMacHeader; -import org.fourthline.cling.model.message.header.LocationHeader; -import org.fourthline.cling.model.message.header.MaxAgeHeader; -import org.fourthline.cling.model.message.header.ServerHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.LocalDevice; - -/** - * @author Christian Bauer - */ -public class OutgoingSearchResponse extends OutgoingDatagramMessage { - - public OutgoingSearchResponse(IncomingDatagramMessage request, - Location location, - LocalDevice device) { - - super(new UpnpResponse(UpnpResponse.Status.OK), request.getSourceAddress(), request.getSourcePort()); - - getHeaders().add(UpnpHeader.Type.MAX_AGE, new MaxAgeHeader(device.getIdentity().getMaxAgeSeconds())); - getHeaders().add(UpnpHeader.Type.LOCATION, new LocationHeader(location.getURL())); - getHeaders().add(UpnpHeader.Type.SERVER, new ServerHeader()); - getHeaders().add(UpnpHeader.Type.EXT, new EXTHeader()); - - if ("true".equals(System.getProperty(Constants.SYSTEM_PROPERTY_ANNOUNCE_MAC_ADDRESS)) - && location.getNetworkAddress().getHardwareAddress() != null) { - getHeaders().add( - UpnpHeader.Type.EXT_IFACE_MAC, - new InterfaceMacHeader(location.getNetworkAddress().getHardwareAddress()) - ); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseDeviceType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseDeviceType.java deleted file mode 100644 index a8b4f97..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseDeviceType.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.header.DeviceTypeHeader; -import org.fourthline.cling.model.message.header.DeviceUSNHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -/** - * @author Christian Bauer - */ -public class OutgoingSearchResponseDeviceType extends OutgoingSearchResponse { - - public OutgoingSearchResponseDeviceType(IncomingDatagramMessage request, - Location location, - LocalDevice device) { - super(request, location, device); - - getHeaders().add(UpnpHeader.Type.ST, new DeviceTypeHeader(device.getType())); - getHeaders().add(UpnpHeader.Type.USN, new DeviceUSNHeader(device.getIdentity().getUdn(), device.getType())); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseRootDevice.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseRootDevice.java deleted file mode 100644 index 3214d53..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseRootDevice.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.header.RootDeviceHeader; -import org.fourthline.cling.model.message.header.USNRootDeviceHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.LocalDevice; - -/** - * @author Christian Bauer - */ -public class OutgoingSearchResponseRootDevice extends OutgoingSearchResponse { - - public OutgoingSearchResponseRootDevice(IncomingDatagramMessage request, - Location location, - LocalDevice device) { - super(request, location, device); - - getHeaders().add(UpnpHeader.Type.ST, new RootDeviceHeader()); - getHeaders().add(UpnpHeader.Type.USN, new USNRootDeviceHeader(device.getIdentity().getUdn())); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseServiceType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseServiceType.java deleted file mode 100644 index 9c3adec..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseServiceType.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.header.ServiceTypeHeader; -import org.fourthline.cling.model.message.header.ServiceUSNHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.types.ServiceType; - -/** - * @author Christian Bauer - */ -public class OutgoingSearchResponseServiceType extends OutgoingSearchResponse { - - public OutgoingSearchResponseServiceType(IncomingDatagramMessage request, - Location location, - LocalDevice device, - ServiceType serviceType) { - super(request, location, device); - - getHeaders().add(UpnpHeader.Type.ST, new ServiceTypeHeader(serviceType)); - getHeaders().add(UpnpHeader.Type.USN, new ServiceUSNHeader(device.getIdentity().getUdn(), serviceType)); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseUDN.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseUDN.java deleted file mode 100644 index 2a67d23..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/discovery/OutgoingSearchResponseUDN.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.discovery; - -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.header.UDNHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.LocalDevice; - -/** - * @author Christian Bauer - */ -public class OutgoingSearchResponseUDN extends OutgoingSearchResponse { - - public OutgoingSearchResponseUDN(IncomingDatagramMessage request, - Location location, - LocalDevice device) { - super(request, location, device); - - getHeaders().add(UpnpHeader.Type.ST, new UDNHeader(device.getIdentity().getUdn())); - getHeaders().add(UpnpHeader.Type.USN, new UDNHeader(device.getIdentity().getUdn())); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingEventRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingEventRequestMessage.java deleted file mode 100644 index 820c9e7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingEventRequestMessage.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.gena; - -import org.fourthline.cling.model.meta.RemoteService; -import org.fourthline.cling.model.state.StateVariableValue; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.message.header.SubscriptionIdHeader; -import org.fourthline.cling.model.message.header.NTEventHeader; -import org.fourthline.cling.model.message.header.NTSHeader; -import org.fourthline.cling.model.message.header.EventSequenceHeader; -import org.fourthline.cling.model.types.NotificationSubtype; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.List; -import java.util.ArrayList; - -/** - * @author Christian Bauer - */ -public class IncomingEventRequestMessage extends StreamRequestMessage { - - final private List stateVariableValues = new ArrayList<>(); - final private RemoteService service; - - public IncomingEventRequestMessage(StreamRequestMessage source, RemoteService service) { - super(source); - this.service = service; - } - - public RemoteService getService() { - return service; - } - - public List getStateVariableValues() { - return stateVariableValues; - } - - public String getSubscrptionId() { - SubscriptionIdHeader header = - getHeaders().getFirstHeader(UpnpHeader.Type.SID,SubscriptionIdHeader.class); - return header != null ? header.getValue() : null; - } - - public UnsignedIntegerFourBytes getSequence() { - EventSequenceHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.SEQ, EventSequenceHeader.class); - return header != null ? header.getValue() : null; - } - - /** - * @return true if this message as an NT and NTS header. - */ - public boolean hasNotificationHeaders() { - UpnpHeader ntHeader = getHeaders().getFirstHeader(UpnpHeader.Type.NT); - UpnpHeader ntsHeader = getHeaders().getFirstHeader(UpnpHeader.Type.NTS); - return ntHeader != null && ntHeader.getValue() != null - && ntsHeader != null && ntsHeader.getValue() != null; - } - - /** - * @return true if this message has an NT header, and NTS header - * with value {@link org.fourthline.cling.model.types.NotificationSubtype#PROPCHANGE}. - */ - public boolean hasValidNotificationHeaders() { - NTEventHeader ntHeader = getHeaders().getFirstHeader(UpnpHeader.Type.NT, NTEventHeader.class); - NTSHeader ntsHeader = getHeaders().getFirstHeader(UpnpHeader.Type.NTS, NTSHeader.class); - return ntHeader != null && ntHeader.getValue() != null - && ntsHeader != null && ntsHeader.getValue().equals(NotificationSubtype.PROPCHANGE); - - } - - @Override - public String toString() { - return super.toString() + " SEQUENCE: " + getSequence().getValue(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingSubscribeRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingSubscribeRequestMessage.java deleted file mode 100644 index 8d9c8d9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingSubscribeRequestMessage.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.gena; - -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.header.CallbackHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.message.header.NTEventHeader; -import org.fourthline.cling.model.message.header.TimeoutHeader; -import org.fourthline.cling.model.message.header.SubscriptionIdHeader; -import org.fourthline.cling.model.meta.LocalService; - -import java.net.URL; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class IncomingSubscribeRequestMessage extends StreamRequestMessage { - - final private LocalService service; - - public IncomingSubscribeRequestMessage(StreamRequestMessage source, LocalService service) { - super(source); - this.service = service; - } - - public LocalService getService() { - return service; - } - - public List getCallbackURLs() { - CallbackHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.CALLBACK, CallbackHeader.class); - return header != null ? header.getValue() : null; - } - - public boolean hasNotificationHeader() { - return getHeaders().getFirstHeader(UpnpHeader.Type.NT, NTEventHeader.class) != null; - } - - public Integer getRequestedTimeoutSeconds() { - TimeoutHeader timeoutHeader = getHeaders().getFirstHeader(UpnpHeader.Type.TIMEOUT, TimeoutHeader.class); - return timeoutHeader != null ? timeoutHeader.getValue() : null; - } - - public String getSubscriptionId() { - SubscriptionIdHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.SID, SubscriptionIdHeader.class); - return header != null ? header.getValue() : null; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingSubscribeResponseMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingSubscribeResponseMessage.java deleted file mode 100644 index 50975a3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingSubscribeResponseMessage.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.gena; - -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.header.SubscriptionIdHeader; -import org.fourthline.cling.model.message.header.TimeoutHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -/** - * @author Christian Bauer - */ -public class IncomingSubscribeResponseMessage extends StreamResponseMessage { - - public IncomingSubscribeResponseMessage(StreamResponseMessage source) { - super(source); - } - - /** - * @return true if this message has an SID and TIMEOUT header value. - */ - public boolean isValidHeaders() { - return getHeaders().getFirstHeader(UpnpHeader.Type.SID, SubscriptionIdHeader.class) != null && - getHeaders().getFirstHeader(UpnpHeader.Type.TIMEOUT, TimeoutHeader.class) != null; - } - - public String getSubscriptionId() { - return getHeaders().getFirstHeader(UpnpHeader.Type.SID, SubscriptionIdHeader.class).getValue(); - } - - public int getSubscriptionDurationSeconds() { - return getHeaders().getFirstHeader(UpnpHeader.Type.TIMEOUT, TimeoutHeader.class).getValue(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingUnsubscribeRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingUnsubscribeRequestMessage.java deleted file mode 100644 index bbdd7e9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/IncomingUnsubscribeRequestMessage.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.gena; - -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.header.CallbackHeader; -import org.fourthline.cling.model.message.header.NTEventHeader; -import org.fourthline.cling.model.message.header.SubscriptionIdHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -/** - * @author Christian Bauer - */ -public class IncomingUnsubscribeRequestMessage extends StreamRequestMessage { - - final private LocalService service; - - public IncomingUnsubscribeRequestMessage(StreamRequestMessage source, LocalService service) { - super(source); - this.service = service; - } - - public LocalService getService() { - return service; - } - - public boolean hasCallbackHeader() { - return getHeaders().getFirstHeader(UpnpHeader.Type.CALLBACK, CallbackHeader.class) != null; - } - - public boolean hasNotificationHeader() { - return getHeaders().getFirstHeader(UpnpHeader.Type.NT, NTEventHeader.class) != null; - } - - public String getSubscriptionId() { - SubscriptionIdHeader header = getHeaders().getFirstHeader(UpnpHeader.Type.SID, SubscriptionIdHeader.class); - return header != null ? header.getValue() : null; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingEventRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingEventRequestMessage.java deleted file mode 100644 index fba09e6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingEventRequestMessage.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.gena; - -import org.fourthline.cling.model.state.StateVariableValue; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.header.ContentTypeHeader; -import org.fourthline.cling.model.message.header.EventSequenceHeader; -import org.fourthline.cling.model.message.header.NTEventHeader; -import org.fourthline.cling.model.message.header.NTSHeader; -import org.fourthline.cling.model.message.header.SubscriptionIdHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.types.NotificationSubtype; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.model.gena.GENASubscription; - -import java.net.URL; -import java.util.Collection; - -/** - * @author Christian Bauer - */ -public class OutgoingEventRequestMessage extends StreamRequestMessage { - - final private Collection stateVariableValues; - - public OutgoingEventRequestMessage(GENASubscription subscription, - URL callbackURL, - UnsignedIntegerFourBytes sequence, - Collection values) { - - super(new UpnpRequest(UpnpRequest.Method.NOTIFY, callbackURL)); - - getHeaders().add(UpnpHeader.Type.CONTENT_TYPE, new ContentTypeHeader()); - getHeaders().add(UpnpHeader.Type.NT, new NTEventHeader()); - getHeaders().add(UpnpHeader.Type.NTS, new NTSHeader(NotificationSubtype.PROPCHANGE)); - getHeaders().add(UpnpHeader.Type.SID, new SubscriptionIdHeader(subscription.getSubscriptionId())); - - // Important! Pass by value so that we can safely increment it afterwards and before this is send! - getHeaders().add(UpnpHeader.Type.SEQ, new EventSequenceHeader(sequence.getValue())); - - this.stateVariableValues = values; - } - - public OutgoingEventRequestMessage(GENASubscription subscription, URL callbackURL) { - this(subscription, callbackURL, subscription.getCurrentSequence(), subscription.getCurrentValues().values()); - } - - public Collection getStateVariableValues() { - return stateVariableValues; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingEventResponseMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingEventResponseMessage.java deleted file mode 100644 index 4ee0e9e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingEventResponseMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.gena; - -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.header.ContentTypeHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -/** - * @author Christian Bauer - */ -public class OutgoingEventResponseMessage extends StreamResponseMessage { - - public OutgoingEventResponseMessage() { - super(new UpnpResponse(UpnpResponse.Status.OK)); - getHeaders().add(UpnpHeader.Type.CONTENT_TYPE, new ContentTypeHeader()); - } - - public OutgoingEventResponseMessage(UpnpResponse operation) { - super(operation); - getHeaders().add(UpnpHeader.Type.CONTENT_TYPE, new ContentTypeHeader()); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingRenewalRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingRenewalRequestMessage.java deleted file mode 100644 index 2b1e524..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingRenewalRequestMessage.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.gena; - -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.header.SubscriptionIdHeader; -import org.fourthline.cling.model.message.header.TimeoutHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -/** - * @author Christian Bauer - */ -public class OutgoingRenewalRequestMessage extends StreamRequestMessage { - - public OutgoingRenewalRequestMessage(RemoteGENASubscription subscription, - UpnpHeaders extraHeaders) { - - super(UpnpRequest.Method.SUBSCRIBE, subscription.getEventSubscriptionURL()); - - getHeaders().add( - UpnpHeader.Type.SID, - new SubscriptionIdHeader(subscription.getSubscriptionId()) - ); - - getHeaders().add( - UpnpHeader.Type.TIMEOUT, - new TimeoutHeader(subscription.getRequestedDurationSeconds()) - ); - - if (extraHeaders != null) - getHeaders().putAll(extraHeaders); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingSubscribeRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingSubscribeRequestMessage.java deleted file mode 100644 index 2e8e46a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingSubscribeRequestMessage.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.gena; - -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.header.CallbackHeader; -import org.fourthline.cling.model.message.header.NTEventHeader; -import org.fourthline.cling.model.message.header.TimeoutHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -import java.net.URL; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class OutgoingSubscribeRequestMessage extends StreamRequestMessage { - - public OutgoingSubscribeRequestMessage(RemoteGENASubscription subscription, - List callbackURLs, - UpnpHeaders extraHeaders) { - - super(UpnpRequest.Method.SUBSCRIBE, subscription.getEventSubscriptionURL()); - - getHeaders().add( - UpnpHeader.Type.CALLBACK, - new CallbackHeader(callbackURLs) - ); - - getHeaders().add( - UpnpHeader.Type.NT, - new NTEventHeader() - ); - - getHeaders().add( - UpnpHeader.Type.TIMEOUT, - new TimeoutHeader(subscription.getRequestedDurationSeconds()) - ); - - if (extraHeaders != null) - getHeaders().putAll(extraHeaders); - } - - public boolean hasCallbackURLs() { - CallbackHeader callbackHeader = - getHeaders().getFirstHeader(UpnpHeader.Type.CALLBACK, CallbackHeader.class); - return callbackHeader.getValue().size() > 0; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingSubscribeResponseMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingSubscribeResponseMessage.java deleted file mode 100644 index c958e45..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingSubscribeResponseMessage.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.gena; - -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.header.ServerHeader; -import org.fourthline.cling.model.message.header.SubscriptionIdHeader; -import org.fourthline.cling.model.message.header.TimeoutHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.gena.LocalGENASubscription; - -/** - * @author Christian Bauer - */ -public class OutgoingSubscribeResponseMessage extends StreamResponseMessage { - - - public OutgoingSubscribeResponseMessage(UpnpResponse.Status status) { - super(status); - } - - public OutgoingSubscribeResponseMessage(LocalGENASubscription subscription) { - super(new UpnpResponse(UpnpResponse.Status.OK)); - - getHeaders().add(UpnpHeader.Type.SERVER,new ServerHeader()); - getHeaders().add(UpnpHeader.Type.SID, new SubscriptionIdHeader(subscription.getSubscriptionId())); - getHeaders().add(UpnpHeader.Type.TIMEOUT, new TimeoutHeader(subscription.getActualDurationSeconds())); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingUnsubscribeRequestMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingUnsubscribeRequestMessage.java deleted file mode 100644 index d30be58..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/gena/OutgoingUnsubscribeRequestMessage.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.gena; - -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.header.SubscriptionIdHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; - -/** - * @author Christian Bauer - */ -public class OutgoingUnsubscribeRequestMessage extends StreamRequestMessage { - - public OutgoingUnsubscribeRequestMessage(RemoteGENASubscription subscription, - UpnpHeaders extraHeaders) { - - super(UpnpRequest.Method.UNSUBSCRIBE, subscription.getEventSubscriptionURL()); - - getHeaders().add( - UpnpHeader.Type.SID, - new SubscriptionIdHeader(subscription.getSubscriptionId()) - ); - - if (extraHeaders != null) - getHeaders().putAll(extraHeaders); - - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/AVClientInfoHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/AVClientInfoHeader.java deleted file mode 100644 index a7cb345..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/AVClientInfoHeader.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -/** - * A simple string, not validated, used only by Sony Playstation3. - * - * @author Christian Bauer - */ -public class AVClientInfoHeader extends UpnpHeader { - - public AVClientInfoHeader() { - } - - public AVClientInfoHeader(String s) { - setValue(s); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - setValue(s); - } - - @Override - public String getString() { - return getValue(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/CallbackHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/CallbackHeader.java deleted file mode 100644 index 1a22148..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/CallbackHeader.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public class CallbackHeader extends UpnpHeader> { - - final private static Logger log = Logger.getLogger(CallbackHeader.class.getName()); - - public CallbackHeader() { - setValue(new ArrayList()); - } - - public CallbackHeader(List urls) { - this(); - getValue().addAll(urls); - } - - public CallbackHeader(URL url) { - this(); - getValue().add(url); - } - - public void setString(String s) throws InvalidHeaderException { - - if (s.length() == 0) { - // Well, no callback URLs are not useful but we have to consider this state - return; - } - - if (!s.contains("<") || !s.contains(">")) { - throw new InvalidHeaderException("URLs not in brackets: " + s); - } - - s = s.replaceAll("<", ""); - String[] split = s.split(">"); - try { - List urls = new ArrayList<>(); - for (String sp : split) { - sp = sp.trim(); - - if (!sp.startsWith("http://")) { - log.warning("Discarding non-http callback URL: " + sp); - continue; - } - - URL url = new URL(sp); - try { - /* - On some platforms (Android...), a valid URL might not be a valid URI, so - we need to test for this and skip any invalid URI, e.g. - - Java.net.URISyntaxException: Invalid % sequence: %wl in authority at index 32: http://[fe80::208:caff:fec4:824e%wlan0]:8485/eventSub - at libcore.net.UriCodec.validate(UriCodec.java:58) - at java.net.URI.parseURI(URI.java:394) - at java.net.URI.(URI.java:204) - at java.net.URL.toURI(URL.java:497) - */ - url.toURI(); - } catch (URISyntaxException ex) { - log.log(Level.WARNING, "Discarding callback URL, not a valid URI on this platform: " + url, ex); - continue; - } - - urls.add(url); - } - setValue(urls); - } catch (MalformedURLException ex) { - throw new InvalidHeaderException("Can't parse callback URLs from '" + s + "': " + ex); - } - } - - public String getString() { - StringBuilder s = new StringBuilder(); - for (URL url : getValue()) { - s.append("<").append(url.toString()).append(">"); - } - return s.toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ContentRangeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ContentRangeHeader.java deleted file mode 100644 index 0f2bfea..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ContentRangeHeader.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.BytesRange; -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * - * @author Christian Bauer - * @author Mario Franco - */ -public class ContentRangeHeader extends UpnpHeader { - - public static final String PREFIX = "bytes "; - - public ContentRangeHeader() { - } - - public ContentRangeHeader(BytesRange value) { - setValue(value); - } - - public ContentRangeHeader(String s) { - setString(s); - } - - public void setString(String s) throws InvalidHeaderException { - try { - setValue(BytesRange.valueOf(s,PREFIX)); - } catch (InvalidValueException invalidValueException) { - throw new InvalidHeaderException("Invalid Range Header: " + invalidValueException.getMessage()); - } - } - - public String getString() { - return getValue().getString(true,PREFIX); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ContentTypeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ContentTypeHeader.java deleted file mode 100644 index a8a9782..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ContentTypeHeader.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.seamless.util.MimeType; - -/** - * @author Christian Bauer - */ -public class ContentTypeHeader extends UpnpHeader { - - public static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/xml"); - public static final MimeType DEFAULT_CONTENT_TYPE_UTF8 = MimeType.valueOf("text/xml;charset=\"utf-8\""); - - public ContentTypeHeader() { - setValue(DEFAULT_CONTENT_TYPE); - } - - public ContentTypeHeader(MimeType contentType) { - setValue(contentType); - } - - public ContentTypeHeader(String s) throws InvalidHeaderException{ - setString(s); - } - - public void setString(String s) throws InvalidHeaderException { - setValue(MimeType.valueOf(s)); - } - - public String getString() { - return getValue().toString(); - } - - public boolean isUDACompliantXML() { - // UDA spec says "must be text/xml", however, sometimes you get a charset token as well... - return isText() && getValue().getSubtype().equals(DEFAULT_CONTENT_TYPE.getSubtype()); - } - - public boolean isText() { - return getValue() != null && getValue().getType().equals(DEFAULT_CONTENT_TYPE.getType()); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/DeviceTypeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/DeviceTypeHeader.java deleted file mode 100644 index 0ad6c30..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/DeviceTypeHeader.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.DeviceType; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class DeviceTypeHeader extends UpnpHeader { - - public DeviceTypeHeader() { - } - - public DeviceTypeHeader(URI uri) { - setString(uri.toString()); - } - - public DeviceTypeHeader(DeviceType value) { - setValue(value); - } - - public void setString(String s) throws InvalidHeaderException { - try { - setValue(DeviceType.valueOf(s)); - } catch (RuntimeException ex) { - throw new InvalidHeaderException("Invalid device type header value, " + ex.getMessage()); - } - } - - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/DeviceUSNHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/DeviceUSNHeader.java deleted file mode 100644 index 8c4152d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/DeviceUSNHeader.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.NamedDeviceType; -import org.fourthline.cling.model.types.UDN; - -/** - * @author Christian Bauer - */ -public class DeviceUSNHeader extends UpnpHeader { - - public DeviceUSNHeader() { - } - - public DeviceUSNHeader(UDN udn, DeviceType deviceType) { - setValue(new NamedDeviceType(udn, deviceType)); - } - - public DeviceUSNHeader(NamedDeviceType value) { - setValue(value); - } - - public void setString(String s) throws InvalidHeaderException { - try { - setValue(NamedDeviceType.valueOf(s)); - } catch (Exception ex) { - throw new InvalidHeaderException("Invalid device USN header value, " + ex.getMessage()); - } - } - - public String getString() { - return getValue().toString(); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/EXTHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/EXTHeader.java deleted file mode 100644 index a245b07..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/EXTHeader.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -/** - * @author Christian Bauer - */ -public class EXTHeader extends UpnpHeader { - - // That's just an empty header! Isn't that great... - public final static String DEFAULT_VALUE = ""; - - public EXTHeader() { - setValue(DEFAULT_VALUE); - } - - public void setString(String s) throws InvalidHeaderException { - if (s != null && s.length() > 0) { - throw new InvalidHeaderException("Invalid EXT header, it has no value: " + s); - } - } - - public String getString() { - return getValue(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/EventSequenceHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/EventSequenceHeader.java deleted file mode 100644 index 410e9de..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/EventSequenceHeader.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -/** - * @author Christian Bauer - */ -public class EventSequenceHeader extends UpnpHeader { - - public EventSequenceHeader() { - } - - public EventSequenceHeader(long value) { - setValue(new UnsignedIntegerFourBytes(value)); - } - - public void setString(String s) throws InvalidHeaderException { - - // Cut off leading zeros - if (!"0".equals(s)) { - while(s.startsWith("0")) { - s = s.substring(1); - } - } - - try { - setValue(new UnsignedIntegerFourBytes(s)); - } catch (NumberFormatException ex) { - throw new InvalidHeaderException("Invalid event sequence, " + ex.getMessage()); - } - - } - - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/HostHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/HostHeader.java deleted file mode 100644 index 2f2cb75..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/HostHeader.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.types.HostPort; - -/** - * @author Christian Bauer - */ -public class HostHeader extends UpnpHeader { - - int port = Constants.UPNP_MULTICAST_PORT; - String group = Constants.IPV4_UPNP_MULTICAST_GROUP; - - public HostHeader() { - setValue(new HostPort(group, port)); - } - - public HostHeader(int port) { - setValue(new HostPort(group, port)); - } - - public HostHeader(String host, int port) { - setValue(new HostPort(host, port)); - } - - public void setString(String s) throws InvalidHeaderException { - // UDA 1.1/1.0 section 1.2.2 - if (s.contains(":")) { - // We have a port in the header, so we have to use that instead of the UDA default - try { - this.port = Integer.valueOf(s.substring(s.indexOf(":")+1)); - this.group = s.substring(0, s.indexOf(":")); - setValue(new HostPort(group, port)); - } catch (NumberFormatException ex) { - throw new InvalidHeaderException("Invalid HOST header value, can't parse port: " + s + " - " + ex.getMessage()); - } - } else { - this.group = s; - setValue(new HostPort(group, port)); - } - } - - public String getString() { - return getValue().toString(); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/InterfaceMacHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/InterfaceMacHeader.java deleted file mode 100644 index 0bff58c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/InterfaceMacHeader.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.seamless.util.io.HexBin; - -/** - * Custom header for Cling, used to transfer the MAC ethernet address for Wake-on-LAN. - * - * @author Christian Bauer - */ -public class InterfaceMacHeader extends UpnpHeader { - - public InterfaceMacHeader() { - } - - public InterfaceMacHeader(byte[] value) { - setValue(value); - } - - public InterfaceMacHeader(String s) { - setString(s); - } - - public void setString(String s) throws InvalidHeaderException { - byte[] bytes = HexBin.stringToBytes(s, ":"); - setValue(bytes); - if (bytes.length != 6) { - throw new InvalidHeaderException("Invalid MAC address: " + s); - } - } - - public String getString() { - return HexBin.bytesToString(getValue(), ":"); - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") '" + getString() + "'"; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/InvalidHeaderException.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/InvalidHeaderException.java deleted file mode 100644 index b965981..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/InvalidHeaderException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -/** - * Thrown if the value of a header was invalid for the given header. - * - * @author Christian Bauer - */ -public class InvalidHeaderException extends RuntimeException { - - public InvalidHeaderException(String s) { - super(s); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/LocationHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/LocationHeader.java deleted file mode 100644 index ff9033a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/LocationHeader.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import java.net.MalformedURLException; -import java.net.URL; - -/** - * TODO: UDA 1.1 says it should be RfC 3986 compatible. - * - *

See http://blog.jclark.com/2008/11/what-allowed-in-uri.html

- * - * @author Christian Bauer - */ -public class LocationHeader extends UpnpHeader { - - public LocationHeader() { - } - - public LocationHeader(URL value) { - setValue(value); - } - - public LocationHeader(String s) { - setString(s); - } - - public void setString(String s) throws InvalidHeaderException { - try { - URL url = new URL(s); - setValue(url); - } catch (MalformedURLException ex) { - throw new InvalidHeaderException("Invalid URI: " + ex.getMessage()); - } - } - - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MANHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MANHeader.java deleted file mode 100644 index ed06a50..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MANHeader.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -/** - * @author Christian Bauer - */ -public class MANHeader extends UpnpHeader { - - public static final Pattern PATTERN = Pattern.compile("\"(.+?)\"(;.+?)??"); - public static final Pattern NAMESPACE_PATTERN = Pattern.compile(";\\s?ns\\s?=\\s?([0-9]{2})"); - - public String namespace; - - public MANHeader() { - } - - public MANHeader(String value) { - setValue(value); - } - - public MANHeader(String value, String namespace) { - this(value); - this.namespace = namespace; - } - - public void setString(String s) throws InvalidHeaderException { - - Matcher matcher = PATTERN.matcher(s); - if (matcher.matches()) { - setValue(matcher.group(1)); - - if (matcher.group(2) != null) { - Matcher nsMatcher = NAMESPACE_PATTERN.matcher(matcher.group(2)); - if (nsMatcher.matches()) { - setNamespace(nsMatcher.group(1)); - } else { - throw new InvalidHeaderException("Invalid namespace in MAN header value: " + s); - } - } - - } else { - throw new InvalidHeaderException("Invalid MAN header value: " + s); - } - } - - public String getString() { - if (getValue() == null) return null; - StringBuilder s = new StringBuilder(); - s.append("\"").append(getValue()).append("\""); - if (getNamespace() != null) s.append("; ns=").append(getNamespace()); - return s.toString(); - } - - public String getNamespace() { - return namespace; - } - - public void setNamespace(String namespace) { - this.namespace = namespace; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MXHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MXHeader.java deleted file mode 100644 index c9d59eb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MXHeader.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -/** - * @author Christian Bauer - */ -public class MXHeader extends UpnpHeader { - - // 3 second seems like a good default to spread search responses (UDA says 120?!? wtf) - public static final Integer DEFAULT_VALUE = 3; - - /** - * Defaults to 3 seconds. - */ - public MXHeader() { - setValue(DEFAULT_VALUE); - } - - public MXHeader(Integer delayInSeconds) { - setValue(delayInSeconds); - } - - public void setString(String s) throws InvalidHeaderException { - Integer value; - try { - value = Integer.parseInt(s); - } catch (Exception ex) { - throw new InvalidHeaderException("Can't parse MX seconds integer from: " + s); - } - - // UDA 1.0, section 1.2.3: "If the MX header specifies a value greater than 120, the device - // should assume that it contained the value 120 or less." - if (value < 0 || value > 120) { - setValue(DEFAULT_VALUE); - } else { - setValue(value); - } - } - - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MaxAgeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MaxAgeHeader.java deleted file mode 100644 index 282a803..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/MaxAgeHeader.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.Constants; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.Locale; - -/** - * @author Christian Bauer - */ -public class MaxAgeHeader extends UpnpHeader { - - // UDA 1.1 expands on the rules in UDA 1.0 and clearly says that anything but max-age has to be ignored - public static final Pattern MAX_AGE_REGEX = Pattern.compile(".*max-age\\s*=\\s*([0-9]+).*"); - - public MaxAgeHeader(Integer maxAge) { - setValue(maxAge); - } - - public MaxAgeHeader() { - setValue(Constants.MIN_ADVERTISEMENT_AGE_SECONDS); - } - - public void setString(String s) throws InvalidHeaderException { - - Matcher matcher = MAX_AGE_REGEX.matcher(s.toLowerCase(Locale.ROOT)); - if (!matcher.matches()){ - throw new InvalidHeaderException("Invalid cache-control value, can't parse max-age seconds: " + s); - } - - Integer maxAge = Integer.parseInt(matcher.group(1)); - setValue(maxAge); - } - - public String getString() { - return "max-age="+getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/NTEventHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/NTEventHeader.java deleted file mode 100644 index 65c733a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/NTEventHeader.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import java.util.Locale; - -/** - * @author Christian Bauer - */ -public class NTEventHeader extends UpnpHeader { - - public NTEventHeader() { - setValue("upnp:event"); - } - - public void setString(String s) throws InvalidHeaderException { - if (!s.toLowerCase(Locale.ROOT).equals(getValue())) { - throw new InvalidHeaderException("Invalid event NT header value: " + s); - } - } - - public String getString() { - return getValue(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/NTSHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/NTSHeader.java deleted file mode 100644 index 01437f6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/NTSHeader.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.NotificationSubtype; - -/** - * @author Christian Bauer - */ -public class NTSHeader extends UpnpHeader { - - public NTSHeader() { - } - - public NTSHeader(NotificationSubtype type) { - setValue(type); - } - - public void setString(String s) throws InvalidHeaderException { - for (NotificationSubtype type : NotificationSubtype.values()) { - if (s.equals(type.getHeaderString())) { - setValue(type); - break; - } - } - if (getValue() == null) { - throw new InvalidHeaderException("Invalid NTS header value: " + s); - } - - } - - public String getString() { - return getValue().getHeaderString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/PragmaHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/PragmaHeader.java deleted file mode 100644 index b8daa0c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/PragmaHeader.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.model.types.PragmaType; - -/** - * - * @author Christian Bauer - * @author Mario Franco - */ -public class PragmaHeader extends UpnpHeader { - - public PragmaHeader() { - } - - public PragmaHeader(PragmaType value) { - setValue(value); - } - - public PragmaHeader(String s) { - setString(s); - } - - public void setString(String s) throws InvalidHeaderException { - try { - setValue(PragmaType.valueOf(s)); - } catch (InvalidValueException invalidValueException) { - throw new InvalidHeaderException("Invalid Range Header: " + invalidValueException.getMessage()); - } - } - - public String getString() { - return getValue().getString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/RangeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/RangeHeader.java deleted file mode 100644 index ee94e5a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/RangeHeader.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.BytesRange; -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * - * @author Christian Bauer - * @author Mario Franco - */ -public class RangeHeader extends UpnpHeader { - - public RangeHeader() { - } - - public RangeHeader(BytesRange value) { - setValue(value); - } - - public RangeHeader(String s) { - setString(s); - } - - public void setString(String s) throws InvalidHeaderException { - try { - setValue(BytesRange.valueOf(s)); - } catch (InvalidValueException invalidValueException) { - throw new InvalidHeaderException("Invalid Range Header: " + invalidValueException.getMessage()); - } - } - - public String getString() { - return getValue().getString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/RootDeviceHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/RootDeviceHeader.java deleted file mode 100644 index 8e5a9ff..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/RootDeviceHeader.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import java.util.Locale; - -/** - * @author Christian Bauer - */ -public class RootDeviceHeader extends UpnpHeader { - - public RootDeviceHeader() { - setValue("upnp:rootdevice"); - } - - public void setString(String s) throws InvalidHeaderException { - if (!s.toLowerCase(Locale.ROOT).equals(getValue())) { - throw new InvalidHeaderException("Invalid root device NT header value: " + s); - } - } - - public String getString() { - return getValue(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/STAllHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/STAllHeader.java deleted file mode 100644 index 99614d4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/STAllHeader.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.NotificationSubtype; - -/** - * @author Christian Bauer - */ -public class STAllHeader extends UpnpHeader { - - public STAllHeader() { - setValue(NotificationSubtype.ALL); - } - - public void setString(String s) throws InvalidHeaderException { - if (!s.equals(NotificationSubtype.ALL.getHeaderString())) { - throw new InvalidHeaderException("Invalid ST header value (not "+NotificationSubtype.ALL+"): " + s); - } - } - - public String getString() { - return getValue().getHeaderString(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServerHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServerHeader.java deleted file mode 100644 index 519b5ce..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServerHeader.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.ServerClientTokens; - -/** - * @author Christian Bauer - */ -public class ServerHeader extends UpnpHeader { - - public ServerHeader() { - setValue(new ServerClientTokens()); - } - - public ServerHeader(ServerClientTokens tokens) { - setValue(tokens); - } - - public void setString(String s) throws InvalidHeaderException { - // TODO: This parsing is not as robust as I'd like, probably should use regexs instead - - // UDA 1.1/1.0 section 1.2.2 and RfC 2616, section 14.38 - // OSNAME/OSVERSION UPnP/1.x PRODUCTNAME/PRODUCTVERSION - ServerClientTokens serverClientTokens = new ServerClientTokens(); - - // They are all UNKNOWN at this point - serverClientTokens.setOsName(ServerClientTokens.UNKNOWN_PLACEHOLDER); - serverClientTokens.setOsVersion(ServerClientTokens.UNKNOWN_PLACEHOLDER); - serverClientTokens.setProductName(ServerClientTokens.UNKNOWN_PLACEHOLDER); - serverClientTokens.setProductVersion(ServerClientTokens.UNKNOWN_PLACEHOLDER); - - // We definitely need a UPnP product token - if (s.contains("UPnP/1.1")) { - serverClientTokens.setMinorVersion(1); - } else if (!s.contains("UPnP/1.")) { - throw new InvalidHeaderException("Missing 'UPnP/1.' in server information: " + s); - } - - // We might be lucky and the vendor has implemented other tokens correctly. so let's at least try - try { - - int numberOfSpaces = 0; - for( int i = 0; i < s.length(); i++ ) { - if( s.charAt(i) == ' ' ) numberOfSpaces++; - } - - String[] osNameVersion; - String[] productNameVersion; - - if (s.contains(",")) { - - // Some guys think that the tokens are separated with commas, not whitespace (read section 3.8 of the HTTP spec!) - String[] productTokens = s.split(","); - osNameVersion = productTokens[0].split("/"); - productNameVersion = productTokens[2].split("/"); - - } else if (numberOfSpaces > 2) { - - // Some guys think that whitespace in token names is OK... it's not ... but let's try... - String beforeUpnpToken = s.substring(0, s.indexOf("UPnP/1.")).trim(); - String afterUpnpToken = s.substring(s.indexOf("UPnP/1.")+8).trim(); // Assumes minor version is 0-9! - osNameVersion = beforeUpnpToken.split("/"); - productNameVersion = afterUpnpToken.split("/"); - - } else { - - // Finally, how it is supposed to be, according to UPnP UDA 1.1 (not 1.0 and not HTTP spec!) - String[] productTokens = s.split(" "); - osNameVersion = productTokens[0].split("/"); - productNameVersion = productTokens[2].split("/"); - } - - - serverClientTokens.setOsName(osNameVersion[0].trim()); - if (osNameVersion.length > 1) { - serverClientTokens.setOsVersion(osNameVersion[1].trim()); - } - serverClientTokens.setProductName(productNameVersion[0].trim()); - if (productNameVersion.length > 1) { - serverClientTokens.setProductVersion(productNameVersion[1].trim()); - } - - } catch (Exception ex) { - - // If something goes wrong, go back to defaults - serverClientTokens.setOsName(ServerClientTokens.UNKNOWN_PLACEHOLDER); - serverClientTokens.setOsVersion(ServerClientTokens.UNKNOWN_PLACEHOLDER); - serverClientTokens.setProductName(ServerClientTokens.UNKNOWN_PLACEHOLDER); - serverClientTokens.setProductVersion(ServerClientTokens.UNKNOWN_PLACEHOLDER); - - - /* These are the rules: - - Many HTTP/1.1 header field values consist of words separated by LWS or special characters. These special - characters MUST be in a quoted string to be used within a parameter value (as defined in section 3.6). - - token = 1* - separators = "(" | ")" | "<" | ">" | "@" - | "," | ";" | ":" | "\" | <"> - | "/" | "[" | "]" | "?" | "=" - | "{" | "}" | SP | HT - */ - } - - setValue(serverClientTokens); - } - - public String getString() { - return getValue().getHttpToken(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServiceTypeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServiceTypeHeader.java deleted file mode 100644 index 15d1849..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServiceTypeHeader.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.ServiceType; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class ServiceTypeHeader extends UpnpHeader { - - public ServiceTypeHeader() { - } - - public ServiceTypeHeader(URI uri) { - setString(uri.toString()); - } - - public ServiceTypeHeader(ServiceType value) { - setValue(value); - } - - public void setString(String s) throws InvalidHeaderException { - try { - setValue(ServiceType.valueOf(s)); - } catch (RuntimeException ex) { - throw new InvalidHeaderException("Invalid service type header value, " + ex.getMessage()); - } - } - - public String getString() { - return getValue().toString(); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServiceUSNHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServiceUSNHeader.java deleted file mode 100644 index 64a7244..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/ServiceUSNHeader.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.NamedServiceType; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; - -/** - * @author Christian Bauer - */ -public class ServiceUSNHeader extends UpnpHeader { - - public ServiceUSNHeader() { - } - - public ServiceUSNHeader(UDN udn, ServiceType serviceType) { - setValue(new NamedServiceType(udn, serviceType)); - } - - public ServiceUSNHeader(NamedServiceType value) { - setValue(value); - } - - public void setString(String s) throws InvalidHeaderException { - try { - setValue(NamedServiceType.valueOf(s)); - } catch (Exception ex) { - throw new InvalidHeaderException("Invalid service USN header value, " + ex.getMessage()); - } - } - - public String getString() { - return getValue().toString(); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/SoapActionHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/SoapActionHeader.java deleted file mode 100644 index 4ab8aba..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/SoapActionHeader.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.SoapActionType; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class SoapActionHeader extends UpnpHeader { - - public SoapActionHeader() { - } - - public SoapActionHeader(URI uri) { - setValue(SoapActionType.valueOf(uri.toString())); - } - - public SoapActionHeader(SoapActionType value) { - setValue(value); - } - - public SoapActionHeader(String s) throws InvalidHeaderException { - setString(s); - } - - public void setString(String s) throws InvalidHeaderException { - try { - if (!s.startsWith("\"") && s.endsWith("\"")) { - throw new InvalidHeaderException("Invalid SOAP action header, must be enclosed in doublequotes:" + s); - } - - SoapActionType t = SoapActionType.valueOf(s.substring(1, s.length()-1)); - setValue(t); - } catch (RuntimeException ex) { - throw new InvalidHeaderException("Invalid SOAP action header value, " + ex.getMessage()); - } - } - - public String getString() { - return "\"" + getValue().toString() + "\""; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/SubscriptionIdHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/SubscriptionIdHeader.java deleted file mode 100644 index 3481e35..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/SubscriptionIdHeader.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -/** - * @author Christian Bauer - */ -public class SubscriptionIdHeader extends UpnpHeader { - - public static final String PREFIX = "uuid:"; - - public SubscriptionIdHeader() { - } - - public SubscriptionIdHeader(String value) { - setValue(value); - } - - public void setString(String s) throws InvalidHeaderException { - if (!s.startsWith(PREFIX)) { - throw new InvalidHeaderException("Invalid subscription ID header value, must start with '"+PREFIX+"': " + s); - } - setValue(s); - } - - public String getString() { - return getValue(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/TimeoutHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/TimeoutHeader.java deleted file mode 100644 index 1d144ae..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/TimeoutHeader.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.UserConstants; - -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -/** - * @author Christian Bauer - */ -public class TimeoutHeader extends UpnpHeader { - - // It's probably OK to assume that "infinite" means 4000 years? - public static final Integer INFINITE_VALUE = Integer.MAX_VALUE; - - public static final Pattern PATTERN = Pattern.compile("Second-(?:([0-9]+)|infinite)"); - - /** - * Defaults to {@link org.fourthline.cling.model.UserConstants#DEFAULT_SUBSCRIPTION_DURATION_SECONDS}. - */ - public TimeoutHeader() { - setValue(UserConstants.DEFAULT_SUBSCRIPTION_DURATION_SECONDS); - } - - public TimeoutHeader(int timeoutSeconds) { - setValue(timeoutSeconds); - } - - public TimeoutHeader(Integer timeoutSeconds) { - setValue(timeoutSeconds); - } - - public void setString(String s) throws InvalidHeaderException { - - Matcher matcher = PATTERN.matcher(s); - if (!matcher.matches()) { - throw new InvalidHeaderException("Can't parse timeout seconds integer from: " + s); - } - - if (matcher.group(1) != null) { - setValue(Integer.parseInt(matcher.group(1))); - } else { - setValue(INFINITE_VALUE); - } - - } - - public String getString() { - return "Second-" + (getValue().equals(INFINITE_VALUE) ? "infinite" : getValue()); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDADeviceTypeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDADeviceTypeHeader.java deleted file mode 100644 index 606c266..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDADeviceTypeHeader.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.UDADeviceType; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class UDADeviceTypeHeader extends DeviceTypeHeader { - - public UDADeviceTypeHeader() { - } - - public UDADeviceTypeHeader(URI uri) { - super(uri); - } - - public UDADeviceTypeHeader(DeviceType value) { - super(value); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - try { - setValue(UDADeviceType.valueOf(s)); - } catch (Exception ex) { - throw new InvalidHeaderException("Invalid UDA device type header value, " + ex.getMessage()); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDAServiceTypeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDAServiceTypeHeader.java deleted file mode 100644 index 24ab543..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDAServiceTypeHeader.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.UDAServiceType; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class UDAServiceTypeHeader extends ServiceTypeHeader { - - public UDAServiceTypeHeader() { - } - - public UDAServiceTypeHeader(URI uri) { - super(uri); - } - - public UDAServiceTypeHeader(UDAServiceType value) { - super(value); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - try { - setValue(UDAServiceType.valueOf(s)); - } catch (Exception ex) { - throw new InvalidHeaderException("Invalid UDA service type header value, " + ex.getMessage()); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDNHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDNHeader.java deleted file mode 100644 index 1382827..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UDNHeader.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.UDN; - -/** - * @author Christian Bauer - */ -public class UDNHeader extends UpnpHeader { - - public UDNHeader() { - } - - public UDNHeader(UDN udn) { - setValue(udn); - } - - public void setString(String s) throws InvalidHeaderException { - if (!s.startsWith(UDN.PREFIX)) { - throw new InvalidHeaderException("Invalid UDA header value, must start with '"+UDN.PREFIX+"': " + s); - } - - if (s.contains("::urn")) { - throw new InvalidHeaderException("Invalid UDA header value, must not contain '::urn': " + s); - } - - UDN udn = new UDN( s.substring(UDN.PREFIX.length()) ); - setValue(udn); - } - - public String getString() { - return getValue().toString(); - } -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/USNRootDeviceHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/USNRootDeviceHeader.java deleted file mode 100644 index 808515c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/USNRootDeviceHeader.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.fourthline.cling.model.types.UDN; - -/** - * @author Christian Bauer - */ -public class USNRootDeviceHeader extends UpnpHeader { - - public static final String ROOT_DEVICE_SUFFIX = "::upnp:rootdevice"; - - public USNRootDeviceHeader() { - } - - public USNRootDeviceHeader(UDN udn) { - setValue(udn); - } - - public void setString(String s) throws InvalidHeaderException { - if (!s.startsWith(UDN.PREFIX) || !s.endsWith(ROOT_DEVICE_SUFFIX)) { - throw new InvalidHeaderException( - "Invalid root device USN header value, must start with '" + - UDN.PREFIX + "' and end with '" + - ROOT_DEVICE_SUFFIX + "' but is '" + s + "'" - ); - } - UDN udn = new UDN(s.substring(UDN.PREFIX.length(), s.length() - ROOT_DEVICE_SUFFIX.length())); - setValue(udn); - } - - public String getString() { - return getValue().toString() + ROOT_DEVICE_SUFFIX; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UpnpHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UpnpHeader.java deleted file mode 100644 index d98d234..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UpnpHeader.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -import org.seamless.util.Exceptions; - -import java.util.HashMap; -import java.util.Map; -import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Transforms known and standardized UPnP/HTTP headers from/to string representation. - *

- * The {@link #newInstance(org.fourthline.cling.model.message.header.UpnpHeader.Type, String)} method - * attempts to instantiate the best header subtype for a given header (name) and string value. - *

- * - * @author Christian Bauer - */ -public abstract class UpnpHeader { - - final private static Logger log = Logger.getLogger(UpnpHeader.class.getName()); - - /** - * Maps a standardized UPnP header to potential header subtypes. - */ - public static enum Type { - - USN("USN", - USNRootDeviceHeader.class, - DeviceUSNHeader.class, - ServiceUSNHeader.class, - UDNHeader.class - ), - NT("NT", - RootDeviceHeader.class, - UDADeviceTypeHeader.class, - UDAServiceTypeHeader.class, - DeviceTypeHeader.class, - ServiceTypeHeader.class, - UDNHeader.class, - NTEventHeader.class - ), - NTS("NTS", NTSHeader.class), - HOST("HOST", HostHeader.class), - SERVER("SERVER", ServerHeader.class), - LOCATION("LOCATION", LocationHeader.class), - MAX_AGE("CACHE-CONTROL", MaxAgeHeader.class), - USER_AGENT("USER-AGENT", UserAgentHeader.class), - CONTENT_TYPE("CONTENT-TYPE", ContentTypeHeader.class), - MAN("MAN", MANHeader.class), - MX("MX", MXHeader.class), - ST("ST", - STAllHeader.class, - RootDeviceHeader.class, - UDADeviceTypeHeader.class, - UDAServiceTypeHeader.class, - DeviceTypeHeader.class, - ServiceTypeHeader.class, - UDNHeader.class - ), - EXT("EXT", EXTHeader.class), - SOAPACTION("SOAPACTION", SoapActionHeader.class), - TIMEOUT("TIMEOUT", TimeoutHeader.class), - CALLBACK("CALLBACK", CallbackHeader.class), - SID("SID", SubscriptionIdHeader.class), - SEQ("SEQ", EventSequenceHeader.class), - RANGE("RANGE", RangeHeader.class), - CONTENT_RANGE("CONTENT-RANGE", ContentRangeHeader.class), - PRAGMA("PRAGMA", PragmaHeader.class), - - EXT_IFACE_MAC("X-CLING-IFACE-MAC", InterfaceMacHeader.class), - EXT_AV_CLIENT_INFO("X-AV-CLIENT-INFO", AVClientInfoHeader.class); - - private static Map byName = new HashMap() {{ - for (Type t : Type.values()) { - put(t.getHttpName(), t); - } - }}; - - private String httpName; - private Class[] headerTypes; - - @SafeVarargs - private Type(String httpName, Class... headerClass) { - this.httpName = httpName; - this.headerTypes = headerClass; - } - - public String getHttpName() { - return httpName; - } - - public Class[] getHeaderTypes() { - return headerTypes; - } - - public boolean isValidHeaderType(Class clazz) { - for (Class permissibleType : getHeaderTypes()) { - if (permissibleType.isAssignableFrom(clazz)) { - return true; - } - } - return false; - } - - /** - * @param httpName A case-insensitive HTTP header name. - */ - public static Type getByHttpName(String httpName) { - if (httpName == null) return null; - return byName.get(httpName.toUpperCase(Locale.ROOT)); - } - } - - private T value; - - public void setValue(T value) { - this.value = value; - } - - public T getValue() { - return value; - } - - /** - * @param s This header's value as a string representation. - * @throws InvalidHeaderException If the value is invalid for this UPnP header. - */ - public abstract void setString(String s) throws InvalidHeaderException; - - /** - * @return A string representing this header's value. - */ - public abstract String getString(); - - /** - * Create a new instance of a {@link UpnpHeader} subtype that matches the given type and value. - *

- * This method iterates through all potential header subtype classes as declared in {@link Type}. - * It creates a new instance of the subtype class and calls its {@link #setString(String)} method. - * If no {@link org.fourthline.cling.model.message.header.InvalidHeaderException} is thrown, the subtype - * instance is returned. - *

- * - * @param type The type (or name) of the header. - * @param headerValue The value of the header. - * @return The best matching header subtype instance, or null if no subtype can be found. - */ - public static UpnpHeader newInstance(UpnpHeader.Type type, String headerValue) { - - // Try all the UPnP headers and see if one matches our value parsers - UpnpHeader upnpHeader = null; - for (int i = 0; i < type.getHeaderTypes().length && upnpHeader == null; i++) { - Class headerClass = type.getHeaderTypes()[i]; - try { - log.finest("Trying to parse '" + type + "' with class: " + headerClass.getSimpleName()); - upnpHeader = headerClass.newInstance(); - if (headerValue != null) { - upnpHeader.setString(headerValue); - } - } catch (InvalidHeaderException ex) { - log.finest("Invalid header value for tested type: " + headerClass.getSimpleName() + " - " + ex.getMessage()); - upnpHeader = null; - } catch (Exception ex) { - log.severe("Error instantiating header of type '" + type + "' with value: " + headerValue); - log.log(Level.SEVERE, "Exception root cause: ", Exceptions.unwrap(ex)); - } - - } - return upnpHeader; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") '" + getValue() + "'"; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UserAgentHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UserAgentHeader.java deleted file mode 100644 index a419967..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/message/header/UserAgentHeader.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.message.header; - -/** - * A simple string, not validated (everyone gets this wrong) - * - * @author Christian Bauer - * @author Michael Pujos - */ -public class UserAgentHeader extends UpnpHeader { - - public UserAgentHeader() { - } - - public UserAgentHeader(String s) { - setValue(s); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - setValue(s); - } - - @Override - public String getString() { - return getValue(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Action.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Action.java deleted file mode 100644 index 79f12fe..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Action.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.Validatable; -import org.fourthline.cling.model.ValidationError; - -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -/** - * Describes an action and its input/output arguments. - * - * @author Christian Bauer - */ -public class Action implements Validatable { - - final private static Logger log = Logger.getLogger(Action.class.getName()); - - final private String name; - final private ActionArgument[] arguments; - final private ActionArgument[] inputArguments; - final private ActionArgument[] outputArguments; - - // Package mutable state - private S service; - - public Action(String name, ActionArgument[] arguments) { - this.name = name; - if (arguments != null) { - - List inputList= new ArrayList<>(); - List outputList = new ArrayList<>(); - - for (ActionArgument argument : arguments) { - argument.setAction(this); - if (argument.getDirection().equals(ActionArgument.Direction.IN)) - inputList.add(argument); - if (argument.getDirection().equals(ActionArgument.Direction.OUT)) - outputList.add(argument); - } - - this.arguments = arguments; - this.inputArguments = inputList.toArray(new ActionArgument[inputList.size()]); - this.outputArguments = outputList.toArray(new ActionArgument[outputList.size()]); - } else { - this.arguments = new ActionArgument[0]; - this.inputArguments = new ActionArgument[0]; - this.outputArguments = new ActionArgument[0]; - } - } - - public String getName() { - return name; - } - - public boolean hasArguments() { - return getArguments() != null && getArguments().length > 0; - } - - public ActionArgument[] getArguments() { - return arguments; - } - - public S getService() { - return service; - } - - void setService(S service) { - if (this.service != null) - throw new IllegalStateException("Final value has been set already, model is immutable"); - this.service = service; - } - - public ActionArgument getFirstInputArgument() { - if (!hasInputArguments()) throw new IllegalStateException("No input arguments: " + this); - return getInputArguments()[0]; - } - - public ActionArgument getFirstOutputArgument() { - if (!hasOutputArguments()) throw new IllegalStateException("No output arguments: " + this); - return getOutputArguments()[0]; - } - - public ActionArgument[] getInputArguments() { - return inputArguments; - } - - public ActionArgument getInputArgument(String name) { - for (ActionArgument arg : getInputArguments()) { - if (arg.isNameOrAlias(name)) return arg; - } - return null; - } - - public ActionArgument[] getOutputArguments() { - return outputArguments; - } - - public ActionArgument getOutputArgument(String name) { - for (ActionArgument arg : getOutputArguments()) { - if (arg.getName().equals(name)) return arg; - } - return null; - } - - public boolean hasInputArguments() { - return getInputArguments() != null && getInputArguments().length > 0; - } - - public boolean hasOutputArguments() { - return getOutputArguments() != null && getOutputArguments().length > 0; - } - - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + - ", Arguments: " + (getArguments() != null ? getArguments().length : "NO ARGS") + - ") " + getName(); - } - - public List validate() { - List errors = new ArrayList<>(); - - if (getName() == null || getName().length() == 0) { - errors.add(new ValidationError( - getClass(), - "name", - "Action without name of: " + getService() - )); - } else if (!ModelUtil.isValidUDAName(getName())) { - log.warning("UPnP specification violation of: " + getService().getDevice()); - log.warning("Invalid action name: " + this); - } - - for (ActionArgument actionArgument : getArguments()) { - // Check argument relatedStateVariable in service state table - - if (getService().getStateVariable(actionArgument.getRelatedStateVariableName()) == null) { - errors.add(new ValidationError( - getClass(), - "arguments", - "Action argument references an unknown state variable: " + actionArgument.getRelatedStateVariableName() - )); - } - } - - ActionArgument retValueArgument = null; - int retValueArgumentIndex = 0; - int i = 0; - for (ActionArgument actionArgument : getArguments()) { - // Check retval - if (actionArgument.isReturnValue()) { - if (actionArgument.getDirection() == ActionArgument.Direction.IN) { - log.warning("UPnP specification violation of :" + getService().getDevice()); - log.warning("Input argument can not have "); - } else { - if (retValueArgument != null) { - log.warning("UPnP specification violation of: " + getService().getDevice()); - log.warning("Only one argument of action '" + getName() + "' can be "); - } - retValueArgument = actionArgument; - retValueArgumentIndex = i; - } - } - i++; - } - if (retValueArgument != null) { - for (int j = 0; j < retValueArgumentIndex; j++) { - ActionArgument a = getArguments()[j]; - if (a.getDirection() == ActionArgument.Direction.OUT) { - log.warning("UPnP specification violation of: " + getService().getDevice()); - log.warning("Argument '" + retValueArgument.getName() + "' of action '" + getName() + "' is but not the first OUT argument"); - } - } - } - - for (ActionArgument argument : arguments) { - errors.addAll(argument.validate()); - } - - return errors; - } - - public Action deepCopy() { - ActionArgument[] actionArgumentsDupe = new ActionArgument[getArguments().length]; - for (int i = 0; i < getArguments().length; i++) { - ActionArgument arg = getArguments()[i]; - actionArgumentsDupe[i] = arg.deepCopy(); - } - - return new Action<>( - getName(), - actionArgumentsDupe - ); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/ActionArgument.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/ActionArgument.java deleted file mode 100644 index a6eb7ea..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/ActionArgument.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import org.fourthline.cling.model.Validatable; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.ModelUtil; - -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -/** - * Describes a single action argument, either input or output. - *

- * No, I haven't figured out so far what the "return value" thingy is good for. - *

- * - * @author Christian Bauer - */ -public class ActionArgument implements Validatable { - - final private static Logger log = Logger.getLogger(ActionArgument.class.getName()); - - public enum Direction { - IN, OUT - } - - final private String name; - final private String[] aliases; - final private String relatedStateVariableName; - final private Direction direction; - final private boolean returnValue; // TODO: What is this stuff good for anyway? - - // Package mutable state - private Action action; - - public ActionArgument(String name, String relatedStateVariableName, Direction direction) { - this(name, new String[0], relatedStateVariableName, direction, false); - } - - public ActionArgument(String name, String[] aliases, String relatedStateVariableName, Direction direction) { - this(name, aliases, relatedStateVariableName, direction, false); - } - - public ActionArgument(String name, String relatedStateVariableName, Direction direction, boolean returnValue) { - this(name, new String[0], relatedStateVariableName, direction, returnValue); - } - - public ActionArgument(String name, String[] aliases, String relatedStateVariableName, Direction direction, boolean returnValue) { - this.name = name; - this.aliases = aliases; - this.relatedStateVariableName = relatedStateVariableName; - this.direction = direction; - this.returnValue = returnValue; - } - - public String getName() { - return name; - } - - public String[] getAliases() { - return aliases; - } - - public boolean isNameOrAlias(String name) { - if (getName().equalsIgnoreCase(name)) return true; - for (String alias : aliases) { - if (alias.equalsIgnoreCase(name)) return true; - } - return false; - } - - public String getRelatedStateVariableName() { - return relatedStateVariableName; - } - - public Direction getDirection() { - return direction; - } - - public boolean isReturnValue() { - return returnValue; - } - - public Action getAction() { - return action; - } - - void setAction(Action action) { - if (this.action != null) - throw new IllegalStateException("Final value has been set already, model is immutable"); - this.action = action; - } - - public Datatype getDatatype() { - return getAction().getService().getDatatype(this); - } - - public List validate() { - List errors = new ArrayList<>(); - - if (getName() == null || getName().length() == 0) { - errors.add(new ValidationError( - getClass(), - "name", - "Argument without name of: " + getAction() - )); - } else if (!ModelUtil.isValidUDAName(getName())) { - log.warning("UPnP specification violation of: " + getAction().getService().getDevice()); - log.warning("Invalid argument name: " + this); - } else if (getName().length() > 32) { - log.warning("UPnP specification violation of: " + getAction().getService().getDevice()); - log.warning("Argument name should be less than 32 characters: " + this); - } - - if (getDirection() == null) { - errors.add(new ValidationError( - getClass(), - "direction", - "Argument '"+getName()+"' requires a direction, either IN or OUT" - )); - } - - if (isReturnValue() && getDirection() != ActionArgument.Direction.OUT) { - errors.add(new ValidationError( - getClass(), - "direction", - "Return value argument '" + getName() + "' must be direction OUT" - )); - } - - return errors; - } - - public ActionArgument deepCopy() { - return new ActionArgument<>( - getName(), - getAliases(), - getRelatedStateVariableName(), - getDirection(), - isReturnValue() - ); - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ", " + getDirection() + ") " + getName(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Device.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Device.java deleted file mode 100644 index 60df0e0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Device.java +++ /dev/null @@ -1,452 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.profile.RemoteClientInfo; -import org.fourthline.cling.model.resource.Resource; -import org.fourthline.cling.model.Validatable; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Describes either a root or embedded device. - * - * @author Christian Bauer - */ -public abstract class Device implements Validatable { - - final private static Logger log = Logger.getLogger(Device.class.getName()); - - final private DI identity; - - final private UDAVersion version; - final private DeviceType type; - final private DeviceDetails details; - final private Icon[] icons; - final protected S[] services; - final protected D[] embeddedDevices; - - // Package mutable state - private D parentDevice; - - public Device(DI identity) throws ValidationException { - this(identity, null, null, null, null, null); - } - - public Device(DI identity, DeviceType type, DeviceDetails details, - Icon[] icons, S[] services) throws ValidationException { - this(identity, null, type, details, icons, services, null); - } - - public Device(DI identity, DeviceType type, DeviceDetails details, - Icon[] icons, S[] services, D[] embeddedDevices) throws ValidationException { - this(identity, null, type, details, icons, services, embeddedDevices); - } - - public Device(DI identity, UDAVersion version, DeviceType type, DeviceDetails details, - Icon[] icons, S[] services, D[] embeddedDevices) throws ValidationException { - - this.identity = identity; - this.version = version == null ? new UDAVersion() : version; - this.type = type; - this.details = details; - - // We don't fail device validation if icons were invalid, only log a warning. To - // comply with mutability rules (can't set icons field in validate() method), we - // validate the icons here before we set the field value - List validIcons = new ArrayList<>(); - if (icons != null) { - for (Icon icon : icons) { - if (icon != null) { - icon.setDevice(this); // Set before validate()! - List iconErrors = icon.validate(); - if(iconErrors.isEmpty()) { - validIcons.add(icon); - } else { - log.warning("Discarding invalid '" + icon + "': " + iconErrors); - } - } - } - } - this.icons = validIcons.toArray(new Icon[validIcons.size()]); - - boolean allNullServices = true; - if (services != null) { - for (S service : services) { - if (service != null) { - allNullServices = false; - service.setDevice(this); - } - } - } - this.services = services == null || allNullServices ? null : services; - - boolean allNullEmbedded = true; - if (embeddedDevices != null) { - for (D embeddedDevice : embeddedDevices) { - if (embeddedDevice != null) { - allNullEmbedded = false; - embeddedDevice.setParentDevice(this); - } - } - } - this.embeddedDevices = embeddedDevices == null || allNullEmbedded ? null : embeddedDevices; - - List errors = validate(); - if (errors.size() > 0) { - if (log.isLoggable(Level.FINEST)) { - for (ValidationError error : errors) { - log.finest(error.toString()); - } - } - throw new ValidationException("Validation of device graph failed, call getErrors() on exception", errors); - } - } - - public DI getIdentity() { - return identity; - } - - public UDAVersion getVersion() { - return version; - } - - public DeviceType getType() { - return type; - } - - public DeviceDetails getDetails() { - return details; - } - - public DeviceDetails getDetails(RemoteClientInfo info) { - return this.getDetails(); - } - - public Icon[] getIcons() { - return icons; - } - - public boolean hasIcons() { - return getIcons() != null && getIcons().length > 0; - } - - public boolean hasServices() { - return getServices() != null && getServices().length > 0; - } - - - public boolean hasEmbeddedDevices() { - return getEmbeddedDevices() != null && getEmbeddedDevices().length > 0; - } - - public D getParentDevice() { - return parentDevice; - } - - void setParentDevice(D parentDevice) { - if (this.parentDevice != null) - throw new IllegalStateException("Final value has been set already, model is immutable"); - this.parentDevice = parentDevice; - } - - public boolean isRoot() { - return getParentDevice() == null; - } - - public abstract S[] getServices(); - - public abstract D[] getEmbeddedDevices(); - - public abstract D getRoot(); - - public abstract D findDevice(UDN udn); - - public D[] findEmbeddedDevices() { - return toDeviceArray(findEmbeddedDevices((D) this)); - } - - public D[] findDevices(DeviceType deviceType) { - return toDeviceArray(find(deviceType, (D) this)); - } - - public D[] findDevices(ServiceType serviceType) { - return toDeviceArray(find(serviceType, (D) this)); - } - - public Icon[] findIcons() { - List icons = new ArrayList<>(); - if (hasIcons()) { - icons.addAll(Arrays.asList(getIcons())); - } - D[] embeddedDevices = findEmbeddedDevices(); - for (D embeddedDevice : embeddedDevices) { - if (embeddedDevice.hasIcons()) { - icons.addAll(Arrays.asList(embeddedDevice.getIcons())); - } - } - return icons.toArray(new Icon[icons.size()]); - } - - public S[] findServices() { - return toServiceArray(findServices(null, null, (D) this)); - } - - public S[] findServices(ServiceType serviceType) { - return toServiceArray(findServices(serviceType, null, (D) this)); - } - - protected D find(UDN udn, D current) { - if (current.getIdentity() != null && current.getIdentity().getUdn() != null) { - if (current.getIdentity().getUdn().equals(udn)) return current; - } - if (current.hasEmbeddedDevices()) { - for (D embeddedDevice : (D[]) current.getEmbeddedDevices()) { - D match; - if ((match = find(udn, embeddedDevice)) != null) return match; - } - } - return null; - } - - protected Collection findEmbeddedDevices(D current) { - Collection devices = new HashSet<>(); - if (!current.isRoot() && current.getIdentity().getUdn() != null) - devices.add(current); - - if (current.hasEmbeddedDevices()) { - for (D embeddedDevice : (D[]) current.getEmbeddedDevices()) { - devices.addAll(findEmbeddedDevices(embeddedDevice)); - } - } - return devices; - } - - protected Collection find(DeviceType deviceType, D current) { - Collection devices = new HashSet<>(); - // Type might be null if we just discovered the device and it hasn't yet been hydrated - if (current.getType() != null && current.getType().implementsVersion(deviceType)) { - devices.add(current); - } - if (current.hasEmbeddedDevices()) { - for (D embeddedDevice : (D[]) current.getEmbeddedDevices()) { - devices.addAll(find(deviceType, embeddedDevice)); - } - } - return devices; - } - - protected Collection find(ServiceType serviceType, D current) { - Collection services = findServices(serviceType, null, current); - Collection devices = new HashSet<>(); - for (Service service : services) { - devices.add((D) service.getDevice()); - } - return devices; - } - - protected Collection findServices(ServiceType serviceType, ServiceId serviceId, D current) { - Collection services = new HashSet<>(); - if (current.hasServices()) { - for (Service service : current.getServices()) { - if (isMatch(service, serviceType, serviceId)) - services.add(service); - } - } - Collection embeddedDevices = findEmbeddedDevices(current); - if (embeddedDevices != null) { - for (D embeddedDevice : embeddedDevices) { - if (embeddedDevice.hasServices()) { - for (Service service : embeddedDevice.getServices()) { - if (isMatch(service, serviceType, serviceId)) - services.add(service); - } - } - } - } - return services; - } - - public S findService(ServiceId serviceId) { - Collection services = findServices(null, serviceId, (D) this); - return services.size() == 1 ? services.iterator().next() : null; - } - - public S findService(ServiceType serviceType) { - Collection services = findServices(serviceType, null, (D) this); - return services.size() > 0 ? services.iterator().next() : null; - } - - public ServiceType[] findServiceTypes() { - Collection services = findServices(null, null, (D) this); - Collection col = new HashSet<>(); - for (S service : services) { - col.add(service.getServiceType()); - } - return col.toArray(new ServiceType[col.size()]); - } - - private boolean isMatch(Service s, ServiceType serviceType, ServiceId serviceId) { - boolean matchesType = serviceType == null || s.getServiceType().implementsVersion(serviceType); - boolean matchesId = serviceId == null || s.getServiceId().equals(serviceId); - return matchesType && matchesId; - } - - public boolean isFullyHydrated() { - S[] services = findServices(); - for (S service : services) { - if (service.hasStateVariables()) return true; - } - return false; - } - - public String getDisplayString() { - - // The goal is to have a clean string with " " - - String cleanModelName = null; - String cleanModelNumber = null; - - if (getDetails() != null && getDetails().getModelDetails() != null) { - - // Some vendors end the model name with the model number, let's remove that - ModelDetails modelDetails = getDetails().getModelDetails(); - if (modelDetails.getModelName() != null) { - cleanModelName = modelDetails.getModelNumber() != null && modelDetails.getModelName().endsWith(modelDetails.getModelNumber()) - ? modelDetails.getModelName().substring(0, modelDetails.getModelName().length() - modelDetails.getModelNumber().length()) - : modelDetails.getModelName(); - } - - // Some vendors repeat the model name as the model number, no good - if (cleanModelName != null) { - cleanModelNumber = modelDetails.getModelNumber() != null && !cleanModelName.startsWith(modelDetails.getModelNumber()) - ? modelDetails.getModelNumber() - : ""; - } else { - cleanModelNumber = modelDetails.getModelNumber(); - } - } - - StringBuilder sb = new StringBuilder(); - - if (getDetails() != null && getDetails().getManufacturerDetails() != null) { - - // Some vendors repeat the manufacturer in model name, let's remove that too - if (cleanModelName != null && getDetails().getManufacturerDetails().getManufacturer() != null) { - cleanModelName = cleanModelName.startsWith(getDetails().getManufacturerDetails().getManufacturer()) - ? cleanModelName.substring(getDetails().getManufacturerDetails().getManufacturer().length()).trim() - : cleanModelName.trim(); - } - - if (getDetails().getManufacturerDetails().getManufacturer() != null) { - sb.append(getDetails().getManufacturerDetails().getManufacturer()); - } - } - - sb.append((cleanModelName != null && cleanModelName.length() > 0 ? " " + cleanModelName : "")); - sb.append((cleanModelNumber != null && cleanModelNumber.length() > 0 ? " " + cleanModelNumber.trim() : "")); - return sb.toString(); - } - - public List validate() { - List errors = new ArrayList<>(); - - if (getType() != null) { - - // Only validate the graph if we have a device type - that means we validate only if there - // actually is a fully hydrated graph, not just a discovered device of which we haven't even - // retrieved the descriptor yet. This assumes that the descriptor will ALWAYS contain a device - // type. Now that is a risky assumption... - - errors.addAll(getVersion().validate()); - - if(getIdentity() != null) { - errors.addAll(getIdentity().validate()); - } - - if (getDetails() != null) { - errors.addAll(getDetails().validate()); - } - - if (hasServices()) { - for (Service service : getServices()) { - if (service != null) - errors.addAll(service.validate()); - } - } - - if (hasEmbeddedDevices()) { - for (Device embeddedDevice : getEmbeddedDevices()) { - if (embeddedDevice != null) - errors.addAll(embeddedDevice.validate()); - } - } - } - - return errors; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Device device = (Device) o; - - if (!identity.equals(device.identity)) return false; - - return true; - } - - @Override - public int hashCode() { - return identity.hashCode(); - } - - public abstract D newInstance(UDN udn, UDAVersion version, DeviceType type, DeviceDetails details, - Icon[] icons, S[] services, List embeddedDevices) throws ValidationException; - - public abstract S newInstance(ServiceType serviceType, ServiceId serviceId, - URI descriptorURI, URI controlURI, URI eventSubscriptionURI, - Action[] actions, StateVariable[] stateVariables) throws ValidationException; - - public abstract D[] toDeviceArray(Collection col); - - public abstract S[] newServiceArray(int size); - - public abstract S[] toServiceArray(Collection col); - - public abstract Resource[] discoverResources(Namespace namespace); - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") Identity: " + getIdentity().toString() + ", Root: " + isRoot(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/DeviceDetails.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/DeviceDetails.java deleted file mode 100644 index 655fb53..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/DeviceDetails.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import org.fourthline.cling.model.Validatable; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.types.DLNACaps; -import org.fourthline.cling.model.types.DLNADoc; - -import java.net.URI; -import java.net.URL; -import java.util.List; -import java.util.ArrayList; -import java.util.logging.Logger; - -/** - * Encapsulates all optional metadata about a device. - * - * @author Christian Bauer - */ -public class DeviceDetails implements Validatable { - - final private static Logger log = Logger.getLogger(DeviceDetails.class.getName()); - - final private URL baseURL; - final private String friendlyName; - final private ManufacturerDetails manufacturerDetails; - final private ModelDetails modelDetails; - final private String serialNumber; - final private String upc; - final private URI presentationURI; - final private DLNADoc[] dlnaDocs; - final private DLNACaps dlnaCaps; - final private DLNACaps secProductCaps; - - public DeviceDetails(String friendlyName) { - this(null, friendlyName, null, null, null, null, null); - } - - public DeviceDetails(String friendlyName, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps) { - this(null, friendlyName, null, null, null, null, null, dlnaDocs, dlnaCaps); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails) { - this(null, friendlyName, manufacturerDetails, null, null, null, null); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps) { - this(null, friendlyName, manufacturerDetails, null, null, null, null, dlnaDocs, dlnaCaps); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, - ModelDetails modelDetails) { - this(null, friendlyName, manufacturerDetails, modelDetails, null, null, null); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, - ModelDetails modelDetails, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps) { - this(null, friendlyName, manufacturerDetails, modelDetails, null, null, null, dlnaDocs, dlnaCaps); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, - ModelDetails modelDetails, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps, DLNACaps secProductCaps) { - this(null, friendlyName, manufacturerDetails, modelDetails, null, null, null, dlnaDocs, dlnaCaps, secProductCaps); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, ModelDetails modelDetails, - String serialNumber, String upc) { - this(null, friendlyName, manufacturerDetails, modelDetails, serialNumber, upc, null); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, ModelDetails modelDetails, - String serialNumber, String upc, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps) { - this(null, friendlyName, manufacturerDetails, modelDetails, serialNumber, upc, null, dlnaDocs, dlnaCaps); - } - - public DeviceDetails(String friendlyName, URI presentationURI) { - this(null, friendlyName, null, null, null, null, presentationURI); - } - - public DeviceDetails(String friendlyName, URI presentationURI, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps) { - this(null, friendlyName, null, null, null, null, presentationURI, dlnaDocs, dlnaCaps); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, - ModelDetails modelDetails, URI presentationURI) { - this(null, friendlyName, manufacturerDetails, modelDetails, null, null, presentationURI); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, - ModelDetails modelDetails, URI presentationURI, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps) { - this(null, friendlyName, manufacturerDetails, modelDetails, null, null, presentationURI, dlnaDocs, dlnaCaps); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, ModelDetails modelDetails, - String serialNumber, String upc, URI presentationURI) { - this(null, friendlyName, manufacturerDetails, modelDetails, serialNumber, upc, presentationURI); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, ModelDetails modelDetails, - String serialNumber, String upc, URI presentationURI, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps) { - this(null, friendlyName, manufacturerDetails, modelDetails, serialNumber, upc, presentationURI, dlnaDocs, dlnaCaps); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, ModelDetails modelDetails, - String serialNumber, String upc, String presentationURI) - throws IllegalArgumentException { - this(null, friendlyName, manufacturerDetails, modelDetails, serialNumber, upc, URI.create(presentationURI)); - } - - public DeviceDetails(String friendlyName, ManufacturerDetails manufacturerDetails, ModelDetails modelDetails, - String serialNumber, String upc, String presentationURI, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps) - throws IllegalArgumentException { - this(null, friendlyName, manufacturerDetails, modelDetails, serialNumber, upc, URI.create(presentationURI), dlnaDocs, dlnaCaps); - } - - public DeviceDetails(URL baseURL, String friendlyName, - ManufacturerDetails manufacturerDetails, ModelDetails modelDetails, - String serialNumber, String upc, - URI presentationURI) { - this(baseURL, friendlyName, manufacturerDetails, modelDetails, serialNumber, upc, presentationURI, null, null); - } - - public DeviceDetails(URL baseURL, String friendlyName, - ManufacturerDetails manufacturerDetails, ModelDetails modelDetails, - String serialNumber, String upc, - URI presentationURI, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps) { - this(baseURL, friendlyName, manufacturerDetails, modelDetails, serialNumber, upc, presentationURI, dlnaDocs, dlnaCaps, null); - } - - public DeviceDetails(URL baseURL, String friendlyName, - ManufacturerDetails manufacturerDetails, ModelDetails modelDetails, - String serialNumber, String upc, - URI presentationURI, DLNADoc[] dlnaDocs, DLNACaps dlnaCaps, DLNACaps secProductCaps) { - this.baseURL = baseURL; - this.friendlyName = friendlyName; - this.manufacturerDetails = manufacturerDetails == null ? new ManufacturerDetails() : manufacturerDetails; - this.modelDetails = modelDetails == null ? new ModelDetails() : modelDetails; - this.serialNumber = serialNumber; - this.upc = upc; - this.presentationURI = presentationURI; - this.dlnaDocs = dlnaDocs != null ? dlnaDocs : new DLNADoc[0]; - this.dlnaCaps = dlnaCaps; - this.secProductCaps = secProductCaps; - } - - public URL getBaseURL() { - return baseURL; - } - - public String getFriendlyName() { - return friendlyName; - } - - public ManufacturerDetails getManufacturerDetails() { - return manufacturerDetails; - } - - public ModelDetails getModelDetails() { - return modelDetails; - } - - public String getSerialNumber() { - return serialNumber; - } - - public String getUpc() { - return upc; - } - - public URI getPresentationURI() { - return presentationURI; - } - - public DLNADoc[] getDlnaDocs() { - return dlnaDocs; - } - - public DLNACaps getDlnaCaps() { - return dlnaCaps; - } - - public DLNACaps getSecProductCaps() { - return secProductCaps; - } - - public List validate() { - List errors = new ArrayList<>(); - - if (getUpc() != null) { - // This is broken in more than half of the devices I've tested, so let's not even bother with a warning - if (getUpc().length() != 12) { - log.fine("UPnP specification violation, UPC must be 12 digits: " + getUpc()); - } else { - try { - Long.parseLong(getUpc()); - } catch (NumberFormatException ex) { - log.fine("UPnP specification violation, UPC must be 12 digits all-numeric: " + getUpc()); - } - } - } - - return errors; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/DeviceIdentity.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/DeviceIdentity.java deleted file mode 100644 index f2e990f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/DeviceIdentity.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import java.util.ArrayList; -import java.util.List; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.Validatable; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.types.UDN; - -/** - * Unique device name, received and offered during discovery with SSDP. - * - * @author Christian Bauer - */ -public class DeviceIdentity implements Validatable { - - final private UDN udn; - final private Integer maxAgeSeconds; - - public DeviceIdentity(UDN udn, DeviceIdentity template) { - this.udn = udn; - this.maxAgeSeconds = template.getMaxAgeSeconds(); - } - - public DeviceIdentity(UDN udn) { - this.udn = udn; - this.maxAgeSeconds = Constants.MIN_ADVERTISEMENT_AGE_SECONDS; - } - - public DeviceIdentity(UDN udn, Integer maxAgeSeconds) { - this.udn = udn; - this.maxAgeSeconds = maxAgeSeconds; - } - - public UDN getUdn() { - return udn; - } - - public Integer getMaxAgeSeconds() { - return maxAgeSeconds; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - DeviceIdentity that = (DeviceIdentity) o; - - if (!udn.equals(that.udn)) return false; - - return true; - } - - @Override - public int hashCode() { - return udn.hashCode(); - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") UDN: " + getUdn(); - } - - @Override - public List validate() { - List errors = new ArrayList<>(); - - if (getUdn() == null) { - errors.add(new ValidationError( - getClass(), - "major", - "Device has no UDN" - )); - } - - return errors; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Icon.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Icon.java deleted file mode 100644 index 8383fb6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Icon.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - - -import org.fourthline.cling.model.Validatable; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.types.BinHexDatatype; -import org.seamless.util.io.IO; -import org.seamless.util.MimeType; -import org.seamless.util.URIUtil; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -/** - * The metadata of a device icon, might include the actual image data of a local icon. - * - *

- * Note that validation of icons is lax on purpose, a valid Icon might still - * return null from {@link #getMimeType()}, {@link #getWidth()}, - * {@link #getHeight()}, and {@link #getDepth()}. However, {@link #getUri()} will return - * a valid URI for a valid Icon. - *

- * - * @author Christian Bauer - */ -public class Icon implements Validatable { - - final private static Logger log = Logger.getLogger(StateVariable.class.getName()); - - final private MimeType mimeType; - final private int width; - final private int height; - final private int depth; - final private URI uri; - final private byte[] data; - - // Package mutable state - private Device device; - - /** - * Used internally by Cling when {@link RemoteDevice} is discovered, you shouldn't have to call this. - */ - public Icon(String mimeType, int width, int height, int depth, URI uri) { - this(mimeType != null && mimeType.length() > 0 ? MimeType.valueOf(mimeType) : null, width, height, depth, uri, null); - } - - /** - * Use this constructor if your local icon data can be resolved on the classpath, for - * example: MyClass.class.getResource("/my/icon.png) - * - * @param url A URL of the icon data that can be read with new File(url.toURI()). - */ - public Icon(String mimeType, int width, int height, int depth, URL url) throws IOException{ - this(mimeType, width, height, depth, new File(URIUtil.toURI(url))); - } - - /** - * Use this constructor if your local icon data can be resolved with a File, the file's - * name must be unique within the scope of a device. - */ - public Icon(String mimeType, int width, int height, int depth, File file) throws IOException { - this(mimeType, width, height, depth, file.getName(), IO.readBytes(file)); - } - - /** - * Use this constructor if your local icon data is an InputStream. - * - * @param uniqueName Must be a valid URI path segment and unique within the scope of a device. - */ - public Icon(String mimeType, int width, int height, int depth, String uniqueName, InputStream is) throws IOException { - this(mimeType, width, height, depth, uniqueName, IO.readBytes(is)); - } - - /** - * Use this constructor if your local icon data is in a byte[]. - * - * @param uniqueName Must be a valid URI path segment and unique within the scope of a device. - */ - public Icon(String mimeType, int width, int height, int depth, String uniqueName, byte[] data) { - this(mimeType != null && mimeType.length() > 0 ? MimeType.valueOf(mimeType) : null, width, height, depth, URI.create(uniqueName), data); - } - - /** - * Use this constructor if your local icon is binary data encoded with BinHex. - - * @param uniqueName Must be a valid URI path segment and unique within the scope of a device. - * @param binHexEncoded The icon bytes encoded as BinHex. - */ - public Icon(String mimeType, int width, int height, int depth, String uniqueName, String binHexEncoded) { - this( - mimeType, width, height, depth, uniqueName, - binHexEncoded != null && !binHexEncoded.equals("") ? new BinHexDatatype().valueOf(binHexEncoded) : null - ); - } - - protected Icon(MimeType mimeType, int width, int height, int depth, URI uri, byte[] data) { - this.mimeType = mimeType; - this.width = width; - this.height = height; - this.depth = depth; - this.uri = uri; - this.data = data; - } - - public MimeType getMimeType() { - return mimeType; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public int getDepth() { - return depth; - } - - public URI getUri() { - return uri; - } - - public byte[] getData() { - return data; - } - - public Device getDevice() { - return device; - } - - void setDevice(Device device) { - if (this.device != null) - throw new IllegalStateException("Final value has been set already, model is immutable"); - this.device = device; - } - - public List validate() { - List errors = new ArrayList<>(); - - if (getMimeType() == null) { - log.warning("UPnP specification violation of: " + getDevice()); - log.warning("Invalid icon, missing mime type: " + this); - } - if (getWidth() == 0) { - log.warning("UPnP specification violation of: " + getDevice()); - log.warning("Invalid icon, missing width: " + this); - } - if (getHeight() == 0) { - log.warning("UPnP specification violation of: " + getDevice()); - log.warning("Invalid icon, missing height: " + this); - } - if (getDepth() == 0) { - log.warning("UPnP specification violation of: " + getDevice()); - log.warning("Invalid icon, missing bitmap depth: " + this); - } - - if (getUri() == null) { - errors.add(new ValidationError( - getClass(), - "uri", - "URL is required" - )); - } else { - try { - URL testURI = getUri().toURL(); - if (testURI == null) - throw new MalformedURLException(); - } catch (MalformedURLException ex) { - errors.add(new ValidationError( - getClass(), - "uri", - "URL must be valid: " + ex.getMessage()) - ); - } catch (IllegalArgumentException ex) { - // Relative URI is fine here! - } - } - - return errors; - } - - public Icon deepCopy() { - return new Icon( - getMimeType(), - getWidth(), - getHeight(), - getDepth(), - getUri(), - getData() - ); - } - - @Override - public String toString() { - return "Icon(" + getWidth() + "x" + getHeight() + ", MIME: " + getMimeType() + ") " + getUri(); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/LocalDevice.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/LocalDevice.java deleted file mode 100644 index 9acfcf9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/LocalDevice.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.profile.RemoteClientInfo; -import org.fourthline.cling.model.profile.DeviceDetailsProvider; -import org.fourthline.cling.model.resource.DeviceDescriptorResource; -import org.fourthline.cling.model.resource.IconResource; -import org.fourthline.cling.model.resource.ServiceControlResource; -import org.fourthline.cling.model.resource.ServiceDescriptorResource; -import org.fourthline.cling.model.resource.ServiceEventSubscriptionResource; -import org.fourthline.cling.model.resource.Resource; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -/** - * The metadata of a device created on this host, by application code. - * - * @author Christian Bauer - */ -public class LocalDevice extends Device { - - final private DeviceDetailsProvider deviceDetailsProvider; - - public LocalDevice(DeviceIdentity identity) throws ValidationException { - super(identity); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - LocalService service) throws ValidationException { - super(identity, type, details, null, new LocalService[]{service}); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetailsProvider deviceDetailsProvider, - LocalService service) throws ValidationException { - super(identity, type, null, null, new LocalService[]{service}); - this.deviceDetailsProvider = deviceDetailsProvider; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetailsProvider deviceDetailsProvider, - LocalService service, LocalDevice embeddedDevice) throws ValidationException { - super(identity, type, null, null, new LocalService[]{service}, new LocalDevice[]{embeddedDevice}); - this.deviceDetailsProvider = deviceDetailsProvider; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - LocalService service, LocalDevice embeddedDevice) throws ValidationException { - super(identity, type, details, null, new LocalService[]{service}, new LocalDevice[]{embeddedDevice}); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - LocalService[] services) throws ValidationException { - super(identity, type, details, null, services); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - LocalService[] services, LocalDevice[] embeddedDevices) throws ValidationException { - super(identity, type, details, null, services, embeddedDevices); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon icon, LocalService service) throws ValidationException { - super(identity, type, details, new Icon[]{icon}, new LocalService[]{service}); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon icon, LocalService service, LocalDevice embeddedDevice) throws ValidationException { - super(identity, type, details, new Icon[]{icon}, new LocalService[]{service}, new LocalDevice[]{embeddedDevice}); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon icon, LocalService[] services) throws ValidationException { - super(identity, type, details, new Icon[]{icon}, services); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetailsProvider deviceDetailsProvider, - Icon icon, LocalService[] services) throws ValidationException { - super(identity, type, null, new Icon[]{icon}, services); - this.deviceDetailsProvider = deviceDetailsProvider; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon icon, LocalService[] services, LocalDevice[] embeddedDevices) throws ValidationException { - super(identity, type, details, new Icon[]{icon}, services, embeddedDevices); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon[] icons, LocalService service) throws ValidationException { - super(identity, type, details, icons, new LocalService[]{service}); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon[] icons, LocalService service, LocalDevice embeddedDevice) throws ValidationException { - super(identity, type, details, icons, new LocalService[]{service}, new LocalDevice[]{embeddedDevice}); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetailsProvider deviceDetailsProvider, - Icon[] icons, LocalService service, LocalDevice embeddedDevice) throws ValidationException { - super(identity, type, null, icons, new LocalService[]{service}, new LocalDevice[]{embeddedDevice}); - this.deviceDetailsProvider = deviceDetailsProvider; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon[] icons, LocalService[] services) throws ValidationException { - super(identity, type, details, icons, services); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon[] icons, LocalService[] services, LocalDevice[] embeddedDevices) throws ValidationException { - super(identity, type, details, icons, services, embeddedDevices); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, UDAVersion version, DeviceType type, DeviceDetails details, - Icon[] icons, LocalService[] services, LocalDevice[] embeddedDevices) throws ValidationException { - super(identity, version, type, details, icons, services, embeddedDevices); - this.deviceDetailsProvider = null; - } - - public LocalDevice(DeviceIdentity identity, UDAVersion version, DeviceType type, DeviceDetailsProvider deviceDetailsProvider, - Icon[] icons, LocalService[] services, LocalDevice[] embeddedDevices) throws ValidationException { - super(identity, version, type, null, icons, services, embeddedDevices); - this.deviceDetailsProvider = deviceDetailsProvider; - } - - public DeviceDetailsProvider getDeviceDetailsProvider() { - return deviceDetailsProvider; - } - - @Override - public DeviceDetails getDetails(RemoteClientInfo info) { - if (getDeviceDetailsProvider() != null) { - return getDeviceDetailsProvider().provide(info); - } - return this.getDetails(); - } - - @Override - public LocalService[] getServices() { - return this.services != null ? this.services : new LocalService[0]; - } - - @Override - public LocalDevice[] getEmbeddedDevices() { - return this.embeddedDevices != null ? this.embeddedDevices : new LocalDevice[0]; - } - - @Override - public LocalDevice newInstance(UDN udn, UDAVersion version, DeviceType type, DeviceDetails details, - Icon[] icons, LocalService[] services, List embeddedDevices) - throws ValidationException { - return new LocalDevice( - new DeviceIdentity(udn, getIdentity().getMaxAgeSeconds()), - version, type, details, icons, - services, - embeddedDevices.size() > 0 ? embeddedDevices.toArray(new LocalDevice[embeddedDevices.size()]) : null - ); - } - - @Override - public LocalService newInstance(ServiceType serviceType, ServiceId serviceId, - URI descriptorURI, URI controlURI, URI eventSubscriptionURI, - Action[] actions, StateVariable[] stateVariables) throws ValidationException { - return new LocalService( - serviceType, serviceId, - actions, stateVariables - ); - } - - @Override - public LocalDevice[] toDeviceArray(Collection col) { - return col.toArray(new LocalDevice[col.size()]); - } - - @Override - public LocalService[] newServiceArray(int size) { - return new LocalService[size]; - } - - @Override - public LocalService[] toServiceArray(Collection col) { - return col.toArray(new LocalService[col.size()]); - } - - @Override - public List validate() { - List errors = new ArrayList<>(); - errors.addAll(super.validate()); - - // We have special rules for local icons, the URI must always be a relative path which will - // be added to the device base URI! - if (hasIcons()) { - for (Icon icon : getIcons()) { - if (icon.getUri().isAbsolute()) { - errors.add(new ValidationError( - getClass(), - "icons", - "Local icon URI can not be absolute: " + icon.getUri() - )); - } - if (icon.getUri().toString().contains("../")) { - errors.add(new ValidationError( - getClass(), - "icons", - "Local icon URI must not contain '../': " + icon.getUri() - )); - } - if (icon.getUri().toString().startsWith("/")) { - errors.add(new ValidationError( - getClass(), - "icons", - "Local icon URI must not start with '/': " + icon.getUri() - )); - } - } - } - - return errors; - } - - @Override - public Resource[] discoverResources(Namespace namespace) { - List discovered = new ArrayList<>(); - - // Device - if (isRoot()) { - // This should guarantee that each logical local device tree (with all its embedded devices) has only - // one device descriptor resource - because only one device in the tree isRoot(). - discovered.add(new DeviceDescriptorResource(namespace.getDescriptorPath(this), this)); - } - - // Services - for (LocalService service : getServices()) { - - discovered.add( - new ServiceDescriptorResource(namespace.getDescriptorPath(service), service) - ); - - // Control - discovered.add( - new ServiceControlResource(namespace.getControlPath(service), service) - ); - - // Event subscription - discovered.add( - new ServiceEventSubscriptionResource(namespace.getEventSubscriptionPath(service), service) - ); - - } - - // Icons - for (Icon icon : getIcons()) { - discovered.add(new IconResource(namespace.prefixIfRelative(this, icon.getUri()), icon)); - } - - // Embedded devices - if (hasEmbeddedDevices()) { - for (Device embeddedDevice : getEmbeddedDevices()) { - discovered.addAll(Arrays.asList(embeddedDevice.discoverResources(namespace))); - } - } - - return discovered.toArray(new Resource[discovered.size()]); - } - - @Override - public LocalDevice getRoot() { - if (isRoot()) return this; - LocalDevice current = this; - while (current.getParentDevice() != null) { - current = current.getParentDevice(); - } - return current; - } - - @Override - public LocalDevice findDevice(UDN udn) { - return find(udn, this); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/LocalService.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/LocalService.java deleted file mode 100644 index e3e0d44..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/LocalService.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.ServiceManager; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.action.ActionExecutor; -import org.fourthline.cling.model.state.StateVariableAccessor; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * The metadata of a service created on this host, by application code. - *

- * After instantiation {@link #setManager(org.fourthline.cling.model.ServiceManager)} must - * be called to bind the service metadata to the service implementation. - *

- * - * @author Christian Bauer - */ -public class LocalService extends Service { - - final protected Map actionExecutors; - final protected Map stateVariableAccessors; - final protected Set stringConvertibleTypes; - final protected boolean supportsQueryStateVariables; - - protected ServiceManager manager; - - public LocalService(ServiceType serviceType, ServiceId serviceId, - Action[] actions, StateVariable[] stateVariables) throws ValidationException { - super(serviceType, serviceId, actions, stateVariables); - this.manager = null; - this.actionExecutors = new HashMap<>(); - this.stateVariableAccessors = new HashMap<>(); - this.stringConvertibleTypes = new HashSet<>(); - this.supportsQueryStateVariables = true; - } - - public LocalService(ServiceType serviceType, ServiceId serviceId, - Map actionExecutors, - Map stateVariableAccessors, - Set stringConvertibleTypes, - boolean supportsQueryStateVariables) throws ValidationException { - - super(serviceType, serviceId, - actionExecutors.keySet().toArray(new Action[actionExecutors.size()]), - stateVariableAccessors.keySet().toArray(new StateVariable[stateVariableAccessors.size()]) - ); - - this.supportsQueryStateVariables = supportsQueryStateVariables; - this.stringConvertibleTypes = stringConvertibleTypes; - this.stateVariableAccessors = stateVariableAccessors; - this.actionExecutors = actionExecutors; - } - - synchronized public void setManager(ServiceManager manager) { - if (this.manager != null) { - throw new IllegalStateException("Manager is final"); - } - this.manager = manager; - } - - synchronized public ServiceManager getManager() { - if (manager == null) { - throw new IllegalStateException("Unmanaged service, no implementation instance available"); - } - return manager; - } - - public boolean isSupportsQueryStateVariables() { - return supportsQueryStateVariables; - } - - public Set getStringConvertibleTypes() { - return stringConvertibleTypes; - } - - public boolean isStringConvertibleType(Object o) { - return o != null && isStringConvertibleType(o.getClass()); - } - - public boolean isStringConvertibleType(Class clazz) { - return ModelUtil.isStringConvertibleType(getStringConvertibleTypes(), clazz); - } - - public StateVariableAccessor getAccessor(String stateVariableName) { - StateVariable sv; - return (sv = getStateVariable(stateVariableName)) != null ? getAccessor(sv) : null; - } - - public StateVariableAccessor getAccessor(StateVariable stateVariable) { - return stateVariableAccessors.get(stateVariable); - } - - public ActionExecutor getExecutor(String actionName) { - Action action; - return (action = getAction(actionName)) != null ? getExecutor(action) : null; - } - - public ActionExecutor getExecutor(Action action) { - return actionExecutors.get(action); - } - - @Override - public Action getQueryStateVariableAction() { - return getAction(QueryStateVariableAction.ACTION_NAME); - } - - @Override - public String toString() { - return super.toString() + ", Manager: " + manager; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/ManufacturerDetails.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/ManufacturerDetails.java deleted file mode 100644 index 3472c24..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/ManufacturerDetails.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import java.net.URI; - -/** - * Encpasulates optional metadata about a device's manufacturer. - * - * @author Christian Bauer - */ -public class ManufacturerDetails { - - private String manufacturer; - private URI manufacturerURI; - - ManufacturerDetails() { - } - - public ManufacturerDetails(String manufacturer) { - this.manufacturer = manufacturer; - } - - public ManufacturerDetails(URI manufacturerURI) { - this.manufacturerURI = manufacturerURI; - } - - public ManufacturerDetails(String manufacturer, URI manufacturerURI) { - this.manufacturer = manufacturer; - this.manufacturerURI = manufacturerURI; - } - - public ManufacturerDetails(String manufacturer, String manufacturerURI) throws IllegalArgumentException { - this.manufacturer = manufacturer; - this.manufacturerURI = URI.create(manufacturerURI); - } - - public String getManufacturer() { - return manufacturer; - } - - public URI getManufacturerURI() { - return manufacturerURI; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/ModelDetails.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/ModelDetails.java deleted file mode 100644 index 83cb6cd..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/ModelDetails.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import java.net.URI; - -/** - * Encpasulates optional metadata about the model of a device. - * - * @author Christian Bauer - */ -public class ModelDetails { - - private String modelName; - private String modelDescription; - private String modelNumber; - private URI modelURI; - - ModelDetails() { - } - - public ModelDetails(String modelName) { - this.modelName = modelName; - } - - public ModelDetails(String modelName, String modelDescription) { - this.modelName = modelName; - this.modelDescription = modelDescription; - } - - public ModelDetails(String modelName, String modelDescription, String modelNumber) { - this.modelName = modelName; - this.modelDescription = modelDescription; - this.modelNumber = modelNumber; - } - - public ModelDetails(String modelName, String modelDescription, String modelNumber, URI modelURI) { - this.modelName = modelName; - this.modelDescription = modelDescription; - this.modelNumber = modelNumber; - this.modelURI = modelURI; - } - - public ModelDetails(String modelName, String modelDescription, String modelNumber, String modelURI) throws IllegalArgumentException { - this.modelName = modelName; - this.modelDescription = modelDescription; - this.modelNumber = modelNumber; - this.modelURI = URI.create(modelURI); - } - - public String getModelName() { - return modelName; - } - - public String getModelDescription() { - return modelDescription; - } - - public String getModelNumber() { - return modelNumber; - } - - public URI getModelURI() { - return modelURI; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/QueryStateVariableAction.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/QueryStateVariableAction.java deleted file mode 100644 index 59c552c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/QueryStateVariableAction.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import org.fourthline.cling.model.ValidationError; - -import java.util.List; -import java.util.Collections; - - -/** - * Describes a single action, the deprecated "query any state variable" action. - * - * Note: This is already deprecated in UDA 1.0! - * - * @author Christian Bauer - */ -public class QueryStateVariableAction extends Action { - - public static final String INPUT_ARG_VAR_NAME = "varName"; - public static final String OUTPUT_ARG_RETURN = "return"; - - public static final String ACTION_NAME = "QueryStateVariable"; - public static final String VIRTUAL_STATEVARIABLE_INPUT = "VirtualQueryActionInput"; - public static final String VIRTUAL_STATEVARIABLE_OUTPUT = "VirtualQueryActionOutput"; - - public QueryStateVariableAction() { - this(null); - } - - public QueryStateVariableAction(S service) { - super(ACTION_NAME, - new ActionArgument[]{ - new ActionArgument(INPUT_ARG_VAR_NAME, VIRTUAL_STATEVARIABLE_INPUT, ActionArgument.Direction.IN), - new ActionArgument(OUTPUT_ARG_RETURN, VIRTUAL_STATEVARIABLE_OUTPUT, ActionArgument.Direction.OUT), - } - ); - setService(service); - } - - @Override - public String getName() { - return ACTION_NAME; - } - - @Override - public List validate() { - return Collections.EMPTY_LIST; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteDevice.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteDevice.java deleted file mode 100644 index 3a405ce..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteDevice.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - - -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.resource.ServiceEventCallbackResource; -import org.fourthline.cling.model.resource.Resource; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; -import org.seamless.util.URIUtil; - -import java.net.URI; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -/** - * The metadata of a device that was discovered on the network. - * - * @author Christian Bauer - */ -public class RemoteDevice extends Device { - - public RemoteDevice(RemoteDeviceIdentity identity) throws ValidationException { - super(identity); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - RemoteService service) throws ValidationException { - super(identity, type, details, null, new RemoteService[]{service}); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - RemoteService service, RemoteDevice embeddedDevice) throws ValidationException { - super(identity, type, details, null, new RemoteService[]{service}, new RemoteDevice[]{embeddedDevice}); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - RemoteService[] services) throws ValidationException { - super(identity, type, details, null, services); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - RemoteService[] services, RemoteDevice[] embeddedDevices) throws ValidationException { - super(identity, type, details, null, services, embeddedDevices); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon icon, RemoteService service) throws ValidationException { - super(identity, type, details, new Icon[]{icon}, new RemoteService[]{service}); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon icon, RemoteService service, RemoteDevice embeddedDevice) throws ValidationException { - super(identity, type, details, new Icon[]{icon}, new RemoteService[]{service}, new RemoteDevice[]{embeddedDevice}); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon icon, RemoteService[] services) throws ValidationException { - super(identity, type, details, new Icon[]{icon}, services); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon icon, RemoteService[] services, RemoteDevice[] embeddedDevices) throws ValidationException { - super(identity, type, details, new Icon[]{icon}, services, embeddedDevices); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon[] icons, RemoteService service) throws ValidationException { - super(identity, type, details, icons, new RemoteService[]{service}); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon[] icons, RemoteService service, RemoteDevice embeddedDevice) throws ValidationException { - super(identity, type, details, icons, new RemoteService[]{service}, new RemoteDevice[]{embeddedDevice}); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon[] icons, RemoteService[] services) throws ValidationException { - super(identity, type, details, icons, services); - } - - public RemoteDevice(RemoteDeviceIdentity identity, DeviceType type, DeviceDetails details, - Icon[] icons, RemoteService[] services, RemoteDevice[] embeddedDevices) throws ValidationException { - super(identity, type, details, icons, services, embeddedDevices); - } - - public RemoteDevice(RemoteDeviceIdentity identity, UDAVersion version, DeviceType type, DeviceDetails details, - Icon[] icons, RemoteService[] services, RemoteDevice[] embeddedDevices) throws ValidationException { - super(identity, version, type, details, icons, services, embeddedDevices); - } - - @Override - public RemoteService[] getServices() { - return this.services != null ? this.services : new RemoteService[0]; - } - - @Override - public RemoteDevice[] getEmbeddedDevices() { - return this.embeddedDevices != null ? this.embeddedDevices : new RemoteDevice[0]; - } - - public URL normalizeURI(URI relativeOrAbsoluteURI) { - - // TODO: I have one device (Netgear 834DG DSL Router) that sends a , and even that is wrong (port)! - // This can be fixed by "re-enabling" UPnP in the upnpService after a reboot, it will then use the right port... - // return URIUtil.createAbsoluteURL(getDescriptorURL(), relativeOrAbsoluteURI); - - if (getDetails() != null && getDetails().getBaseURL() != null) { - // If we have an , all URIs are relative to it - return URIUtil.createAbsoluteURL(getDetails().getBaseURL(), relativeOrAbsoluteURI); - } else { - // Otherwise, they are relative to the descriptor location - return URIUtil.createAbsoluteURL(getIdentity().getDescriptorURL(), relativeOrAbsoluteURI); - } - - } - - @Override - public RemoteDevice newInstance(UDN udn, UDAVersion version, DeviceType type, DeviceDetails details, - Icon[] icons, RemoteService[] services, - List embeddedDevices) throws ValidationException { - return new RemoteDevice( - new RemoteDeviceIdentity(udn, getIdentity()), - version, type, details, icons, - services, - embeddedDevices.size() > 0 ? embeddedDevices.toArray(new RemoteDevice[embeddedDevices.size()]) : null - ); - } - - @Override - public RemoteService newInstance(ServiceType serviceType, ServiceId serviceId, - URI descriptorURI, URI controlURI, URI eventSubscriptionURI, - Action[] actions, StateVariable[] stateVariables) throws ValidationException { - return new RemoteService( - serviceType, serviceId, - descriptorURI, controlURI, eventSubscriptionURI, - actions, stateVariables - ); - } - - @Override - public RemoteDevice[] toDeviceArray(Collection col) { - return col.toArray(new RemoteDevice[col.size()]); - } - - @Override - public RemoteService[] newServiceArray(int size) { - return new RemoteService[size]; - } - - @Override - public RemoteService[] toServiceArray(Collection col) { - return col.toArray(new RemoteService[col.size()]); - } - - @Override - public Resource[] discoverResources(Namespace namespace) { - List discovered = new ArrayList<>(); - - // Services - for (RemoteService service : getServices()) { - if(service == null) continue; - discovered.add(new ServiceEventCallbackResource(namespace.getEventCallbackPath(service), service)); - } - - // Embedded devices - if (hasEmbeddedDevices()) { - for (Device embeddedDevice : getEmbeddedDevices()) { - if(embeddedDevice == null) continue; - discovered.addAll(Arrays.asList(embeddedDevice.discoverResources(namespace))); - } - } - - return discovered.toArray(new Resource[discovered.size()]); - } - - @Override - public RemoteDevice getRoot() { - if (isRoot()) return this; - RemoteDevice current = this; - while (current.getParentDevice() != null) { - current = current.getParentDevice(); - } - return current; - } - - @Override - public RemoteDevice findDevice(UDN udn) { - return find(udn, this); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteDeviceIdentity.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteDeviceIdentity.java deleted file mode 100644 index f646633..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteDeviceIdentity.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.message.discovery.IncomingNotificationRequest; -import org.fourthline.cling.model.message.discovery.IncomingSearchResponse; -import org.fourthline.cling.model.types.UDN; - -import java.net.InetAddress; -import java.net.URL; - -/** - * Additional identifying information only relevant for discovered remote devices. - *

- * This information always includes the URL of the device's descriptor, and the - * local network interface address we should use in the future, because it is - * guaranteed to be reachable by this remote device (e.g. when we build a local - * callback URL). - *

- *

- * Optional is the remote hosts interface MAC hardware address. If we have it, we - * can use it to send Wake-On-LAN broadcasts if we think the remote host is not - * reachable and might be sleeping. (Useful for "stateless" reconnecting control - * points.) - *

- * - * @author Christian Bauer - */ -public class RemoteDeviceIdentity extends DeviceIdentity { - - final private URL descriptorURL; - final private byte[] interfaceMacAddress; - final private InetAddress discoveredOnLocalAddress; - - public RemoteDeviceIdentity(UDN udn, RemoteDeviceIdentity template) { - this(udn, template.getMaxAgeSeconds(), template.getDescriptorURL(), template.getInterfaceMacAddress(), template.getDiscoveredOnLocalAddress()); - } - - public RemoteDeviceIdentity(UDN udn, Integer maxAgeSeconds, URL descriptorURL, byte[] interfaceMacAddress, InetAddress discoveredOnLocalAddress) { - super(udn, maxAgeSeconds); - this.descriptorURL = descriptorURL; - this.interfaceMacAddress = interfaceMacAddress; - this.discoveredOnLocalAddress = discoveredOnLocalAddress; - } - - public RemoteDeviceIdentity(IncomingNotificationRequest notificationRequest) { - this(notificationRequest.getUDN(), - notificationRequest.getMaxAge(), - notificationRequest.getLocationURL(), - notificationRequest.getInterfaceMacHeader(), - notificationRequest.getLocalAddress() - ); - } - - public RemoteDeviceIdentity(IncomingSearchResponse searchResponse) { - this(searchResponse.getRootDeviceUDN(), - searchResponse.getMaxAge(), - searchResponse.getLocationURL(), - searchResponse.getInterfaceMacHeader(), - searchResponse.getLocalAddress() - ); - } - - public URL getDescriptorURL() { - return descriptorURL; - } - - public byte[] getInterfaceMacAddress() { - return interfaceMacAddress; - } - - public InetAddress getDiscoveredOnLocalAddress() { - return discoveredOnLocalAddress; - } - - public byte[] getWakeOnLANBytes() { - if (getInterfaceMacAddress() == null) return null; - byte[] bytes = new byte[6 + 16 * getInterfaceMacAddress().length]; - for (int i = 0; i < 6; i++) { - bytes[i] = (byte) 0xff; - } - for (int i = 6; i < bytes.length; i += getInterfaceMacAddress().length) { - System.arraycopy(getInterfaceMacAddress(), 0, bytes, i, getInterfaceMacAddress().length); - } - return bytes; - } - - @Override - public String toString() { - // Performance optimization, so we don't have to wrap all log("foo " + device) calls with isLoggable - if(ModelUtil.ANDROID_RUNTIME) { - return "(RemoteDeviceIdentity) UDN: " + getUdn() + ", Descriptor: " + getDescriptorURL(); - } - return "(" + getClass().getSimpleName() + ") UDN: " + getUdn() + ", Descriptor: " + getDescriptorURL(); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteService.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteService.java deleted file mode 100644 index c045f2f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/RemoteService.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -/** - * The metadata of a service discovered on a remote device. - *

- * Includes the URI's for getting the service's descriptor, calling its - * actions, and subscribing to events. - *

- * - * @author Christian Bauer - */ -public class RemoteService extends Service { - - final private URI descriptorURI; - final private URI controlURI; - final private URI eventSubscriptionURI; - - public RemoteService(ServiceType serviceType, ServiceId serviceId, - URI descriptorURI, URI controlURI, URI eventSubscriptionURI) throws ValidationException { - this(serviceType, serviceId, descriptorURI, controlURI, eventSubscriptionURI, null, null); - } - - public RemoteService(ServiceType serviceType, ServiceId serviceId, - URI descriptorURI, URI controlURI, URI eventSubscriptionURI, - Action[] actions, StateVariable[] stateVariables) throws ValidationException { - super(serviceType, serviceId, actions, stateVariables); - - this.descriptorURI = descriptorURI; - this.controlURI = controlURI; - this.eventSubscriptionURI = eventSubscriptionURI; - - List errors = validateThis(); - if (errors.size() > 0) { - throw new ValidationException("Validation of device graph failed, call getErrors() on exception", errors); - } - } - - @Override - public Action getQueryStateVariableAction() { - return new QueryStateVariableAction(this); - } - - public URI getDescriptorURI() { - return descriptorURI; - } - - public URI getControlURI() { - return controlURI; - } - - public URI getEventSubscriptionURI() { - return eventSubscriptionURI; - } - - public List validateThis() { - List errors = new ArrayList<>(); - - if (getDescriptorURI() == null) { - errors.add(new ValidationError( - getClass(), - "descriptorURI", - "Descriptor location (SCPDURL) is required" - )); - } - - if (getControlURI() == null) { - errors.add(new ValidationError( - getClass(), - "controlURI", - "Control URL is required" - )); - } - - if (getEventSubscriptionURI() == null) { - errors.add(new ValidationError( - getClass(), - "eventSubscriptionURI", - "Event subscription URL is required" - )); - } - - return errors; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") Descriptor: " + getDescriptorURI(); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Service.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Service.java deleted file mode 100644 index cc3aae8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/Service.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import org.fourthline.cling.model.ServiceReference; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.ServiceId; -import org.fourthline.cling.model.types.ServiceType; - -/** - * The metadata of a service, with actions and state variables. - * - * @author Christian Bauer - */ -public abstract class Service { - - final private static Logger log = Logger.getLogger(Service.class.getName()); - - final private ServiceType serviceType; - final private ServiceId serviceId; - - - final private Map actions = new HashMap<>(); - final private Map stateVariables = new HashMap<>(); - - // Package mutable state - private D device; - - public Service(ServiceType serviceType, ServiceId serviceId) throws ValidationException { - this(serviceType, serviceId, null, null); - } - - public Service(ServiceType serviceType, ServiceId serviceId, - Action[] actions, StateVariable[] stateVariables) throws ValidationException { - - this.serviceType = serviceType; - this.serviceId = serviceId; - - if (actions != null) { - for (Action action : actions) { - this.actions.put(action.getName(), action); - action.setService(this); - } - } - - if (stateVariables != null) { - for (StateVariable stateVariable : stateVariables) { - this.stateVariables.put(stateVariable.getName(), stateVariable); - stateVariable.setService(this); - } - } - - } - - public ServiceType getServiceType() { - return serviceType; - } - - public ServiceId getServiceId() { - return serviceId; - } - - public boolean hasActions() { - return getActions() != null && getActions().length > 0; - } - - public Action[] getActions() { - return actions == null ? null : actions.values().toArray(new Action[actions.values().size()]); - } - - public boolean hasStateVariables() { - // TODO: Spec says always has to have at least one... - return getStateVariables() != null && getStateVariables().length > 0; - } - - public StateVariable[] getStateVariables() { - return stateVariables == null ? null : stateVariables.values().toArray(new StateVariable[stateVariables.values().size()]); - } - - public D getDevice() { - return device; - } - - void setDevice(D device) { - if (this.device != null) - throw new IllegalStateException("Final value has been set already, model is immutable"); - this.device = device; - } - - public Action getAction(String name) { - return actions == null ? null : actions.get(name); - } - - public StateVariable getStateVariable(String name) { - // Some magic necessary for the deprecated 'query state variable' action stuff - if (QueryStateVariableAction.VIRTUAL_STATEVARIABLE_INPUT.equals(name)) { - return new StateVariable( - QueryStateVariableAction.VIRTUAL_STATEVARIABLE_INPUT, - new StateVariableTypeDetails(Datatype.Builtin.STRING.getDatatype()) - ); - } - if (QueryStateVariableAction.VIRTUAL_STATEVARIABLE_OUTPUT.equals(name)) { - return new StateVariable( - QueryStateVariableAction.VIRTUAL_STATEVARIABLE_OUTPUT, - new StateVariableTypeDetails(Datatype.Builtin.STRING.getDatatype()) - ); - } - return stateVariables == null ? null : stateVariables.get(name); - } - - public StateVariable getRelatedStateVariable(ActionArgument argument) { - return getStateVariable(argument.getRelatedStateVariableName()); - } - - public Datatype getDatatype(ActionArgument argument) { - return getRelatedStateVariable(argument).getTypeDetails().getDatatype(); - } - - public ServiceReference getReference() { - return new ServiceReference(getDevice().getIdentity().getUdn(), getServiceId()); - } - - public List validate() { - List errors = new ArrayList<>(); - - if (getServiceType() == null) { - errors.add(new ValidationError( - getClass(), - "serviceType", - "Service type/info is required" - )); - } - - if (getServiceId() == null) { - errors.add(new ValidationError( - getClass(), - "serviceId", - "Service ID is required" - )); - } - - // TODO: If the service has no evented variables, it should not have an event subscription URL, which means - // the url element in the device descriptor must be present, but empty!!!! - - /* TODO: This doesn't fit into our meta model, we don't know if a service has state variables until - we completely hydrate it from a service descriptor - if (getStateVariables().length == 0) { - errors.add(new ValidationError( - getClass(), - "stateVariables", - "Service must have at least one state variable" - )); - } - */ - if (hasStateVariables()) { - for (StateVariable stateVariable : getStateVariables()) { - errors.addAll(stateVariable.validate()); - } - } - - if (hasActions()) { - for (Action action : getActions()) { - - // Instead of bailing out here, we try to continue if an action is invalid - // errors.addAll(action.validate()); - - List actionErrors = action.validate(); - if(actionErrors.size() > 0) { - actions.remove(action.getName()); // Remove it - log.warning("Discarding invalid action of service '" + getServiceId() + "': " + action.getName()); - for (ValidationError actionError : actionErrors) { - log.warning("Invalid action '" + action.getName() + "': " + actionError); - } - } - } - } - - return errors; - } - - public abstract Action getQueryStateVariableAction(); - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") ServiceId: " + getServiceId(); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariable.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariable.java deleted file mode 100644 index be0be72..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariable.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.Validatable; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.types.Datatype; - -import java.util.List; -import java.util.ArrayList; -import java.util.logging.Logger; - -/** - * The metadata of a named state variable. - * - * @author Christian Bauer - */ -public class StateVariable implements Validatable { - - final private static Logger log = Logger.getLogger(StateVariable.class.getName()); - - final private String name; - final private StateVariableTypeDetails type; - final private StateVariableEventDetails eventDetails; - - // Package mutable state - private S service; - - public StateVariable(String name, StateVariableTypeDetails type) { - this(name, type, new StateVariableEventDetails()); - } - - public StateVariable(String name, StateVariableTypeDetails type, StateVariableEventDetails eventDetails) { - this.name = name; - this.type = type; - this.eventDetails = eventDetails; - } - - public String getName() { - return name; - } - - public StateVariableTypeDetails getTypeDetails() { - return type; - } - - public StateVariableEventDetails getEventDetails() { - return eventDetails; - } - - public S getService() { - return service; - } - - void setService(S service) { - if (this.service != null) - throw new IllegalStateException("Final value has been set already, model is immutable"); - this.service = service; - } - - public List validate() { - List errors = new ArrayList<>(); - - if (getName() == null || getName().length() == 0) { - errors.add(new ValidationError( - getClass(), - "name", - "StateVariable without name of: " + getService() - )); - } else if (!ModelUtil.isValidUDAName(getName())) { - log.warning("UPnP specification violation of: " + getService().getDevice()); - log.warning("Invalid state variable name: " + this); - } - - errors.addAll(getTypeDetails().validate()); - - return errors; - } - - public boolean isModeratedNumericType() { - return Datatype.Builtin.isNumeric( - getTypeDetails().getDatatype().getBuiltin() - ) && getEventDetails().getEventMinimumDelta() > 0; - } - - public StateVariable deepCopy() { - return new StateVariable( - getName(), - getTypeDetails(), - getEventDetails() - ); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(").append(getClass().getSimpleName()); - sb.append(", Name: ").append(getName()); - sb.append(", Type: ").append(getTypeDetails().getDatatype().getDisplayString()).append(")"); - if (!getEventDetails().isSendEvents()) { - sb.append(" (No Events)"); - } - if (getTypeDetails().getDefaultValue() != null) { - sb.append(" Default Value: ").append("'").append(getTypeDetails().getDefaultValue()).append("'"); - } - if (getTypeDetails().getAllowedValues() != null) { - sb.append(" Allowed Values: "); - for (String s : getTypeDetails().getAllowedValues()) { - sb.append(s).append("|"); - } - } - return sb.toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableAllowedValueRange.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableAllowedValueRange.java deleted file mode 100644 index dcc6d21..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableAllowedValueRange.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -import org.fourthline.cling.model.Validatable; -import org.fourthline.cling.model.ValidationError; - -import java.util.List; -import java.util.ArrayList; -import java.util.logging.Logger; - -/** - * Integrity rule for a state variable, restricting its values to a range with steps. - *

- * TODO: The question here is: Are they crazy enough to use this for !integer (e.g. floating point) numbers? - * - * @author Christian Bauer - */ -public class StateVariableAllowedValueRange implements Validatable { - - final private static Logger log = Logger.getLogger(StateVariableAllowedValueRange.class.getName()); - - final private long minimum; - final private long maximum; - final private long step; - - public StateVariableAllowedValueRange(long minimum, long maximum) { - this(minimum, maximum, 1); - } - - public StateVariableAllowedValueRange(long minimum, long maximum, long step) { - if (minimum > maximum) { - log.warning("UPnP specification violation, allowed value range minimum '" + minimum - + "' is greater than maximum '" + maximum + "', switching values."); - this.minimum = maximum; - this.maximum = minimum; - } else { - this.minimum = minimum; - this.maximum = maximum; - } - this.step = step; - } - - public long getMinimum() { - return minimum; - } - - public long getMaximum() { - return maximum; - } - - public long getStep() { - return step; - } - - public boolean isInRange(long value) { - return value >= getMinimum() && value <= getMaximum() && (value % step) == 0; - } - - public List validate() { - return new ArrayList<>(); - } - - @Override - public String toString() { - return "Range Min: " + getMinimum() + " Max: " + getMaximum() + " Step: " + getStep(); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableEventDetails.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableEventDetails.java deleted file mode 100644 index 53a2dd2..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableEventDetails.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - -/** - * Eventing options of a state variable, including moderation settings. - * - * @author Christian Bauer - */ -public class StateVariableEventDetails { - - final private boolean sendEvents; - final private int eventMaximumRateMilliseconds; - final private int eventMinimumDelta; - - public StateVariableEventDetails() { - this(true, 0, 0); - } - - public StateVariableEventDetails(boolean sendEvents) { - this(sendEvents, 0, 0); - } - - public StateVariableEventDetails(boolean sendEvents, int eventMaximumRateMilliseconds, int eventMinimumDelta) { - this.sendEvents = sendEvents; - this.eventMaximumRateMilliseconds = eventMaximumRateMilliseconds; - this.eventMinimumDelta = eventMinimumDelta; - } - - public boolean isSendEvents() { - return sendEvents; - } - - public int getEventMaximumRateMilliseconds() { - return eventMaximumRateMilliseconds; - } - - public int getEventMinimumDelta() { - return eventMinimumDelta; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableTypeDetails.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableTypeDetails.java deleted file mode 100644 index bcb30da..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/StateVariableTypeDetails.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - - - -import org.fourthline.cling.model.Validatable; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.types.Datatype; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.logging.Logger; - -/** - * Type of a state variable, its default value, and integrity rules for allowed values and ranges. - * - * @author Christian Bauer - */ -public class StateVariableTypeDetails implements Validatable { - - final private static Logger log = Logger.getLogger(StateVariableTypeDetails.class.getName()); - - final private Datatype datatype; - final private String defaultValue; - final private String[] allowedValues; - final private StateVariableAllowedValueRange allowedValueRange; - - public StateVariableTypeDetails(Datatype datatype) { - this(datatype, null, null, null); - } - - public StateVariableTypeDetails(Datatype datatype, String defaultValue) { - this(datatype, defaultValue, null, null); - } - - public StateVariableTypeDetails(Datatype datatype, String defaultValue, String[] allowedValues, StateVariableAllowedValueRange allowedValueRange) { - this.datatype = datatype; - this.defaultValue = defaultValue; - this.allowedValues = allowedValues; - this.allowedValueRange = allowedValueRange; - } - - public Datatype getDatatype() { - return datatype; - } - - public String getDefaultValue() { - return defaultValue; - } - - public String[] getAllowedValues() { - // TODO: UPNP VIOLATION: DirecTV HR23/700 High Definition DVR Receiver has invalid default value - if (!foundDefaultInAllowedValues(defaultValue, allowedValues)) { - List list = new ArrayList<>(Arrays.asList(allowedValues)); - list.add(getDefaultValue()); - return list.toArray(new String[list.size()]); - } - return allowedValues; - } - - public StateVariableAllowedValueRange getAllowedValueRange() { - return allowedValueRange; - } - - protected boolean foundDefaultInAllowedValues(String defaultValue, String[] allowedValues) { - if (defaultValue == null || allowedValues == null) return true; - for (String s : allowedValues) { - if (s.equals(defaultValue)) return true; - } - return false; - } - - public List validate() { - List errors = new ArrayList<>(); - - if (getDatatype() == null) { - errors.add(new ValidationError( - getClass(), - "datatype", - "Service state variable has no datatype" - )); - } - - if (getAllowedValues() != null) { - - if (getAllowedValueRange() != null) { - errors.add(new ValidationError( - getClass(), - "allowedValues", - "Allowed value list of state variable can not also be restricted with allowed value range" - )); - } - - if (!Datatype.Builtin.STRING.equals(getDatatype().getBuiltin())) { - errors.add(new ValidationError( - getClass(), - "allowedValues", - "Allowed value list of state variable only available for string datatype, not: " + getDatatype() - )); - } - - for (String s : getAllowedValues()) { - if (s.length() > 31) { - log.warning("UPnP specification violation, allowed value string must be less than 32 chars: " + s); - } - } - - if(!foundDefaultInAllowedValues(defaultValue, allowedValues)) { - log.warning("UPnP specification violation, allowed string values " + - "don't contain default value: " + defaultValue - ); - } - } - - if (getAllowedValueRange() != null) { - errors.addAll(getAllowedValueRange().validate()); - } - - return errors; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/UDAVersion.java b/clinglibrary/src/main/java/org/fourthline/cling/model/meta/UDAVersion.java deleted file mode 100644 index b5eca60..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/meta/UDAVersion.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.meta; - - - - -import org.fourthline.cling.model.Validatable; -import org.fourthline.cling.model.ValidationError; - -import java.util.List; -import java.util.ArrayList; - -/** - * Version of the UPnP Device Architecture (UDA), defaults to 1.0. - * - * @author Christian Bauer - */ -public class UDAVersion implements Validatable { - - private int major = 1; - private int minor = 0; - - public UDAVersion() { - } - - public UDAVersion(int major, int minor) { - this.major = major; - this.minor = minor; - } - - public int getMajor() { - return major; - } - - public int getMinor() { - return minor; - } - - public List validate() { - List errors = new ArrayList<>(); - - if (getMajor() != 1) { - errors.add(new ValidationError( - getClass(), - "major", - "UDA major spec version must be 1" - )); - } - if (getMajor() < 0) { - errors.add(new ValidationError( - getClass(), - "minor", - "UDA minor spec version must be equal or greater 0" - )); - } - - return errors; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/profile/ClientInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/model/profile/ClientInfo.java deleted file mode 100644 index b08c20f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/profile/ClientInfo.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.profile; - -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.message.header.UserAgentHeader; - -/** - * Encapsulates information about a (local) client. - * - * @author Christian Bauer - */ -public class ClientInfo { - - final protected UpnpHeaders requestHeaders; - - public ClientInfo() { - this(new UpnpHeaders()); - } - - public ClientInfo(UpnpHeaders requestHeaders) { - this.requestHeaders = requestHeaders; - } - - public UpnpHeaders getRequestHeaders() { - return requestHeaders; - } - - public String getRequestUserAgent() { - return getRequestHeaders().getFirstHeaderString(UpnpHeader.Type.USER_AGENT); - } - - public void setRequestUserAgent(String userAgent) { - getRequestHeaders().add(UpnpHeader.Type.USER_AGENT, new UserAgentHeader(userAgent)); - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") User-Agent: " + getRequestUserAgent(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/profile/DeviceDetailsProvider.java b/clinglibrary/src/main/java/org/fourthline/cling/model/profile/DeviceDetailsProvider.java deleted file mode 100644 index 99bd0f1..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/profile/DeviceDetailsProvider.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.profile; - -import org.fourthline.cling.model.meta.DeviceDetails; - -/** - * Provides custom device details metadata based on control point profile. - *

- * Use this instead of {@link DeviceDetails} when you create a - * {@link org.fourthline.cling.model.meta.LocalDevice} if dynamic metadata is - * required - e.g. when your control points expect different DLNA capabilities - * or if they are otherwise incompatible with the standard metadata of the - * service you provide. You can then provide custom metadata for each - * control point based on the detected control point information. - *

- *

- * Don't forget to provide a default, that is, if none of your conditions match - * you still have to provide a minimal {@link DeviceDetails} instance for - * generic control points. - *

- * - * @author Mario Franco - * @author Christian Bauer - */ -public interface DeviceDetailsProvider { - DeviceDetails provide(RemoteClientInfo info); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/profile/HeaderDeviceDetailsProvider.java b/clinglibrary/src/main/java/org/fourthline/cling/model/profile/HeaderDeviceDetailsProvider.java deleted file mode 100644 index 6a7a18c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/profile/HeaderDeviceDetailsProvider.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.profile; - -import org.fourthline.cling.model.meta.DeviceDetails; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -/** - * Selects device details based on a regex and the client's HTTP headers. - *

- * This provider will lookup and match a {@link DeviceDetails} entry in a - * given map that is keyed by HTTP header name and a regular expression pattern. - * If the control point sent an HTTP header that matches an entry's name, - * and the value of the control points header matches the pattern of the entry, - * the value of the entry is applied. This is a case-insensitive pattern match. - *

- * - * @author Mario Franco - * @author Christian Bauer - */ -public class HeaderDeviceDetailsProvider implements DeviceDetailsProvider { - - public static class Key { - - final String headerName; - final String valuePattern; - final Pattern pattern; - - public Key(String headerName, String valuePattern) { - this.headerName = headerName; - this.valuePattern = valuePattern; - this.pattern = Pattern.compile(valuePattern, Pattern.CASE_INSENSITIVE); - } - - public String getHeaderName() { - return headerName; - } - - public String getValuePattern() { - return valuePattern; - } - - public boolean isValuePatternMatch(String value) { - return pattern.matcher(value).matches(); - } - } - - - final private DeviceDetails defaultDeviceDetails; - final private Map headerDetails; - - public HeaderDeviceDetailsProvider(DeviceDetails defaultDeviceDetails) { - this(defaultDeviceDetails, null); - } - - public HeaderDeviceDetailsProvider(DeviceDetails defaultDeviceDetails, - Map headerDetails) { - this.defaultDeviceDetails = defaultDeviceDetails; - this.headerDetails = headerDetails != null ? headerDetails : new HashMap(); - } - - public DeviceDetails getDefaultDeviceDetails() { - return defaultDeviceDetails; - } - - public Map getHeaderDetails() { - return headerDetails; - } - - public DeviceDetails provide(RemoteClientInfo info) { - if (info == null || info.getRequestHeaders().isEmpty()) return getDefaultDeviceDetails(); - - for (Key key : getHeaderDetails().keySet()) { - List headerValues; - if ((headerValues = info.getRequestHeaders().get(key.getHeaderName())) == null) continue; - for (String headerValue : headerValues) { - if (key.isValuePatternMatch(headerValue)) - return getHeaderDetails().get(key); - } - } - return getDefaultDeviceDetails(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/profile/RemoteClientInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/model/profile/RemoteClientInfo.java deleted file mode 100644 index ccb1e14..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/profile/RemoteClientInfo.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.profile; - -import org.fourthline.cling.model.message.Connection; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.message.header.UserAgentHeader; -import org.seamless.http.RequestInfo; - -import java.net.InetAddress; - -/** - * Encapsulates information about a remote control point, the client. - * - *

- * The {@link #getExtraResponseHeaders()} method offers modifiable HTTP headers which will - * be added to the responses and returned to the client. - *

- * - * @author Christian Bauer - */ -public class RemoteClientInfo extends ClientInfo { - - final protected Connection connection; - final protected UpnpHeaders extraResponseHeaders = new UpnpHeaders(); - - public RemoteClientInfo() { - this(null); - } - - public RemoteClientInfo(StreamRequestMessage requestMessage) { - this(requestMessage != null ? requestMessage.getConnection() : null, - requestMessage != null ? requestMessage.getHeaders() : new UpnpHeaders()); - } - - public RemoteClientInfo(Connection connection, UpnpHeaders requestHeaders) { - super(requestHeaders); - this.connection = connection; - } - - public Connection getConnection() { - return connection; - } - - /** - *

- * Check if the remote client's connection is still open. - *

- *

- * How connection checking is actually performed is transport-implementation dependent. Usually, - * the {@link org.fourthline.cling.transport.spi.StreamServer} will send meaningless heartbeat - * data to the client on its (open) socket. If that fails, the client's connection has been - * closed. Note that some HTTP clients can NOT handle such garbage data in HTTP - * responses, hence calling this method might cause compatibility issues. - *

- * @return true if the remote client's connection was closed. - */ - public boolean isRequestCancelled() { - return !getConnection().isOpen(); - } - - /** - * @throws InterruptedException if {@link #isRequestCancelled()} returns true. - */ - public void throwIfRequestCancelled() throws InterruptedException{ - if(isRequestCancelled()) - throw new InterruptedException("Client's request cancelled"); - } - - public InetAddress getRemoteAddress() { - return getConnection().getRemoteAddress(); - } - - public InetAddress getLocalAddress() { - return getConnection().getLocalAddress(); - } - - public UpnpHeaders getExtraResponseHeaders() { - return extraResponseHeaders; - } - - public void setResponseUserAgent(String userAgent) { - setResponseUserAgent(new UserAgentHeader(userAgent)); - } - - public void setResponseUserAgent(UserAgentHeader userAgentHeader) { - getExtraResponseHeaders().add( - UpnpHeader.Type.USER_AGENT, - userAgentHeader - ); - } - - // TODO: Remove this once we know how ClientProfile will look like - public boolean isWMPRequest() { - return RequestInfo.isWMPRequest(getRequestUserAgent()); - } - - public boolean isXbox360Request() { - return RequestInfo.isXbox360Request( - getRequestUserAgent(), - getRequestHeaders().getFirstHeaderString(UpnpHeader.Type.SERVER) - ); - } - - public boolean isPS3Request() { - return RequestInfo.isPS3Request( - getRequestUserAgent(), - getRequestHeaders().getFirstHeaderString(UpnpHeader.Type.EXT_AV_CLIENT_INFO) - ); - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") Remote Address: " + getRemoteAddress(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/DeviceDescriptorResource.java b/clinglibrary/src/main/java/org/fourthline/cling/model/resource/DeviceDescriptorResource.java deleted file mode 100644 index cd892af..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/DeviceDescriptorResource.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.resource; - -import org.fourthline.cling.model.meta.LocalDevice; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class DeviceDescriptorResource extends Resource { - - public DeviceDescriptorResource(URI localURI, LocalDevice model) { - super(localURI, model); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/IconResource.java b/clinglibrary/src/main/java/org/fourthline/cling/model/resource/IconResource.java deleted file mode 100644 index 46299a0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/IconResource.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.resource; - -import org.fourthline.cling.model.meta.Icon; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class IconResource extends Resource { - - public IconResource(URI localURI, Icon model) { - super(localURI, model); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/Resource.java b/clinglibrary/src/main/java/org/fourthline/cling/model/resource/Resource.java deleted file mode 100644 index 8a3ee66..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/Resource.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.resource; - -import org.fourthline.cling.model.ExpirationDetails; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.List; - -/** - * An addressable object, stored, managed, and accessible through the {@link org.fourthline.cling.registry.Registry}. - * - * @param The type of the model object. - * - * @author Christian Bauer - */ -public class Resource { - - private URI pathQuery; - private M model; - - /** - * @param pathQuery The path and (optional) query URI parts of this resource. - * @param model The model object. - */ - public Resource(URI pathQuery, M model) { - try { - this.pathQuery = new URI(null, null, pathQuery.getPath(), pathQuery.getQuery(), null); - } catch (URISyntaxException ex) { - throw new RuntimeException(ex); - } - this.model = model; - if (model == null) { - throw new IllegalArgumentException("Model instance must not be null"); - } - } - - public URI getPathQuery() { - return pathQuery; - } - - public M getModel() { - return model; - } - - - /** - * @param pathQuery A relative URI. - * @return true if the given URI path and query matches the resource's path and query. - */ - public boolean matches(URI pathQuery) { - return pathQuery.equals(getPathQuery()); - } - - /** - * Called periodically by the registry to maintain the resource. - *

- * NOOP by default. - *

- * - * @param pendingExecutions Add Runnable's to this collection if maintenance code has to run in the background. - * @param expirationDetails The details of this resource's expiration, e.g. when it will expire. - */ - public void maintain(List pendingExecutions, - ExpirationDetails expirationDetails) { - // Do nothing - } - - /** - * Called by the registry when it stops, in the shutdown thread. - *

- * NOOP by default. - *

- */ - public void shutdown() { - // Do nothing - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Resource resource = (Resource) o; - - if (!getPathQuery().equals(resource.getPathQuery())) return false; - - return true; - } - - @Override - public int hashCode() { - return getPathQuery().hashCode(); - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") URI: " + getPathQuery(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceControlResource.java b/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceControlResource.java deleted file mode 100644 index 37b9abc..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceControlResource.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.resource; - -import org.fourthline.cling.model.meta.LocalService; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class ServiceControlResource extends Resource { - - public ServiceControlResource(URI localURI, LocalService model) { - super(localURI, model); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceDescriptorResource.java b/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceDescriptorResource.java deleted file mode 100644 index 06b0d98..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceDescriptorResource.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.resource; - -import org.fourthline.cling.model.meta.LocalService; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class ServiceDescriptorResource extends Resource { - - public ServiceDescriptorResource(URI localURI, LocalService model) { - super(localURI, model); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceEventCallbackResource.java b/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceEventCallbackResource.java deleted file mode 100644 index 54e8028..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceEventCallbackResource.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.resource; - -import org.fourthline.cling.model.meta.RemoteService; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class ServiceEventCallbackResource extends Resource { - - public ServiceEventCallbackResource(URI localURI, RemoteService model) { - super(localURI, model); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceEventSubscriptionResource.java b/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceEventSubscriptionResource.java deleted file mode 100644 index fd81403..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/resource/ServiceEventSubscriptionResource.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.resource; - -import org.fourthline.cling.model.meta.LocalService; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class ServiceEventSubscriptionResource extends Resource { - - public ServiceEventSubscriptionResource(URI localURI, LocalService model) { - super(localURI, model); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/state/FieldStateVariableAccessor.java b/clinglibrary/src/main/java/org/fourthline/cling/model/state/FieldStateVariableAccessor.java deleted file mode 100644 index 6d77022..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/state/FieldStateVariableAccessor.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.state; - -import org.seamless.util.Reflections; - -import java.lang.reflect.Field; - -/** - * Reads the value of a state variable using reflection and a field. - * - * @author Christian Bauer - */ -public class FieldStateVariableAccessor extends StateVariableAccessor { - - protected Field field; - - public FieldStateVariableAccessor(Field field) { - this.field = field; - } - - public Field getField() { - return field; - } - - @Override - public Class getReturnType() { - return getField().getType(); - } - - @Override - public Object read(Object serviceImpl) throws Exception { - return Reflections.get(field, serviceImpl); - } - - @Override - public String toString() { - return super.toString() + " Field: " + getField(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/state/GetterStateVariableAccessor.java b/clinglibrary/src/main/java/org/fourthline/cling/model/state/GetterStateVariableAccessor.java deleted file mode 100644 index 3dc21d6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/state/GetterStateVariableAccessor.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.state; - -import org.seamless.util.Reflections; - -import java.lang.reflect.Method; - -/** - * Reads the value of a state variable using reflection and a getter method. - * - * @author Christian Bauer - */ -public class GetterStateVariableAccessor extends StateVariableAccessor { - - private Method getter; - - public GetterStateVariableAccessor(Method getter) { - this.getter = getter; - } - - public Method getGetter() { - return getter; - } - - @Override - public Class getReturnType() { - return getGetter().getReturnType(); - } - - @Override - public Object read(Object serviceImpl) throws Exception { - return Reflections.invoke(getGetter(), serviceImpl); - } - - @Override - public String toString() { - return super.toString() + " Method: " + getGetter(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/state/StateVariableAccessor.java b/clinglibrary/src/main/java/org/fourthline/cling/model/state/StateVariableAccessor.java deleted file mode 100644 index f2cc5ea..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/state/StateVariableAccessor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.state; - -import org.fourthline.cling.model.Command; -import org.fourthline.cling.model.ServiceManager; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.StateVariable; - - -/** - * Reads the value of a state variable, given an instance that implements the service. - * - * TODO: The design of this is not final, not happy with the relationship between ActionExecutor and this. - * - * @author Christian Bauer - */ -public abstract class StateVariableAccessor { - - public StateVariableValue read(final StateVariable stateVariable, final Object serviceImpl) throws Exception { - - class AccessCommand implements Command { - Object result; - public void execute(ServiceManager serviceManager) throws Exception { - result = read(serviceImpl); - if (stateVariable.getService().isStringConvertibleType(result)) { - result = result.toString(); - } - } - } - - AccessCommand cmd = new AccessCommand(); - stateVariable.getService().getManager().execute(cmd); - return new StateVariableValue(stateVariable, cmd.result); - } - - public abstract Class getReturnType(); - - // TODO: Especially this shouldn't be public - public abstract Object read(Object serviceImpl) throws Exception; - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ")"; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/state/StateVariableValue.java b/clinglibrary/src/main/java/org/fourthline/cling/model/state/StateVariableValue.java deleted file mode 100644 index c38e427..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/state/StateVariableValue.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.state; - -import org.fourthline.cling.model.VariableValue; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * Represents the value of a state variable. - * - * @author Christian Bauer - */ -public class StateVariableValue extends VariableValue { - - private StateVariable stateVariable; - - public StateVariableValue(StateVariable stateVariable, Object value) throws InvalidValueException { - super(stateVariable.getTypeDetails().getDatatype(), value); - this.stateVariable = stateVariable; - } - - public StateVariable getStateVariable() { - return stateVariable; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/AbstractDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/AbstractDatatype.java deleted file mode 100644 index d233d89..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/AbstractDatatype.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import java.lang.reflect.ParameterizedType; - -/** - * @author Christian Bauer - */ -public abstract class AbstractDatatype implements Datatype { - - private Builtin builtin; - - protected Class getValueType() { - return (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; - } - - @Override - public boolean isHandlingJavaType(Class type) { - return getValueType().isAssignableFrom(type); - } - - @Override - public V valueOf(String s) throws InvalidValueException { - return null; - } - - public Builtin getBuiltin() { - return builtin; - } - - public void setBuiltin(Builtin builtin) { - this.builtin = builtin; - } - - public String getString(V value) throws InvalidValueException { - if (value == null) return ""; - if (!isValid(value)) { - throw new InvalidValueException("Value is not valid: " + value); - } - return value.toString(); - } - - public boolean isValid(V value) { - return value == null || getValueType().isAssignableFrom(value.getClass()); - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ")"; - } - - public String getDisplayString() { - if (this instanceof CustomDatatype) { - return ((CustomDatatype)this).getName(); - } else if (getBuiltin() != null) { - return getBuiltin().getDescriptorName(); - } else { - return getValueType().getSimpleName(); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/Base64Datatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/Base64Datatype.java deleted file mode 100644 index 569318b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/Base64Datatype.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.seamless.util.io.Base64Coder; - -/** - * @author Christian Bauer - */ -public class Base64Datatype extends AbstractDatatype { - - public Base64Datatype() { - } - - public Class getValueType() { - return byte[].class; - } - - public byte[] valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - try { - return Base64Coder.decode(s); - } catch (Exception ex) { - throw new InvalidValueException(ex.getMessage(), ex); - } - } - - @Override - public String getString(byte[] value) throws InvalidValueException { - if (value == null) return ""; - try { - return new String(Base64Coder.encode(value), "UTF-8"); - } catch (Exception ex) { - throw new InvalidValueException(ex.getMessage(), ex); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/BinHexDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/BinHexDatatype.java deleted file mode 100644 index 0609c39..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/BinHexDatatype.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.seamless.util.io.HexBin; - -/** - * @author Christian Bauer - */ -public class BinHexDatatype extends AbstractDatatype { - - public BinHexDatatype() { - } - - public Class getValueType() { - return byte[].class; - } - - public byte[] valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - try { - return HexBin.stringToBytes(s); - } catch (Exception ex) { - throw new InvalidValueException(ex.getMessage(), ex); - } - } - - @Override - public String getString(byte[] value) throws InvalidValueException { - if (value == null) return ""; - try { - return HexBin.bytesToString(value); - } catch (Exception ex) { - throw new InvalidValueException(ex.getMessage(), ex); - } - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/BooleanDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/BooleanDatatype.java deleted file mode 100644 index 306027a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/BooleanDatatype.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import java.util.Locale; - -/** - * @author Christian Bauer - */ -public class BooleanDatatype extends AbstractDatatype { - - public BooleanDatatype() { - } - - @Override - public boolean isHandlingJavaType(Class type) { - return type == Boolean.TYPE || Boolean.class.isAssignableFrom(type); - } - - public Boolean valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - if (s.equals("1") || s.toUpperCase(Locale.ROOT).equals("YES") || s.toUpperCase(Locale.ROOT).equals("TRUE")) { - return true; - } else if (s.equals("0") || s.toUpperCase(Locale.ROOT).equals("NO") || s.toUpperCase(Locale.ROOT).equals("FALSE")) { - return false; - } else { - throw new InvalidValueException("Invalid boolean value string: " + s); - } - } - - public String getString(Boolean value) throws InvalidValueException { - if (value == null) return ""; - return value ? "1" : "0"; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/BytesRange.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/BytesRange.java deleted file mode 100644 index 86b17c7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/BytesRange.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.model.types; - -/** - * - * @author Mario Franco - */ -public class BytesRange { - - public static final String PREFIX = "bytes="; - - private Long firstByte; - private Long lastByte; - private Long byteLength; - - public BytesRange(Long firstByte, Long lastByte) { - this.firstByte = firstByte; - this.lastByte = lastByte; - this.byteLength = null; - } - - public BytesRange(Long firstByte, Long lastByte, Long byteLength) { - this.firstByte = firstByte; - this.lastByte = lastByte; - this.byteLength = byteLength; - } - - /** - * @return the firstByte - */ - public Long getFirstByte() { - return firstByte; - } - - /** - * @return the lastByte - */ - public Long getLastByte() { - return lastByte; - } - - /** - * @return the byteLength - */ - public Long getByteLength() { - return byteLength; - } - - /** - * - * @return String format of Bytes Range for response message header - */ - public String getString() { - return getString(false,null); - } - - /** - * - * @return String format of Bytes Range for response message header - */ - public String getString(boolean includeDuration) { - return getString(includeDuration,null); - } - - /** - * - * @return String format of Bytes Range for response message header - */ - public String getString(boolean includeDuration, String rangePrefix) { - String s = (rangePrefix!=null)?rangePrefix:PREFIX; - - if (firstByte!=null) - s += firstByte.toString(); - s += "-"; - if (lastByte!=null) - s+= lastByte.toString(); - if (includeDuration) { - s += "/" + (byteLength != null ? byteLength.toString() : "*"); - } - - return s; - } - - public static BytesRange valueOf(String s) throws InvalidValueException { - return valueOf(s,null); - } - - public static BytesRange valueOf(String s, String rangePrefix) throws InvalidValueException { - if (s.startsWith((rangePrefix!=null)?rangePrefix:PREFIX)) { - Long firstByte=null, lastByte = null, byteLength = null; - String[] params = s.substring( ((rangePrefix!=null)?rangePrefix:PREFIX).length()).split("[-/]"); - switch (params.length) { - case 3: - if (params[2].length() != 0 && !params[2].equals("*")) { - byteLength = Long.parseLong(params[2]); - } - case 2: - if (params[1].length() != 0) { - lastByte = Long.parseLong(params[1]); - } - case 1: - if (params[0].length() != 0) { - firstByte = Long.parseLong(params[0]); - } - if (firstByte!=null || lastByte!= null) - return new BytesRange(firstByte, lastByte, byteLength); - default: - break; - } - } - - throw new InvalidValueException("Can't parse Bytes Range: " + s); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/CharacterDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/CharacterDatatype.java deleted file mode 100644 index d05f69b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/CharacterDatatype.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -public class CharacterDatatype extends AbstractDatatype { - - public CharacterDatatype() { - } - - @Override - public boolean isHandlingJavaType(Class type) { - return type == Character.TYPE || Character.class.isAssignableFrom(type); - } - - public Character valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - return s.charAt(0); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/CustomDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/CustomDatatype.java deleted file mode 100644 index 7b98826..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/CustomDatatype.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -public class CustomDatatype extends AbstractDatatype { - - private String name; - - public CustomDatatype(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public String valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - return s; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") '" + getName() + "'"; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/DLNACaps.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/DLNACaps.java deleted file mode 100644 index 1cb462b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/DLNACaps.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.fourthline.cling.model.ModelUtil; - -import java.util.Arrays; - -/** - * An arbitrary list of comma-separated elements, representing DLNA capabilities (whatever that is). - * - * @author Christian Bauer - */ -public class DLNACaps { - - final String[] caps; - - public DLNACaps(String[] caps) { - this.caps = caps; - } - - public String[] getCaps() { - return caps; - } - - static public DLNACaps valueOf(String s) throws InvalidValueException { - if (s == null || s.length() == 0) return new DLNACaps(new String[0]); - String[] caps = s.split(","); - String[] trimmed = new String[caps.length]; - for (int i = 0; i < caps.length; i++) { - trimmed[i] = caps[i].trim(); - } - return new DLNACaps(trimmed); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - DLNACaps dlnaCaps = (DLNACaps) o; - - if (!Arrays.equals(caps, dlnaCaps.caps)) return false; - - return true; - } - - @Override - public int hashCode() { - return Arrays.hashCode(caps); - } - - @Override - public String toString() { - return ModelUtil.toCommaSeparatedList(getCaps()); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/DLNADoc.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/DLNADoc.java deleted file mode 100644 index b97c83c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/DLNADoc.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Representing the DLNA document and its version. - *

- * Someone ignored the device and service type construct of UPnP - * and invented a new and of course much better device type/version * construct. - *

- * - * @author Christian Bauer - */ -public class DLNADoc { - - public static final Pattern PATTERN = Pattern.compile("(.+?)[ -]([0-9].[0-9]{2})"); - - public enum Version { - V1_0("1.00"), - V1_5("1.50"); - - String s; - - Version(String s) { - this.s = s; - } - - - @Override - public String toString() { - return s; - } - } - - final private String devClass; - final private String version; - - public DLNADoc(String devClass, String version) { - this.devClass = devClass; - this.version = version; - } - - public DLNADoc(String devClass, Version version) { - this.devClass = devClass; - this.version = version.s; - } - - public String getDevClass() { - return devClass; - } - - public String getVersion() { - return version; - } - - public static DLNADoc valueOf(String s) throws InvalidValueException { - Matcher matcher = PATTERN.matcher(s); - if (matcher.matches()) { - return new DLNADoc(matcher.group(1), matcher.group(2)); - } else { - throw new InvalidValueException("Can't parse DLNADoc: " + s); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - DLNADoc dlnaDoc = (DLNADoc) o; - - if (!devClass.equals(dlnaDoc.devClass)) return false; - if (!version.equals(dlnaDoc.version)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = devClass.hashCode(); - result = 31 * result + version.hashCode(); - return result; - } - - @Override - public String toString() { - return getDevClass() + "-" + getVersion(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/Datatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/Datatype.java deleted file mode 100644 index 7116e0a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/Datatype.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; -import java.util.Locale; - -/** - * The type of a state variable value, able to convert to/from string representation. - * - * @param The Java type of the value handled by this datatype. - * @author Christian Bauer - */ -public interface Datatype { - - /** - * Mapping from Java type to UPnP built-in type. - *

- * This map is used for service binding, when we have to figure out - * the type of a UPnP state variable by reflecting on a method or field of - * a service class. From a known Java type we default to a UPnP built-in type. - * This is just a list of default mappings between Java and UPnP types. There - * might be more than this/more than one UPnP type that can handle a given - * Java type. - *

- */ - public static enum Default { - - BOOLEAN(Boolean.class, Builtin.BOOLEAN), - BOOLEAN_PRIMITIVE(Boolean.TYPE, Builtin.BOOLEAN), - SHORT(Short.class, Builtin.I2_SHORT), - SHORT_PRIMITIVE(Short.TYPE, Builtin.I2_SHORT), - INTEGER(Integer.class, Builtin.I4), - INTEGER_PRIMITIVE(Integer.TYPE, Builtin.I4), - UNSIGNED_INTEGER_ONE_BYTE(UnsignedIntegerOneByte.class, Builtin.UI1), - UNSIGNED_INTEGER_TWO_BYTES(UnsignedIntegerTwoBytes.class, Builtin.UI2), - UNSIGNED_INTEGER_FOUR_BYTES(UnsignedIntegerFourBytes.class, Builtin.UI4), - FLOAT(Float.class, Builtin.R4), - FLOAT_PRIMITIVE(Float.TYPE, Builtin.R4), - DOUBLE(Double.class, Builtin.FLOAT), - DOUBLE_PRIMTIIVE(Double.TYPE, Builtin.FLOAT), - CHAR(Character.class, Builtin.CHAR), - CHAR_PRIMITIVE(Character.TYPE, Builtin.CHAR), - STRING(String.class, Builtin.STRING), - CALENDAR(Calendar.class, Builtin.DATETIME), - BYTES(byte[].class, Builtin.BIN_BASE64), - URI(java.net.URI.class, Builtin.URI); - - private Class javaType; - private Builtin builtinType; - - Default(Class javaType, Builtin builtinType) { - this.javaType = javaType; - this.builtinType = builtinType; - } - - public Class getJavaType() { - return javaType; - } - - public Builtin getBuiltinType() { - return builtinType; - } - - public static Default getByJavaType(Class javaType) { - for (Default d : Default.values()) { - if (d.getJavaType().equals(javaType)) { - return d; - } - } - return null; - } - - @Override - public String toString() { - return getJavaType() + " => " + getBuiltinType(); - } - } - - /** - * Mapping from UPnP built-in standardized type to actual subtype of {@link Datatype}. - */ - public static enum Builtin { - - UI1("ui1", new UnsignedIntegerOneByteDatatype()), - UI2("ui2", new UnsignedIntegerTwoBytesDatatype()), - UI4("ui4", new UnsignedIntegerFourBytesDatatype()), - I1("i1", new IntegerDatatype(1)), - I2("i2", new IntegerDatatype(2)), - I2_SHORT("i2", new ShortDatatype()), - I4("i4", new IntegerDatatype(4)), - INT("int", new IntegerDatatype(4)), - R4("r4", new FloatDatatype()), - R8("r8", new DoubleDatatype()), - NUMBER("number", new DoubleDatatype()), - FIXED144("fixed.14.4", new DoubleDatatype()), - FLOAT("float", new DoubleDatatype()), // TODO: Is that Double or Float? - CHAR("char", new CharacterDatatype()), - STRING("string", new StringDatatype()), - DATE("date", new DateTimeDatatype( - new String[]{"yyyy-MM-dd"}, - "yyyy-MM-dd" - )), - DATETIME("dateTime", new DateTimeDatatype( - new String[]{"yyyy-MM-dd", "yyyy-MM-dd'T'HH:mm:ss"}, - "yyyy-MM-dd'T'HH:mm:ss" - )), - DATETIME_TZ("dateTime.tz", new DateTimeDatatype( - new String[]{"yyyy-MM-dd", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ssZ"}, - "yyyy-MM-dd'T'HH:mm:ssZ" - )), - TIME("time", new DateTimeDatatype( - new String[]{"HH:mm:ss"}, - "HH:mm:ss" - )), - TIME_TZ("time.tz", new DateTimeDatatype( - new String[]{"HH:mm:ssZ", "HH:mm:ss"}, - "HH:mm:ssZ" - )), - BOOLEAN("boolean", new BooleanDatatype()), - BIN_BASE64("bin.base64", new Base64Datatype()), - BIN_HEX("bin.hex", new BinHexDatatype()), - URI("uri", new URIDatatype()), - UUID("uuid", new StringDatatype()); - - private static Map byName = new HashMap() {{ - for (Builtin b : Builtin.values()) { - // Lowercase descriptor name! - if (containsKey(b.getDescriptorName().toLowerCase(Locale.ROOT))) - continue; // Ignore double-declarations, take first one only - put(b.getDescriptorName().toLowerCase(Locale.ROOT), b); - } - }}; - - private String descriptorName; - private Datatype datatype; - - Builtin(String descriptorName, AbstractDatatype datatype) { - datatype.setBuiltin(this); // Protected, we actually want this to be immutable - this.descriptorName = descriptorName; - this.datatype = datatype; - } - - public String getDescriptorName() { - return descriptorName; - } - - public Datatype getDatatype() { - return datatype; - } - - public static Builtin getByDescriptorName(String descriptorName) { - // The UPnP spec clearly says "must be one of these values", so I'm assuming - // they are case sensitive. But we want to work with broken devices, which of - // course produce mixed upper/lowercase values. - if (descriptorName == null) return null; - return byName.get(descriptorName.toLowerCase(Locale.ROOT)); - } - - public static boolean isNumeric(Builtin builtin) { - return builtin != null && - (builtin.equals(UI1) || - builtin.equals(UI2) || - builtin.equals(UI4) || - builtin.equals(I1) || - builtin.equals(I2) || - builtin.equals(I4) || - builtin.equals(INT)); - } - } - - /** - * @return true if this datatype can handle values of the given Java type. - */ - public boolean isHandlingJavaType(Class type); - - /** - * @return The built-in UPnP standardized type this datatype is mapped to or - * null if this is a custom datatype. - */ - public Builtin getBuiltin(); - - /** - * @param value The value to validate or null. - * @return Returns true if the value was null, validation result otherwise. - */ - public boolean isValid(V value); - - /** - * Transforms a value supported by this datatype into a string representation. - *

- * This method calls {@link #isValid(Object)} before converting the value, it throws - * an exception if validation fails. - *

- * - * @param value The value to transform. - * @return The transformed value as a string, or an empty string when the value is null, never returns null. - * @throws InvalidValueException - */ - public String getString(V value) throws InvalidValueException; - - /** - * Transforms a string representation into a value of the supported type. - * - * @param s The string representation of a value. - * @return The converted value or null if the string was null or empty. - * @throws InvalidValueException If the string couldn't be parsed. - */ - public V valueOf(String s) throws InvalidValueException; - - /** - * @return Metadata about this datatype, a nice string for display that describes - * this datatype (e.g. concrete class name). - */ - public String getDisplayString(); - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/DateTimeDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/DateTimeDatatype.java deleted file mode 100644 index 3070ff1..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/DateTimeDatatype.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.TimeZone; - -/** - * @author Christian Bauer - */ -public class DateTimeDatatype extends AbstractDatatype { - - protected String[] readFormats; - protected String writeFormat; - - public DateTimeDatatype(String[] readFormats, String writeFormat) { - this.readFormats = readFormats; - this.writeFormat = writeFormat; - } - - public Calendar valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - - Date d = getDateValue(s, readFormats); - if (d == null) { - throw new InvalidValueException("Can't parse date/time from: " + s); - } - - Calendar c = Calendar.getInstance(getTimeZone()); - c.setTime(d); - - /* - // TODO: I'm not sure this is necessary and I don't remember why I wrote it - if (readFormats[0].equals("HH:mm:ssZ") && (getTimeZone().inDaylightTime(d))) - c.add(Calendar.MILLISECOND, 3600000); - */ - - return c; - } - - @Override - public String getString(Calendar value) throws InvalidValueException { - if (value == null) return ""; - SimpleDateFormat sdt = new SimpleDateFormat(writeFormat); - sdt.setTimeZone(getTimeZone()); - return sdt.format(value.getTime()); - } - - protected String normalizeTimeZone(String value) { - if (value.endsWith("Z")) { - value = value.substring(0, value.length() - 1) + "+0000"; - } else if ((value.length() > 7) - && (value.charAt(value.length() - 3) == ':') - && ((value.charAt(value.length() - 6) == '-') || (value.charAt(value.length() - 6) == '+'))) { - - value = value.substring(0, value.length() - 3) + value.substring(value.length() - 2); - } - return value; - } - - protected Date getDateValue(String value, String[] formats) { - - value = normalizeTimeZone(value); - - Date d = null; - for (String format : formats) { - SimpleDateFormat sdt = new SimpleDateFormat(format); - sdt.setTimeZone(getTimeZone()); - try { - d = sdt.parse(value); - // Continue, last match is the one we need - } catch (ParseException ex) { - // Just continue - } - } - return d; - } - - protected TimeZone getTimeZone() { - return TimeZone.getDefault(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/DeviceType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/DeviceType.java deleted file mode 100644 index bf84bc1..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/DeviceType.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.fourthline.cling.model.Constants; - -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Represents a device type, for example urn:my-domain-namespace:device:MyDevice:1. - *

- * Although decimal versions are accepted and parsed, the version used for - * comparison is only the integer without the fraction. - *

- * - * @author Christian Bauer - */ -public class DeviceType { - - final private static Logger log = Logger.getLogger(DeviceType.class.getName()); - - public static final String UNKNOWN = "UNKNOWN"; - - public static final Pattern PATTERN = - Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):device:(" + Constants.REGEX_TYPE + "):([0-9]+).*"); - - private String namespace; - private String type; - private int version = 1; - - public DeviceType(String namespace, String type) { - this(namespace, type, 1); - } - - public DeviceType(String namespace, String type, int version) { - if (namespace != null && !namespace.matches(Constants.REGEX_NAMESPACE)) { - throw new IllegalArgumentException("Device type namespace contains illegal characters"); - } - this.namespace = namespace; - - if (type != null && !type.matches(Constants.REGEX_TYPE)) { - throw new IllegalArgumentException("Device type suffix too long (64) or contains illegal characters"); - } - this.type = type; - - this.version = version; - } - - public String getNamespace() { - return namespace; - } - - public String getType() { - return type; - } - - public int getVersion() { - return version; - } - - /** - * @return Either a {@link UDADeviceType} or a more generic {@link DeviceType}. - */ - public static DeviceType valueOf(String s) throws InvalidValueException { - - DeviceType deviceType = null; - - // Sometimes crazy UPnP devices deliver spaces in a URN, don't ask... - s = s.replaceAll("\\s", ""); - - // First try UDADeviceType parse - try { - deviceType = UDADeviceType.valueOf(s); - } catch (Exception ex) { - // Ignore - } - - if (deviceType != null) - return deviceType; - - try { - // Now try a generic DeviceType parse - Matcher matcher = PATTERN.matcher(s); - if (matcher.matches()) { - return new DeviceType(matcher.group(1), matcher.group(2), Integer.valueOf(matcher.group(3))); - } - - // TODO: UPNP VIOLATION: Escient doesn't provide any device type token - // urn:schemas-upnp-org:device::1 - matcher = Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):device::([0-9]+).*").matcher(s); - if (matcher.matches() && matcher.groupCount() >= 2) { - log.warning("UPnP specification violation, no device type token, defaulting to " + UNKNOWN + ": " + s); - return new DeviceType(matcher.group(1), UNKNOWN, Integer.valueOf(matcher.group(2))); - } - - // TODO: UPNP VIOLATION: EyeTV Netstream uses colons in device type token - // urn:schemas-microsoft-com:service:pbda:tuner:1 - matcher = Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):device:(.+?):([0-9]+).*").matcher(s); - if (matcher.matches() && matcher.groupCount() >= 3) { - String cleanToken = matcher.group(2).replaceAll("[^a-zA-Z_0-9\\-]", "-"); - log.warning( - "UPnP specification violation, replacing invalid device type token '" - + matcher.group(2) - + "' with: " - + cleanToken - ); - return new DeviceType(matcher.group(1), cleanToken, Integer.valueOf(matcher.group(3))); - } - } catch (RuntimeException e) { - throw new InvalidValueException(String.format( - "Can't parse device type string (namespace/type/version) '%s': %s", s, e.toString() - )); - } - - throw new InvalidValueException("Can't parse device type string (namespace/type/version): " + s); - } - - public boolean implementsVersion(DeviceType that) { - if (!namespace.equals(that.namespace)) return false; - if (!type.equals(that.type)) return false; - if (version < that.version) return false; - return true; - } - - public String getDisplayString() { - return getType(); - } - - @Override - public String toString() { - return "urn:" + getNamespace() + ":device:" + getType()+ ":" + getVersion(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof DeviceType)) return false; - - DeviceType that = (DeviceType) o; - - if (version != that.version) return false; - if (!namespace.equals(that.namespace)) return false; - if (!type.equals(that.type)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = namespace.hashCode(); - result = 31 * result + type.hashCode(); - result = 31 * result + version; - return result; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/DoubleDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/DoubleDatatype.java deleted file mode 100644 index 4d81c72..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/DoubleDatatype.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -public class DoubleDatatype extends AbstractDatatype { - - public DoubleDatatype() { - } - - @Override - public boolean isHandlingJavaType(Class type) { - return type == Double.TYPE || Double.class.isAssignableFrom(type); - } - - public Double valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - try { - return Double.parseDouble(s); - } catch (NumberFormatException ex) { - throw new InvalidValueException("Can't convert string to number: " + s, ex); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/ErrorCode.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/ErrorCode.java deleted file mode 100644 index c2538ba..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/ErrorCode.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * Basic UPnP control message error codes. - * - * @author Christian Bauer - */ -public enum ErrorCode { - - INVALID_ACTION(401, "No action by that name at this service"), - INVALID_ARGS(402, "Not enough IN args, too many IN args, no IN arg by that name, one or more IN args are of the wrong data type"), - ACTION_FAILED(501, "Current state of service prevents invoking that action"), - ARGUMENT_VALUE_INVALID(600, "The argument value is invalid"), - ARGUMENT_VALUE_OUT_OF_RANGE(601, "An argument value is less than the minimum or more than the maximum value of the allowedValueRange, or is not in the allowedValueList"), - OPTIONAL_ACTION(602, "The requested action is optional and is not implemented by the device"), - OUT_OF_MEMORY(603, "The device does not have sufficient memory available to complete the action"), - HUMAN_INTERVENTION_REQUIRED(604, "The device has encountered an error condition which it cannot resolve itself"), - ARGUMENT_TOO_LONG(605, "A string argument is too long for the device to handle properly"), - ACTION_NOT_AUTHORIZED(606, "The action requested requires authorization and the sender was not authorized"), - SIGNATURE_FAILURE(607, "The sender's signature failed to verify"), - SIGNATURE_MISSING(608, "The action requested requires a digital signature and there was none provided"), - NOT_ENCRYPTED(609, "This action requires confidentiality but the action was not delivered encrypted"), - INVALID_SEQUENCE(610, "The sequence provided was not valid"), - INVALID_CONTROL_URL(611, "The controlURL within the freshness element does not match the controlURL of the action actually invoked"), - NO_SUCH_SESSION(612, "The session key reference is to a non-existent session"), - TRANSPORT_LOCKED(705, "Transport locked"), - ILLEGAL_MIME_TYPE(714, "Illegal mime-type"); - - private int code; - private String description; - - ErrorCode(int code, String description) { - this.code = code; - this.description = description; - } - - public int getCode() { - return code; - } - - public String getDescription() { - return description; - } - - public static ErrorCode getByCode(int code) { - for (ErrorCode errorCode : values()) { - if (errorCode.getCode() == code) - return errorCode; - } - return null; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/FloatDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/FloatDatatype.java deleted file mode 100644 index 0770aa5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/FloatDatatype.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -public class FloatDatatype extends AbstractDatatype { - - public FloatDatatype() { - } - - @Override - public boolean isHandlingJavaType(Class type) { - return type == Float.TYPE || Float.class.isAssignableFrom(type); - } - - public Float valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - try { - return Float.parseFloat(s.trim()); - } catch (NumberFormatException ex) { - throw new InvalidValueException("Can't convert string to number: " + s, ex); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/HostPort.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/HostPort.java deleted file mode 100644 index f7bc71e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/HostPort.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * Encapsulates a host string and a port. - * - * @author Christian Bauer - */ -public class HostPort { - - private String host; - private int port; - - public HostPort() { - } - - public HostPort(String host, int port) { - this.host = host; - this.port = port; - } - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - HostPort hostPort = (HostPort) o; - - if (port != hostPort.port) return false; - if (!host.equals(hostPort.host)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = host.hashCode(); - result = 31 * result + port; - return result; - } - - @Override - public String toString() { - return host + ":" + port; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/IntegerDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/IntegerDatatype.java deleted file mode 100644 index fb8b589..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/IntegerDatatype.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * Although the UDA 1.0 spec doesn't say it, we assume that "int" is a 4 byte regular Java integer. - * - * @author Christian Bauer - */ -public class IntegerDatatype extends AbstractDatatype { - - private int byteSize; - - public IntegerDatatype(int byteSize) { - this.byteSize = byteSize; - } - - @Override - public boolean isHandlingJavaType(Class type) { - return type == Integer.TYPE || Integer.class.isAssignableFrom(type); - } - - public Integer valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - try { - Integer value = Integer.parseInt(s.trim()); - if (!isValid(value)) { - throw new InvalidValueException("Not a " + getByteSize() + " byte(s) integer: " + s) - ; - } - return value; - } catch (NumberFormatException ex) { - // TODO: UPNP VIOLATION: Some renderers (like PacketVideo TMM Player) send - // RelCount and AbsCount as "NOT_IMPLEMENTED" in GetPositionInfoResponse action. - // The spec says: If not implemented the value shall be Max Integer value. - if(s.equals("NOT_IMPLEMENTED")) { - return getMaxValue(); - } else { - throw new InvalidValueException("Can't convert string to number: " + s, ex); - } - } - } - - public boolean isValid(Integer value) { - return value == null || (value >= getMinValue() && value <= getMaxValue()); - } - - public int getMinValue() { - switch(getByteSize()) { - case 1: - return Byte.MIN_VALUE; - case 2: - return Short.MIN_VALUE; - case 4: - return Integer.MIN_VALUE; - } - throw new IllegalArgumentException("Invalid integer byte size: " + getByteSize()); - } - - public int getMaxValue() { - switch(getByteSize()) { - case 1: - return Byte.MAX_VALUE; - case 2: - return Short.MAX_VALUE; - case 4: - return Integer.MAX_VALUE; - } - throw new IllegalArgumentException("Invalid integer byte size: " + getByteSize()); - } - - public int getByteSize() { - return byteSize; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/InvalidValueException.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/InvalidValueException.java deleted file mode 100644 index b43930c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/InvalidValueException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * Thrown by datatypes and variable value conversion procedures. - * - * @author Christian Bauer - */ -public class InvalidValueException extends RuntimeException { - - public InvalidValueException(String s) { - super(s); - } - - public InvalidValueException(String s, Throwable throwable) { - super(s, throwable); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/NamedDeviceType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/NamedDeviceType.java deleted file mode 100644 index df79a3e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/NamedDeviceType.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * Combines a {@link UDN} with a {@link DeviceType}, string representation - * is separated by double-colon. - * - * @author Christian Bauer - */ -public class NamedDeviceType { - - private UDN udn; - private DeviceType deviceType; - - public NamedDeviceType(UDN udn, DeviceType deviceType) { - this.udn = udn; - this.deviceType = deviceType; - } - - public UDN getUdn() { - return udn; - } - - public DeviceType getDeviceType() { - return deviceType; - } - - public static NamedDeviceType valueOf(String s) throws InvalidValueException { - String[] strings = s.split("::"); - if (strings.length != 2) { - throw new InvalidValueException("Can't parse UDN::DeviceType from: " + s); - } - - UDN udn; - try { - udn = UDN.valueOf(strings[0]); - } catch (Exception ex) { - throw new InvalidValueException("Can't parse UDN: " + strings[0]); - } - - DeviceType deviceType = DeviceType.valueOf(strings[1]); - return new NamedDeviceType(udn, deviceType); - } - - @Override - public String toString() { - return getUdn().toString() + "::" + getDeviceType().toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof NamedDeviceType)) return false; - - NamedDeviceType that = (NamedDeviceType) o; - - if (!deviceType.equals(that.deviceType)) return false; - if (!udn.equals(that.udn)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = udn.hashCode(); - result = 31 * result + deviceType.hashCode(); - return result; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/NamedServiceType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/NamedServiceType.java deleted file mode 100644 index 29e6388..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/NamedServiceType.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * Combines a {@link UDN} with a {@link ServiceType}, string representation - * is separated by double-colon. - * - * @author Christian Bauer - */ -public class NamedServiceType { - - private UDN udn; - private ServiceType serviceType; - - public NamedServiceType(UDN udn, ServiceType serviceType) { - this.udn = udn; - this.serviceType = serviceType; - } - - public UDN getUdn() { - return udn; - } - - public ServiceType getServiceType() { - return serviceType; - } - - public static NamedServiceType valueOf(String s) throws InvalidValueException { - String[] strings = s.split("::"); - if (strings.length != 2) { - throw new InvalidValueException("Can't parse UDN::ServiceType from: " + s); - } - - UDN udn; - try { - udn = UDN.valueOf(strings[0]); - } catch (Exception ex) { - throw new InvalidValueException("Can't parse UDN: " + strings[0]); - } - - ServiceType serviceType = ServiceType.valueOf(strings[1]); - return new NamedServiceType(udn, serviceType); - } - - @Override - public String toString() { - return getUdn().toString() + "::" + getServiceType().toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof NamedServiceType)) return false; - - NamedServiceType that = (NamedServiceType) o; - - if (!serviceType.equals(that.serviceType)) return false; - if (!udn.equals(that.udn)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = udn.hashCode(); - result = 31 * result + serviceType.hashCode(); - return result; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/NotificationSubtype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/NotificationSubtype.java deleted file mode 100644 index 5671230..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/NotificationSubtype.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * Notification message types for SSDP. - * - * @author Christian Bauer - */ -public enum NotificationSubtype { - - ALIVE("ssdp:alive"), - UPDATE("ssdp:update"), - BYEBYE("ssdp:byebye"), - ALL("ssdp:all"), - DISCOVER("ssdp:discover"), - PROPCHANGE("upnp:propchange"); - - private String headerString; - - NotificationSubtype(String headerString) { - this.headerString = headerString; - } - - public String getHeaderString() { - return headerString; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/PragmaType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/PragmaType.java deleted file mode 100644 index ede68ce..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/PragmaType.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.model.types; - -/** - * - * @author Mario Franco - */ -public class PragmaType { - - private String token; - private boolean quote; - private String value; - - public PragmaType(String token, String value, boolean quote) { - this.token = token; - this.value = value; - this.quote = quote; - } - - public PragmaType(String token, String value) { - this.token = token; - this.value = value; - } - - public PragmaType(String value) { - this.token = null; - this.value = value; - } - - - /** - * @return the token - */ - public String getToken() { - return token; - } - - /** - * @return the value - */ - public String getValue() { - return value; - } - - /** - * - * @return String format of Bytes Range for response message header - */ - public String getString() { - String s =""; - if (token!=null) - s += token + "="; - - s += quote? "\""+value+"\"" : value; - return s; - } - - public static PragmaType valueOf(String s) throws InvalidValueException { - if (s.length() != 0) { - String token=null, value = null; - boolean quote = false; - String[] params = s.split("="); - if (params.length > 1) { - token = params[0]; - value = params[1]; - if (value.startsWith("\"") && value.endsWith("\"")) { - quote = true; - value = value.substring(1, value.length()-1); - } - } - else { - value = s; - } - return new PragmaType(token, value, quote); - } - throw new InvalidValueException("Can't parse Bytes Range: " + s); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/ServiceId.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/ServiceId.java deleted file mode 100644 index 32cee1d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/ServiceId.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.fourthline.cling.model.Constants; - -import java.util.logging.Logger; -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -/** - * Represents a service identifier, for example urn:my-domain-namespace:serviceId:MyService123 - * - * @author Christian Bauer - */ -public class ServiceId { - - final private static Logger log = Logger.getLogger(ServiceId.class.getName()); - - public static final String UNKNOWN = "UNKNOWN"; - - public static final Pattern PATTERN = - Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):serviceId:(" + Constants.REGEX_ID + ")"); - - // Note: 'service' vs. 'serviceId' - public static final Pattern BROKEN_PATTERN = - Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):service:(" + Constants.REGEX_ID+ ")"); - - private String namespace; - private String id; - - public ServiceId(String namespace, String id) { - if (namespace != null && !namespace.matches(Constants.REGEX_NAMESPACE)) { - throw new IllegalArgumentException("Service ID namespace contains illegal characters"); - } - this.namespace = namespace; - - if (id != null && !id.matches(Constants.REGEX_ID)) { - throw new IllegalArgumentException("Service ID suffix too long (64) or contains illegal characters"); - } - this.id = id; - } - - public String getNamespace() { - return namespace; - } - - public String getId() { - return id; - } - - public static ServiceId valueOf(String s) throws InvalidValueException { - - ServiceId serviceId = null; - - // First try UDAServiceId parse - try { - serviceId = UDAServiceId.valueOf(s); - } catch (Exception ex) { - // Ignore - } - - if (serviceId != null) - return serviceId; - - // Now try a generic ServiceId parse - Matcher matcher = ServiceId.PATTERN.matcher(s); - if (matcher.matches() && matcher.groupCount() >= 2) { - return new ServiceId(matcher.group(1), matcher.group(2)); - } - - matcher = ServiceId.BROKEN_PATTERN.matcher(s); - if (matcher.matches() && matcher.groupCount() >= 2) { - return new ServiceId(matcher.group(1), matcher.group(2)); - } - - // TODO: UPNP VIOLATION: Kodak Media Server doesn't provide any service ID token - // urn:upnp-org:serviceId: - matcher = Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):serviceId:").matcher(s); - if (matcher.matches() && matcher.groupCount() >= 1) { - log.warning("UPnP specification violation, no service ID token, defaulting to " + UNKNOWN + ": " + s); - return new ServiceId(matcher.group(1), UNKNOWN); - } - - // TODO: UPNP VIOLATION: PS Audio Bridge has invalid service IDs - String tokens[] = s.split("[:]"); - if (tokens.length == 4) { - log.warning("UPnP specification violation, trying a simple colon-split of: " + s); - return new ServiceId(tokens[1], tokens[3]); - } - - throw new InvalidValueException("Can't parse service ID string (namespace/id): " + s); - } - - @Override - public String toString() { - return "urn:" + getNamespace() + ":serviceId:" + getId(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof ServiceId)) return false; - - ServiceId serviceId = (ServiceId) o; - - if (!id.equals(serviceId.id)) return false; - if (!namespace.equals(serviceId.namespace)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = namespace.hashCode(); - result = 31 * result + id.hashCode(); - return result; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/ServiceType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/ServiceType.java deleted file mode 100644 index 2d3f095..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/ServiceType.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.fourthline.cling.model.Constants; - -import java.util.logging.Logger; -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -/** - * Represents a service type, for example urn:my-domain-namespace:service:MyService:1. - *

- * Although decimal versions are accepted and parsed, the version used for - * comparison is only the integer withou the fraction. - *

- * - * @author Christian Bauer - */ -public class ServiceType { - - final private static Logger log = Logger.getLogger(ServiceType.class.getName()); - - public static final Pattern PATTERN = - Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):service:(" + Constants.REGEX_TYPE + "):([0-9]+).*"); - - // Note: 'serviceId' vs. 'service' - public static final Pattern BROKEN_PATTERN = - Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):serviceId:(" + Constants.REGEX_TYPE + "):([0-9]+).*"); - - private String namespace; - private String type; - private int version = 1; - - public ServiceType(String namespace, String type) { - this(namespace, type, 1); - } - - public ServiceType(String namespace, String type, int version) { - - if (namespace != null && !namespace.matches(Constants.REGEX_NAMESPACE)) { - throw new IllegalArgumentException("Service type namespace contains illegal characters"); - } - this.namespace = namespace; - - if (type != null && !type.matches(Constants.REGEX_TYPE)) { - throw new IllegalArgumentException("Service type suffix too long (64) or contains illegal characters"); - } - this.type = type; - - this.version = version; - } - - public String getNamespace() { - return namespace; - } - - public String getType() { - return type; - } - - public int getVersion() { - return version; - } - - /** - * @return Either a {@link UDAServiceType} or a more generic {@link ServiceType}. - */ - public static ServiceType valueOf(String s) throws InvalidValueException { - - if (s == null) - throw new InvalidValueException("Can't parse null string"); - - ServiceType serviceType = null; - - // Sometimes crazy UPnP devices deliver spaces in a URN, don't ask... - s = s.replaceAll("\\s", ""); - - // First try UDAServiceType parse - try { - serviceType = UDAServiceType.valueOf(s); - } catch (Exception ex) { - // Ignore - } - - if (serviceType != null) - return serviceType; - - // Now try a generic ServiceType parse - try { - Matcher matcher = ServiceType.PATTERN.matcher(s); - if (matcher.matches() && matcher.groupCount() >= 3) { - return new ServiceType(matcher.group(1), matcher.group(2), Integer.valueOf(matcher.group(3))); - } - - matcher = ServiceType.BROKEN_PATTERN.matcher(s); - if (matcher.matches() && matcher.groupCount() >= 3) { - return new ServiceType(matcher.group(1), matcher.group(2), Integer.valueOf(matcher.group(3))); - } - - // TODO: UPNP VIOLATION: EyeTV Netstream uses colons in service type token - // urn:schemas-microsoft-com:service:pbda:tuner:1 - matcher = Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):service:(.+?):([0-9]+).*").matcher(s); - if (matcher.matches() && matcher.groupCount() >= 3) { - String cleanToken = matcher.group(2).replaceAll("[^a-zA-Z_0-9\\-]", "-"); - log.warning( - "UPnP specification violation, replacing invalid service type token '" - + matcher.group(2) - + "' with: " - + cleanToken - ); - return new ServiceType(matcher.group(1), cleanToken, Integer.valueOf(matcher.group(3))); - } - - // TODO: UPNP VIOLATION: Ceyton InfiniTV uses colons in service type token and 'serviceId' instead of 'service' - // urn:schemas-opencable-com:serviceId:dri2:debug:1 - matcher = Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):serviceId:(.+?):([0-9]+).*").matcher(s); - if (matcher.matches() && matcher.groupCount() >= 3) { - String cleanToken = matcher.group(2).replaceAll("[^a-zA-Z_0-9\\-]", "-"); - log.warning( - "UPnP specification violation, replacing invalid service type token '" - + matcher.group(2) - + "' with: " - + cleanToken - ); - return new ServiceType(matcher.group(1), cleanToken, Integer.valueOf(matcher.group(3))); - } - } catch (RuntimeException e) { - throw new InvalidValueException(String.format( - "Can't parse service type string (namespace/type/version) '%s': %s", s, e.toString() - )); - } - - throw new InvalidValueException("Can't parse service type string (namespace/type/version): " + s); - } - - /** - * @return true if this type's namespace/name matches the other type's namespace/name and - * this type's version is equal or higher than the given types version. - */ - public boolean implementsVersion(ServiceType that) { - if (that == null) return false; - if (!namespace.equals(that.namespace)) return false; - if (!type.equals(that.type)) return false; - if (version < that.version) return false; - return true; - } - - public String toFriendlyString() { - return getNamespace() + ":" + getType() + ":" + getVersion(); - } - - @Override - public String toString() { - return "urn:" + getNamespace() + ":service:" + getType() + ":" + getVersion(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof ServiceType)) return false; - - ServiceType that = (ServiceType) o; - - if (version != that.version) return false; - if (!namespace.equals(that.namespace)) return false; - if (!type.equals(that.type)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = namespace.hashCode(); - result = 31 * result + type.hashCode(); - result = 31 * result + version; - return result; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/ShortDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/ShortDatatype.java deleted file mode 100644 index a481011..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/ShortDatatype.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * - * @author Christian Bauer - */ -public class ShortDatatype extends AbstractDatatype { - - @Override - public boolean isHandlingJavaType(Class type) { - return type == Short.TYPE || Short.class.isAssignableFrom(type); - } - - public Short valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - try { - Short value = Short.parseShort(s.trim()); - if (!isValid(value)) { - throw new InvalidValueException("Not a valid short: " + s); - } - return value; - } catch (NumberFormatException ex) { - throw new InvalidValueException("Can't convert string to number: " + s, ex); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/SoapActionType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/SoapActionType.java deleted file mode 100644 index eaca0c6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/SoapActionType.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.ModelUtil; - -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -/** - * Header in SOAP action messages, naturally declaring the same thing as the body of the SOAP message. - * - * @author Christian Bauer - */ -public class SoapActionType { - - public static final String MAGIC_CONTROL_NS = "schemas-upnp-org"; - public static final String MAGIC_CONTROL_TYPE = "control-1-0"; - - public static final Pattern PATTERN_MAGIC_CONTROL = - Pattern.compile(Constants.NS_UPNP_CONTROL_10 +"#("+Constants.REGEX_UDA_NAME+")"); - - public static final Pattern PATTERN = - Pattern.compile("urn:(" + Constants.REGEX_NAMESPACE + "):service:(" + Constants.REGEX_TYPE + "):([0-9]+)#("+Constants.REGEX_UDA_NAME+")"); - - private String namespace; - private String type; - private String actionName; - private Integer version; - - public SoapActionType(ServiceType serviceType, String actionName) { - this(serviceType.getNamespace(), serviceType.getType(), serviceType.getVersion(), actionName); - } - - public SoapActionType(String namespace, String type, Integer version, String actionName) { - this.namespace = namespace; - this.type = type; - this.version = version; - this.actionName = actionName; - - if (actionName != null && !ModelUtil.isValidUDAName(actionName)) { - throw new IllegalArgumentException("Action name contains illegal characters: " + actionName); - } - } - - public String getActionName() { - return actionName; - } - - public String getNamespace() { - return namespace; - } - - public String getType() { - return type; - } - - public Integer getVersion() { - return version; - } - - public static SoapActionType valueOf(String s) throws InvalidValueException { - Matcher magicControlMatcher = SoapActionType.PATTERN_MAGIC_CONTROL.matcher(s); - - try { - if (magicControlMatcher.matches()) { - return new SoapActionType(MAGIC_CONTROL_NS, MAGIC_CONTROL_TYPE, null, magicControlMatcher.group(1)); // throws IllegalArgumentException - } - - Matcher matcher = SoapActionType.PATTERN.matcher(s); - if (matcher.matches()) - return new SoapActionType(matcher.group(1), matcher.group(2), Integer.valueOf(matcher.group(3)), matcher.group(4)); - - } catch(RuntimeException e) { - throw new InvalidValueException(String.format( - "Can't parse action type string (namespace/type/version#actionName) '%s': %s", s, e.toString() - )); - } - throw new InvalidValueException("Can't parse action type string (namespace/type/version#actionName): " + s); - } - - public ServiceType getServiceType() { - if (version == null) return null; - return new ServiceType(namespace, type, version); - } - - @Override - public String toString() { - return getTypeString() + "#" + getActionName(); - } - - public String getTypeString() { - if (version == null) { - return "urn:" + getNamespace() + ":" + getType(); - } else { - return "urn:" + getNamespace() + ":service:" + getType() + ":" + getVersion(); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof SoapActionType)) return false; - - SoapActionType that = (SoapActionType) o; - - if (!actionName.equals(that.actionName)) return false; - if (!namespace.equals(that.namespace)) return false; - if (!type.equals(that.type)) return false; - if (version != null ? !version.equals(that.version) : that.version != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = namespace.hashCode(); - result = 31 * result + type.hashCode(); - result = 31 * result + actionName.hashCode(); - result = 31 * result + (version != null ? version.hashCode() : 0); - return result; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/StringDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/StringDatatype.java deleted file mode 100644 index 933c6f5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/StringDatatype.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -public class StringDatatype extends AbstractDatatype { - - public StringDatatype() { - } - - public String valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - return s; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDADeviceType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDADeviceType.java deleted file mode 100644 index e9d304f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDADeviceType.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.fourthline.cling.model.Constants; - -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -/** - * Device type with a fixed schemas-upnp-org namespace. - * - * @author Christian Bauer - */ -public class UDADeviceType extends DeviceType { - - public static final String DEFAULT_NAMESPACE = "schemas-upnp-org"; - - // This pattern also accepts decimal versions, not only integers (as would be required by UDA), but cuts off fractions - public static final Pattern PATTERN = - Pattern.compile("urn:" + DEFAULT_NAMESPACE + ":device:(" + Constants.REGEX_TYPE + "):([0-9]+).*"); - - public UDADeviceType(String type) { - super(DEFAULT_NAMESPACE, type, 1); - } - - public UDADeviceType(String type, int version) { - super(DEFAULT_NAMESPACE, type, version); - } - - public static UDADeviceType valueOf(String s) throws InvalidValueException { - Matcher matcher = PATTERN.matcher(s); - - try { - if (matcher.matches()) - return new UDADeviceType(matcher.group(1), Integer.valueOf(matcher.group(2))); - } catch(RuntimeException e) { - throw new InvalidValueException(String.format( - "Can't parse UDA device type string (namespace/type/version) '%s': %s", s, e.toString() - )); - } - throw new InvalidValueException("Can't parse UDA device type string (namespace/type/version): " + s); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDAServiceId.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDAServiceId.java deleted file mode 100644 index 8996421..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDAServiceId.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.fourthline.cling.model.Constants; - -import java.util.logging.Logger; -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -/** - * Service identifier with a fixed upnp-org namespace. - *

- * Also accepts the namespace sometimes used by broken devices, schemas-upnp-org. - *

- * - * @author Christian Bauer - */ -public class UDAServiceId extends ServiceId { - - private static Logger log = Logger.getLogger(UDAServiceId.class.getName()); - - public static final String DEFAULT_NAMESPACE = "upnp-org"; - public static final String BROKEN_DEFAULT_NAMESPACE = "schemas-upnp-org"; // TODO: UPNP VIOLATION: Intel UPnP tools! - - public static final Pattern PATTERN = - Pattern.compile("urn:" + DEFAULT_NAMESPACE + ":serviceId:(" + Constants.REGEX_ID+ ")"); - - // Note: 'service' vs. 'serviceId' - public static final Pattern BROKEN_PATTERN = - Pattern.compile("urn:" + BROKEN_DEFAULT_NAMESPACE + ":service:(" + Constants.REGEX_ID+ ")"); - - public UDAServiceId(String id) { - super(DEFAULT_NAMESPACE, id); - } - - public static UDAServiceId valueOf(String s) throws InvalidValueException { - Matcher matcher = UDAServiceId.PATTERN.matcher(s); - if (matcher.matches() && matcher.groupCount() >= 1) { - return new UDAServiceId(matcher.group(1)); - } - - matcher = UDAServiceId.BROKEN_PATTERN.matcher(s); - if (matcher.matches() && matcher.groupCount() >= 1) { - return new UDAServiceId(matcher.group(1)); - } - - // TODO: UPNP VIOLATION: Handle garbage sent by Eyecon Android app - matcher = Pattern.compile("urn:upnp-orgerviceId:urnchemas-upnp-orgervice:(" + Constants.REGEX_ID + ")").matcher(s); - if (matcher.matches()) { - log.warning("UPnP specification violation, recovering from Eyecon garbage: " + s); - return new UDAServiceId(matcher.group(1)); - } - - // Some devices just set the last token of the Service ID, e.g. 'ContentDirectory' - if("ContentDirectory".equals(s) || - "ConnectionManager".equals(s) || - "RenderingControl".equals(s) || - "AVTransport".equals(s)) { - log.warning("UPnP specification violation, fixing broken Service ID: " + s); - return new UDAServiceId(s); - } - - throw new InvalidValueException("Can't parse UDA service ID string (upnp-org/id): " + s); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDAServiceType.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDAServiceType.java deleted file mode 100644 index 3e0cab9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDAServiceType.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.fourthline.cling.model.Constants; - -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -/** - * Service type with a fixed schemas-upnp-org namespace. - * - * @author Christian Bauer - */ -public class UDAServiceType extends ServiceType { - - public static final String DEFAULT_NAMESPACE = "schemas-upnp-org"; - - // This pattern also accepts decimal versions, not only integers (as would be required by UDA), but cuts off fractions - public static final Pattern PATTERN = - Pattern.compile("urn:" + DEFAULT_NAMESPACE + ":service:(" + Constants.REGEX_TYPE + "):([0-9]+).*"); - - public UDAServiceType(String type) { - this(type, 1); - } - - public UDAServiceType(String type, int version) { - super(DEFAULT_NAMESPACE, type, version); - } - - public static UDAServiceType valueOf(String s) throws InvalidValueException { - Matcher matcher = UDAServiceType.PATTERN.matcher(s); - - try { - if (matcher.matches()) - return new UDAServiceType(matcher.group(1), Integer.valueOf(matcher.group(2))); - } catch (RuntimeException e) { - throw new InvalidValueException(String.format( - "Can't parse UDA service type string (namespace/type/version) '%s': %s", s, e.toString())); - } - throw new InvalidValueException("Can't parse UDA service type string (namespace/type/version): " + s); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDN.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDN.java deleted file mode 100644 index bb965a8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UDN.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import org.fourthline.cling.model.ModelUtil; - - -import java.io.UnsupportedEncodingException; -import java.util.UUID; -import java.security.MessageDigest; -import java.math.BigInteger; -import java.util.logging.Logger; - -/** - * A unique device name. - *

- * UDA 1.0 does not specify a UUID format, however, UDA 1.1 specifies a format that is compatible - * with java.util.UUID variant 4. You can use any identifier string you like. - *

- *

- * You'll most likely need the {@link #uniqueSystemIdentifier(String)} method sooner or later. - *

- * - * @author Christian Bauer - */ -public class UDN { - - final private static Logger log = Logger.getLogger(UDN.class.getName()); - - public static final String PREFIX = "uuid:"; - - private String identifierString; - - /** - * @param identifierString The identifier string without the "uuid:" prefix. - */ - public UDN(String identifierString) { - this.identifierString = identifierString; - } - - public UDN(UUID uuid) { - this.identifierString = uuid.toString(); - } - - public boolean isUDA11Compliant() { - try { - UUID.fromString(identifierString); - return true; - } catch (IllegalArgumentException ex) { - return false; - } - } - - public String getIdentifierString() { - return identifierString; - } - - public static UDN valueOf(String udnString) { - return new UDN(udnString.startsWith(PREFIX) ? udnString.substring(PREFIX.length()) : udnString); - } - - /** - * Generates a global unique identifier that is the same every time this method is invoked on the same machine with - * the same argument. - *

- * This method combines the first non-loopback network interface's MAC address with given salt to generate a - * globally unique identifier. In other words, every time you call this method with the same salt on the same - * machine, you get the same identifier. If you use the same salt on a different machine, a different identifier - * will be generated. - *

- *

- * Note for Android users: This method does not generate unique identifiers on Android devices and will - * throw an exception. We can't get details such as the hostname or MAC address on Android. Instead, - * construct a UDN with new UDN(UUID). When your application is first started, generate all - * UUIDs needed for your UPnP devices and store them in your Android preferences. Then, use the stored - * UUID to create a UDN every time your application starts. - *

- *

- * Control points can remember your device's identifier, it will and should be the same every time - * your device is powered up. - *

- * - * @param salt An arbitrary string that uniquely identifies the device on the current system, e.g. "MyMediaServer". - * @return A global unique identifier, stable for the current system and salt. - */ - public static UDN uniqueSystemIdentifier(String salt) { - StringBuilder systemSalt = new StringBuilder(); - - // Bug: On Android, NetworkInterface.isLoopback() isn't implemented - if (!ModelUtil.ANDROID_RUNTIME) { - try { - systemSalt.append(new String(ModelUtil.getFirstNetworkInterfaceHardwareAddress(), "UTF-8")); - } catch (UnsupportedEncodingException ex) { - // If your JVM doesn't support utf-8, you have bigger problems - throw new RuntimeException(ex); - } - } else { - throw new RuntimeException( - "This method does not create a unique identifier on Android, see the Javadoc and " + - "use new UDN(UUID) instead!" - ); - } - - try { - byte[] hash = MessageDigest.getInstance("MD5").digest(systemSalt.toString().getBytes("UTF-8")); - return new UDN( - new UUID( - new BigInteger(-1, hash).longValue(), - salt.hashCode() - ) - ); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - @Override - public String toString() { - return PREFIX + getIdentifierString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof UDN)) return false; - UDN udn = (UDN) o; - return identifierString.equals(udn.identifierString); - } - - @Override - public int hashCode() { - return identifierString.hashCode(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/URIDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/URIDatatype.java deleted file mode 100644 index 1b03906..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/URIDatatype.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import java.net.URI; -import java.net.URISyntaxException; - -/** - * @author Christian Bauer - */ -public class URIDatatype extends AbstractDatatype { - - public URIDatatype() { - } - - public URI valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - try { - return new URI(s); - } catch (URISyntaxException ex) { - throw new InvalidValueException(ex.getMessage(), ex); - } - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerFourBytes.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerFourBytes.java deleted file mode 100644 index e696090..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerFourBytes.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -final public class UnsignedIntegerFourBytes extends UnsignedVariableInteger { - - public UnsignedIntegerFourBytes(long value) throws NumberFormatException { - super(value); - } - - public UnsignedIntegerFourBytes(String s) throws NumberFormatException { - super(s); - } - - public Bits getBits() { - return Bits.THIRTYTWO; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerFourBytesDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerFourBytesDatatype.java deleted file mode 100644 index f8b1ba4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerFourBytesDatatype.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -public class UnsignedIntegerFourBytesDatatype extends AbstractDatatype { - - public UnsignedIntegerFourBytes valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - try { - return new UnsignedIntegerFourBytes(s); - } catch (NumberFormatException ex) { - throw new InvalidValueException("Can't convert string to number or not in range: " + s, ex); - } - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerOneByte.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerOneByte.java deleted file mode 100644 index 89165d0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerOneByte.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -final public class UnsignedIntegerOneByte extends UnsignedVariableInteger { - - public UnsignedIntegerOneByte(long value) throws NumberFormatException { - super(value); - } - - public UnsignedIntegerOneByte(String s) throws NumberFormatException { - super(s); - } - - public Bits getBits() { - return Bits.EIGHT; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerOneByteDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerOneByteDatatype.java deleted file mode 100644 index 94a573c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerOneByteDatatype.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -public class UnsignedIntegerOneByteDatatype extends AbstractDatatype { - - public UnsignedIntegerOneByte valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - try { - return new UnsignedIntegerOneByte(s); - } catch (NumberFormatException ex) { - throw new InvalidValueException("Can't convert string to number or not in range: " + s, ex); - } - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerTwoBytes.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerTwoBytes.java deleted file mode 100644 index 61b48c4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerTwoBytes.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -final public class UnsignedIntegerTwoBytes extends UnsignedVariableInteger { - - public UnsignedIntegerTwoBytes(long value) throws NumberFormatException { - super(value); - } - - public UnsignedIntegerTwoBytes(String s) throws NumberFormatException { - super(s); - } - - public Bits getBits() { - return Bits.SIXTEEN; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerTwoBytesDatatype.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerTwoBytesDatatype.java deleted file mode 100644 index aa56540..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedIntegerTwoBytesDatatype.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -/** - * @author Christian Bauer - */ -public class UnsignedIntegerTwoBytesDatatype extends AbstractDatatype { - - public UnsignedIntegerTwoBytes valueOf(String s) throws InvalidValueException { - if (s.equals("")) return null; - try { - return new UnsignedIntegerTwoBytes(s); - } catch (NumberFormatException ex) { - throw new InvalidValueException("Can't convert string to number or not in range: " + s, ex); - } - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedVariableInteger.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedVariableInteger.java deleted file mode 100644 index e139e0f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/UnsignedVariableInteger.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types; - -import java.util.logging.Logger; - -/** - * A crude solution for unsigned "non-negative" types in UPnP, not usable for any arithmetic. - * - * @author Christian Bauer - */ -public abstract class UnsignedVariableInteger { - - final private static Logger log = Logger.getLogger(UnsignedVariableInteger.class.getName()); - - public enum Bits { - EIGHT(0xffL), - SIXTEEN(0xffffL), - TWENTYFOUR(0xffffffL), - THIRTYTWO(0xffffffffL); - - private long maxValue; - - Bits(long maxValue) { - this.maxValue = maxValue; - } - - public long getMaxValue() { - return maxValue; - } - } - - protected long value; - - protected UnsignedVariableInteger() { - } - - public UnsignedVariableInteger(long value) throws NumberFormatException { - setValue(value); - } - - public UnsignedVariableInteger(String s) throws NumberFormatException { - if (s.startsWith("-")) { - // Don't throw exception, just cut it! - // TODO: UPNP VIOLATION: Twonky Player returns "-1" as the track number - log.warning("Invalid negative integer value '" + s + "', assuming value 0!"); - s = "0"; - } - setValue(Long.parseLong(s.trim())); - } - - protected UnsignedVariableInteger setValue(long value) { - isInRange(value); - this.value = value; - return this; - } - - public Long getValue() { - return value; - } - - public void isInRange(long value) throws NumberFormatException { - if (value < getMinValue() || value > getBits().getMaxValue()) { - throw new NumberFormatException("Value must be between " + getMinValue() + " and " + getBits().getMaxValue() + ": " + value); - } - } - - public int getMinValue() { - return 0; - } - - public abstract Bits getBits(); - - public UnsignedVariableInteger increment(boolean rolloverToOne) { - if (value + 1 > getBits().getMaxValue()) { - value = rolloverToOne ? 1 : 0; - } else { - value++; - } - return this; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - UnsignedVariableInteger that = (UnsignedVariableInteger) o; - - if (value != that.value) return false; - - return true; - } - - @Override - public int hashCode() { - return (int) (value ^ (value >>> 32)); - } - - @Override - public String toString() { - return Long.toString(value); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSV.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSV.java deleted file mode 100644 index c5c631e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSV.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.model.ModelUtil; -import org.seamless.util.Reflections; - -import java.util.ArrayList; -import java.util.List; - -/** - * Transforms a state variable value from/to strings of comma-separated elements. - *

- * A concrete implementation of this interface knows how to transform values of the - * declared type into a string of comma-separated list of elements, and how to read - * such strings back into individual values. - *

- *

- * Your action method returns a CSV<...> instance as an output argument. It can - * also accept a concrecte subclass of this type as an input argument, e.g. CSVString. - * This type extends a regular List, so within your action method you can - * handle the elements as usual. - *

- * - * @author Christian Bauer - */ -public abstract class CSV extends ArrayList { - - protected final Datatype.Builtin datatype; - - public CSV() { - datatype = getBuiltinDatatype(); - } - - public CSV(String s) throws InvalidValueException { - datatype = getBuiltinDatatype(); - addAll(parseString(s)); - } - - protected List parseString(String s) throws InvalidValueException { - String[] strings = ModelUtil.fromCommaSeparatedList(s); - List values = new ArrayList<>(); - for (String string : strings) { - values.add(datatype.getDatatype().valueOf(string)); - } - return values; - } - - protected Datatype.Builtin getBuiltinDatatype() throws InvalidValueException { - Class csvType = Reflections.getTypeArguments(ArrayList.class, getClass()).get(0); - Datatype.Default defaultType = Datatype.Default.getByJavaType(csvType); - if (defaultType == null) { - throw new InvalidValueException("No built-in UPnP datatype for Java type of CSV: " + csvType); - } - return defaultType.getBuiltinType(); - } - - @Override - public String toString() { - List stringValues = new ArrayList<>(); - for (T t : this) { - stringValues.add(datatype.getDatatype().getString(t)); - } - return ModelUtil.toCommaSeparatedList(stringValues.toArray(new Object[stringValues.size()])); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVBoolean.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVBoolean.java deleted file mode 100644 index b72c721..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVBoolean.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * @author Christian Bauer - */ -public class CSVBoolean extends CSV { - - public CSVBoolean() { - } - - public CSVBoolean(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVBytes.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVBytes.java deleted file mode 100644 index d4dedfd..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVBytes.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * @author Christian Bauer - */ -public class CSVBytes extends CSV { - - public CSVBytes() { - } - - public CSVBytes(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVCharacter.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVCharacter.java deleted file mode 100644 index 84f5d85..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVCharacter.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * @author Christian Bauer - */ -public class CSVCharacter extends CSV { - - public CSVCharacter() { - } - - public CSVCharacter(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVDate.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVDate.java deleted file mode 100644 index b5f59d5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVDate.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; - -import java.util.Date; - -/** - * @author Christian Bauer - */ -public class CSVDate extends CSV { - - public CSVDate() { - } - - public CSVDate(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVDouble.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVDouble.java deleted file mode 100644 index 4ddd8ec..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVDouble.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * @author Christian Bauer - */ -public class CSVDouble extends CSV { - - public CSVDouble() { - } - - public CSVDouble(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVFloat.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVFloat.java deleted file mode 100644 index 800bd8b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVFloat.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * @author Christian Bauer - */ -public class CSVFloat extends CSV { - - public CSVFloat() { - } - - public CSVFloat(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVInteger.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVInteger.java deleted file mode 100644 index d93b043..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVInteger.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * @author Christian Bauer - */ -public class CSVInteger extends CSV { - - public CSVInteger() { - } - - public CSVInteger(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVShort.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVShort.java deleted file mode 100644 index a25fb11..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVShort.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * @author Christian Bauer - */ -public class CSVShort extends CSV { - - public CSVShort() { - } - - public CSVShort(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVString.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVString.java deleted file mode 100644 index 6a0f5ea..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVString.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * @author Christian Bauer - */ -public class CSVString extends CSV { - - public CSVString() { - } - - public CSVString(String s) throws InvalidValueException { - super(s); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVURI.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVURI.java deleted file mode 100644 index 80e1f30..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVURI.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class CSVURI extends CSV { - - public CSVURI() { - } - - public CSVURI(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerFourBytes.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerFourBytes.java deleted file mode 100644 index 5b56467..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerFourBytes.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -/** - * @author Christian Bauer - */ -public class CSVUnsignedIntegerFourBytes extends CSV { - - public CSVUnsignedIntegerFourBytes() { - } - - public CSVUnsignedIntegerFourBytes(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerOneByte.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerOneByte.java deleted file mode 100644 index 6759b1b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerOneByte.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.model.types.UnsignedIntegerOneByte; - -/** - * @author Christian Bauer - */ -public class CSVUnsignedIntegerOneByte extends CSV { - - public CSVUnsignedIntegerOneByte() { - } - - public CSVUnsignedIntegerOneByte(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerTwoBytes.java b/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerTwoBytes.java deleted file mode 100644 index a087edb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/model/types/csv/CSVUnsignedIntegerTwoBytes.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.model.types.csv; - -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes; - -/** - * @author Christian Bauer - */ -public class CSVUnsignedIntegerTwoBytes extends CSV { - - public CSVUnsignedIntegerTwoBytes() { - } - - public CSVUnsignedIntegerTwoBytes(String s) throws InvalidValueException { - super(s); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolCreationException.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolCreationException.java deleted file mode 100644 index 7db6b21..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolCreationException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol; - -/** - * Recoverable error, thrown when no protocol is available to handle a UPnP message. - * - * @author Christian Bauer - */ -public class ProtocolCreationException extends Exception { - - public ProtocolCreationException(String s) { - super(s); - } - - public ProtocolCreationException(String s, Throwable throwable) { - super(s, throwable); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolFactory.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolFactory.java deleted file mode 100644 index 22f81d9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolFactory.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.gena.LocalGENASubscription; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.protocol.async.SendingNotificationAlive; -import org.fourthline.cling.protocol.async.SendingNotificationByebye; -import org.fourthline.cling.protocol.async.SendingSearch; -import org.fourthline.cling.protocol.sync.SendingAction; -import org.fourthline.cling.protocol.sync.SendingEvent; -import org.fourthline.cling.protocol.sync.SendingRenewal; -import org.fourthline.cling.protocol.sync.SendingSubscribe; -import org.fourthline.cling.protocol.sync.SendingUnsubscribe; - -import java.net.URL; - -/** - * Factory for UPnP protocols, the core implementation of the UPnP specification. - *

- * This factory creates an executable protocol either based on the received UPnP messsage, or - * on local device/search/service metadata). A protocol is an aspect of the UPnP specification, - * you can override individual protocols to customize the behavior of the UPnP stack. - *

- *

- * An implementation has to be thread-safe. - *

- * - * @author Christian Bauer - */ -public interface ProtocolFactory { - - public UpnpService getUpnpService(); - - /** - * Creates a {@link org.fourthline.cling.protocol.async.ReceivingNotification}, - * {@link org.fourthline.cling.protocol.async.ReceivingSearch}, - * or {@link org.fourthline.cling.protocol.async.ReceivingSearchResponse} protocol. - * - * @param message The incoming message, either {@link org.fourthline.cling.model.message.UpnpRequest} or - * {@link org.fourthline.cling.model.message.UpnpResponse}. - * @return The appropriate protocol that handles the messages or null if the message should be dropped. - * @throws ProtocolCreationException If no protocol could be found for the message. - */ - public ReceivingAsync createReceivingAsync(IncomingDatagramMessage message) throws ProtocolCreationException; - - /** - * Creates a {@link org.fourthline.cling.protocol.sync.ReceivingRetrieval}, - * {@link org.fourthline.cling.protocol.sync.ReceivingAction}, - * {@link org.fourthline.cling.protocol.sync.ReceivingSubscribe}, - * {@link org.fourthline.cling.protocol.sync.ReceivingUnsubscribe}, or - * {@link org.fourthline.cling.protocol.sync.ReceivingEvent} protocol. - * - * @param requestMessage The incoming message, examime {@link org.fourthline.cling.model.message.UpnpRequest.Method} - * to determine the protocol. - * @return The appropriate protocol that handles the messages. - * @throws ProtocolCreationException If no protocol could be found for the message. - */ - public ReceivingSync createReceivingSync(StreamRequestMessage requestMessage) throws ProtocolCreationException; - - /** - * Called by the {@link org.fourthline.cling.registry.Registry}, creates a protocol for announcing local devices. - */ - public SendingNotificationAlive createSendingNotificationAlive(LocalDevice localDevice); - - /** - * Called by the {@link org.fourthline.cling.registry.Registry}, creates a protocol for announcing local devices. - */ - public SendingNotificationByebye createSendingNotificationByebye(LocalDevice localDevice); - - /** - * Called by the {@link org.fourthline.cling.controlpoint.ControlPoint}, creates a protocol for a multicast search. - */ - public SendingSearch createSendingSearch(UpnpHeader searchTarget, int mxSeconds); - - /** - * Called by the {@link org.fourthline.cling.controlpoint.ControlPoint}, creates a protocol for executing an action. - */ - public SendingAction createSendingAction(ActionInvocation actionInvocation, URL controlURL); - - /** - * Called by the {@link org.fourthline.cling.controlpoint.ControlPoint}, creates a protocol for GENA subscription. - */ - public SendingSubscribe createSendingSubscribe(RemoteGENASubscription subscription) throws ProtocolCreationException; - - /** - * Called by the {@link org.fourthline.cling.controlpoint.ControlPoint}, creates a protocol for GENA renewal. - */ - public SendingRenewal createSendingRenewal(RemoteGENASubscription subscription); - - /** - * Called by the {@link org.fourthline.cling.controlpoint.ControlPoint}, creates a protocol for GENA unsubscription. - */ - public SendingUnsubscribe createSendingUnsubscribe(RemoteGENASubscription subscription); - - /** - * Called by the {@link org.fourthline.cling.model.gena.GENASubscription}, creates a protocol for sending GENA events. - */ - public SendingEvent createSendingEvent(LocalGENASubscription subscription); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolFactoryImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolFactoryImpl.java deleted file mode 100644 index 985601b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/ProtocolFactoryImpl.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.Namespace; -import org.fourthline.cling.model.NetworkAddress; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.gena.LocalGENASubscription; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.model.types.NamedServiceType; -import org.fourthline.cling.model.types.NotificationSubtype; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.protocol.async.ReceivingNotification; -import org.fourthline.cling.protocol.async.ReceivingSearch; -import org.fourthline.cling.protocol.async.ReceivingSearchResponse; -import org.fourthline.cling.protocol.async.SendingNotificationAlive; -import org.fourthline.cling.protocol.async.SendingNotificationByebye; -import org.fourthline.cling.protocol.async.SendingSearch; -import org.fourthline.cling.protocol.sync.ReceivingAction; -import org.fourthline.cling.protocol.sync.ReceivingEvent; -import org.fourthline.cling.protocol.sync.ReceivingRetrieval; -import org.fourthline.cling.protocol.sync.ReceivingSubscribe; -import org.fourthline.cling.protocol.sync.ReceivingUnsubscribe; -import org.fourthline.cling.protocol.sync.SendingAction; -import org.fourthline.cling.protocol.sync.SendingEvent; -import org.fourthline.cling.protocol.sync.SendingRenewal; -import org.fourthline.cling.protocol.sync.SendingSubscribe; -import org.fourthline.cling.protocol.sync.SendingUnsubscribe; -import org.fourthline.cling.transport.RouterException; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import java.net.URI; -import java.net.URL; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Default implementation, directly instantiates the appropriate protocols. - * - * @author Christian Bauer - */ -@ApplicationScoped -public class ProtocolFactoryImpl implements ProtocolFactory { - - final private static Logger log = Logger.getLogger(ProtocolFactory.class.getName()); - - protected final UpnpService upnpService; - - protected ProtocolFactoryImpl() { - upnpService = null; - } - - @Inject - public ProtocolFactoryImpl(UpnpService upnpService) { - log.fine("Creating ProtocolFactory: " + getClass().getName()); - this.upnpService = upnpService; - } - - public UpnpService getUpnpService() { - return upnpService; - } - - public ReceivingAsync createReceivingAsync(IncomingDatagramMessage message) throws ProtocolCreationException { - if (log.isLoggable(Level.FINE)) { - log.fine("Creating protocol for incoming asynchronous: " + message); - } - - if (message.getOperation() instanceof UpnpRequest) { - IncomingDatagramMessage incomingRequest = message; - - switch (incomingRequest.getOperation().getMethod()) { - case NOTIFY: - return isByeBye(incomingRequest) || isSupportedServiceAdvertisement(incomingRequest) - ? createReceivingNotification(incomingRequest) : null; - case MSEARCH: - return createReceivingSearch(incomingRequest); - } - - } else if (message.getOperation() instanceof UpnpResponse) { - IncomingDatagramMessage incomingResponse = message; - - return isSupportedServiceAdvertisement(incomingResponse) - ? createReceivingSearchResponse(incomingResponse) : null; - } - - throw new ProtocolCreationException("Protocol for incoming datagram message not found: " + message); - } - - protected ReceivingAsync createReceivingNotification(IncomingDatagramMessage incomingRequest) { - return new ReceivingNotification(getUpnpService(), incomingRequest); - } - - protected ReceivingAsync createReceivingSearch(IncomingDatagramMessage incomingRequest) { - return new ReceivingSearch(getUpnpService(), incomingRequest); - } - - protected ReceivingAsync createReceivingSearchResponse(IncomingDatagramMessage incomingResponse) { - return new ReceivingSearchResponse(getUpnpService(), incomingResponse); - } - - // DO NOT USE THE PARSED/TYPED MSG HEADERS! THIS WOULD DEFEAT THE PURPOSE OF THIS OPTIMIZATION! - - protected boolean isByeBye(IncomingDatagramMessage message) { - String ntsHeader = message.getHeaders().getFirstHeader(UpnpHeader.Type.NTS.getHttpName()); - return ntsHeader != null && ntsHeader.equals(NotificationSubtype.BYEBYE.getHeaderString()); - } - - protected boolean isSupportedServiceAdvertisement(IncomingDatagramMessage message) { - ServiceType[] exclusiveServiceTypes = getUpnpService().getConfiguration().getExclusiveServiceTypes(); - if (exclusiveServiceTypes == null) return false; // Discovery is disabled - if (exclusiveServiceTypes.length == 0) return true; // Any advertisement is fine - - String usnHeader = message.getHeaders().getFirstHeader(UpnpHeader.Type.USN.getHttpName()); - if (usnHeader == null) return false; // Not a service advertisement, drop it - - try { - NamedServiceType nst = NamedServiceType.valueOf(usnHeader); - for (ServiceType exclusiveServiceType : exclusiveServiceTypes) { - if (nst.getServiceType().implementsVersion(exclusiveServiceType)) - return true; - } - } catch (InvalidValueException ex) { - log.finest("Not a named service type header value: " + usnHeader); - } - log.fine("Service advertisement not supported, dropping it: " + usnHeader); - return false; - } - - public ReceivingSync createReceivingSync(StreamRequestMessage message) throws ProtocolCreationException { - log.fine("Creating protocol for incoming synchronous: " + message); - - if (message.getOperation().getMethod().equals(UpnpRequest.Method.GET)) { - - return createReceivingRetrieval(message); - - } else if (getUpnpService().getConfiguration().getNamespace().isControlPath(message.getUri())) { - - if (message.getOperation().getMethod().equals(UpnpRequest.Method.POST)) - return createReceivingAction(message); - - } else if (getUpnpService().getConfiguration().getNamespace().isEventSubscriptionPath(message.getUri())) { - - if (message.getOperation().getMethod().equals(UpnpRequest.Method.SUBSCRIBE)) { - return createReceivingSubscribe(message); - } else if (message.getOperation().getMethod().equals(UpnpRequest.Method.UNSUBSCRIBE)) { - return createReceivingUnsubscribe(message); - } - - } else if (getUpnpService().getConfiguration().getNamespace().isEventCallbackPath(message.getUri())) { - - if (message.getOperation().getMethod().equals(UpnpRequest.Method.NOTIFY)) - return createReceivingEvent(message); - - } else { - - // TODO: UPNP VIOLATION: Onkyo devices send event messages with trailing garbage characters - // /dev/9bb022aa-e922-aab9-682b-aa09e9b9e059/svc/upnp-org/RenderingControl/event/cb192%2e168%2e10%2e38 - // TODO: UPNP VIOLATION: Yamaha does the same - // /dev/9ab0c000-f668-11de-9976-00a0de870fd4/svc/upnp-org/RenderingControl/event/cb> activeStreamServers = - getUpnpService().getRouter().getActiveStreamServers( - subscription.getService().getDevice().getIdentity().getDiscoveredOnLocalAddress() - ); - return new SendingSubscribe(getUpnpService(), subscription, activeStreamServers); - } catch (RouterException ex) { - throw new ProtocolCreationException( - "Failed to obtain local stream servers (for event callback URL creation) from router", - ex - ); - } - } - - public SendingRenewal createSendingRenewal(RemoteGENASubscription subscription) { - return new SendingRenewal(getUpnpService(), subscription); - } - - public SendingUnsubscribe createSendingUnsubscribe(RemoteGENASubscription subscription) { - return new SendingUnsubscribe(getUpnpService(), subscription); - } - - public SendingEvent createSendingEvent(LocalGENASubscription subscription) { - return new SendingEvent(getUpnpService(), subscription); - } - - protected ReceivingRetrieval createReceivingRetrieval(StreamRequestMessage message) { - return new ReceivingRetrieval(getUpnpService(), message); - } - - protected ReceivingAction createReceivingAction(StreamRequestMessage message) { - return new ReceivingAction(getUpnpService(), message); - } - - protected ReceivingSubscribe createReceivingSubscribe(StreamRequestMessage message) { - return new ReceivingSubscribe(getUpnpService(), message); - } - - protected ReceivingUnsubscribe createReceivingUnsubscribe(StreamRequestMessage message) { - return new ReceivingUnsubscribe(getUpnpService(), message); - } - - protected ReceivingEvent createReceivingEvent(StreamRequestMessage message) { - return new ReceivingEvent(getUpnpService(), message); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/ReceivingAsync.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/ReceivingAsync.java deleted file mode 100644 index 2e74cbd..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/ReceivingAsync.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.message.UpnpMessage; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.transport.RouterException; -import org.seamless.util.Exceptions; - -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Supertype for all asynchronously executing protocols, handling reception of UPnP messages. - *

- * After instantiation by the {@link ProtocolFactory}, this protocol run()s and - * calls its own {@link #waitBeforeExecution()} method. By default, the protocol does not wait - * before then proceeding with {@link #execute()}. - *

- * - * @param The type of UPnP message handled by this protocol. - * - * @author Christian Bauer - */ -public abstract class ReceivingAsync implements Runnable { - - final private static Logger log = Logger.getLogger(UpnpService.class.getName()); - - private final UpnpService upnpService; - - private M inputMessage; - - protected ReceivingAsync(UpnpService upnpService, M inputMessage) { - this.upnpService = upnpService; - this.inputMessage = inputMessage; - } - - public UpnpService getUpnpService() { - return upnpService; - } - - public M getInputMessage() { - return inputMessage; - } - - public void run() { - boolean proceed; - try { - proceed = waitBeforeExecution(); - } catch (InterruptedException ex) { - log.info("Protocol wait before execution interrupted (on shutdown?): " + getClass().getSimpleName()); - proceed = false; - } - - if (proceed) { - try { - execute(); - } catch (Exception ex) { - Throwable cause = Exceptions.unwrap(ex); - if (cause instanceof InterruptedException) { - log.log(Level.INFO, "Interrupted protocol '" + getClass().getSimpleName() + "': " + ex, cause); - } else { - throw new RuntimeException( - "Fatal error while executing protocol '" + getClass().getSimpleName() + "': " + ex, ex - ); - } - } - } - } - - /** - * Provides an opportunity to pause before executing the protocol. - * - * @return true (default) if execution should continue after waiting. - * - * @throws InterruptedException If waiting has been interrupted, which also stops execution. - */ - protected boolean waitBeforeExecution() throws InterruptedException { - // Don't wait by default - return true; - } - - protected abstract void execute() throws RouterException; - - protected H getFirstHeader(UpnpHeader.Type headerType, Class subtype) { - return getInputMessage().getHeaders().getFirstHeader(headerType, subtype); - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ")"; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/ReceivingSync.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/ReceivingSync.java deleted file mode 100644 index f3449d3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/ReceivingSync.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.profile.RemoteClientInfo; -import org.fourthline.cling.transport.RouterException; - -import java.util.logging.Logger; - -/** - * Supertype for all synchronously executing protocols, handling reception of UPnP messages and return a response. - *

- * After instantiation by the {@link ProtocolFactory}, this protocol run()s and - * calls its own {@link #waitBeforeExecution()} method. By default, the protocol does not wait - * before then proceeding with {@link #executeSync()}. - *

- *

- * The returned response will be available to the client of this protocol. The - * client will then call either {@link #responseSent(org.fourthline.cling.model.message.StreamResponseMessage)} - * or {@link #responseException(Throwable)}, depending on whether the response was successfully - * delivered. The protocol can override these methods to decide if the whole procedure it is - * implementing was successful or not, including not only creation but also delivery of the response. - *

- * - * @param The type of incoming UPnP message handled by this protocol. - * @param The type of response UPnP message created by this protocol. - * - * @author Christian Bauer - */ -public abstract class ReceivingSync extends ReceivingAsync { - - final private static Logger log = Logger.getLogger(UpnpService.class.getName()); - - final protected RemoteClientInfo remoteClientInfo; - protected OUT outputMessage; - - protected ReceivingSync(UpnpService upnpService, IN inputMessage) { - super(upnpService, inputMessage); - this.remoteClientInfo = new RemoteClientInfo(inputMessage); - } - - public OUT getOutputMessage() { - return outputMessage; - } - - final protected void execute() throws RouterException { - outputMessage = executeSync(); - - if (outputMessage != null && getRemoteClientInfo().getExtraResponseHeaders().size() > 0) { - log.fine("Setting extra headers on response message: " + getRemoteClientInfo().getExtraResponseHeaders().size()); - outputMessage.getHeaders().putAll(getRemoteClientInfo().getExtraResponseHeaders()); - } - } - - protected abstract OUT executeSync() throws RouterException; - - /** - * Called by the client of this protocol after the returned response has been successfully delivered. - *

- * NOOP by default. - *

- */ - public void responseSent(StreamResponseMessage responseMessage) { - } - - /** - * Called by the client of this protocol if the returned response was not delivered. - *

- * NOOP by default. - *

- * - * @param t The reason why the response wasn't delivered. - */ - public void responseException(Throwable t) { - } - - public RemoteClientInfo getRemoteClientInfo() { - return remoteClientInfo; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ")"; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/RetrieveRemoteDescriptors.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/RetrieveRemoteDescriptors.java deleted file mode 100644 index 2cbb663..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/RetrieveRemoteDescriptors.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.binding.xml.DescriptorBindingException; -import org.fourthline.cling.binding.xml.DeviceDescriptorBinder; -import org.fourthline.cling.binding.xml.ServiceDescriptorBinder; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.meta.Icon; -import org.fourthline.cling.model.meta.RemoteDevice; -import org.fourthline.cling.model.meta.RemoteService; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; -import org.fourthline.cling.registry.RegistrationException; -import org.fourthline.cling.transport.RouterException; -import org.seamless.util.Exceptions; - -/** - * Retrieves all remote device XML descriptors, parses them, creates an immutable device and service metadata graph. - *

- * This implementation encapsulates all steps which are necessary to create a fully usable and populated - * device metadata graph of a particular UPnP device. It starts with an unhydrated and typically just - * discovered {@link org.fourthline.cling.model.meta.RemoteDevice}, the only property that has to be available is - * its {@link org.fourthline.cling.model.meta.RemoteDeviceIdentity}. - *

- *

- * This protocol implementation will then retrieve the device's XML descriptor, parse it, and retrieve and - * parse all service descriptors until all device and service metadata has been retrieved. The fully - * hydrated device is then added to the {@link org.fourthline.cling.registry.Registry}. - *

- *

- * Any descriptor retrieval, parsing, or validation error of the metadata will abort this protocol - * with a warning message in the log. - *

- * - * @author Christian Bauer - */ -public class RetrieveRemoteDescriptors implements Runnable { - - final private static Logger log = Logger.getLogger(RetrieveRemoteDescriptors.class.getName()); - - private final UpnpService upnpService; - private RemoteDevice rd; - - private static final Set activeRetrievals = new CopyOnWriteArraySet(); - protected List errorsAlreadyLogged = new ArrayList<>(); - - public RetrieveRemoteDescriptors(UpnpService upnpService, RemoteDevice rd) { - this.upnpService = upnpService; - this.rd = rd; - } - - public UpnpService getUpnpService() { - return upnpService; - } - - public void run() { - - URL deviceURL = rd.getIdentity().getDescriptorURL(); - - // Performance optimization, try to avoid concurrent GET requests for device descriptor, - // if we retrieve it once, we have the hydrated device. There is no different outcome - // processing this several times concurrently. - - if (activeRetrievals.contains(deviceURL)) { - log.finer("Exiting early, active retrieval for URL already in progress: " + deviceURL); - return; - } - - // Exit if it has been discovered already, could be we have been waiting in the executor queue too long - if (getUpnpService().getRegistry().getRemoteDevice(rd.getIdentity().getUdn(), true) != null) { - log.finer("Exiting early, already discovered: " + deviceURL); - return; - } - - try { - activeRetrievals.add(deviceURL); - describe(); - } catch (RouterException ex) { - log.log(Level.WARNING, - "Descriptor retrieval failed: " + deviceURL, - ex - ); - } finally { - activeRetrievals.remove(deviceURL); - } - } - - protected void describe() throws RouterException { - - // All of the following is a very expensive and time consuming procedure, thanks to the - // braindead design of UPnP. Several GET requests, several descriptors, several XML parsing - // steps - all of this could be done with one and it wouldn't make a difference. So every - // call of this method has to be really necessary and rare. - - if(getUpnpService().getRouter() == null) { - log.warning("Router not yet initialized"); - return ; - } - - StreamRequestMessage deviceDescRetrievalMsg; - StreamResponseMessage deviceDescMsg; - - try { - - deviceDescRetrievalMsg = - new StreamRequestMessage(UpnpRequest.Method.GET, rd.getIdentity().getDescriptorURL()); - - // Extra headers - UpnpHeaders headers = - getUpnpService().getConfiguration().getDescriptorRetrievalHeaders(rd.getIdentity()); - if (headers != null) - deviceDescRetrievalMsg.getHeaders().putAll(headers); - - log.fine("Sending device descriptor retrieval message: " + deviceDescRetrievalMsg); - deviceDescMsg = getUpnpService().getRouter().send(deviceDescRetrievalMsg); - - } catch(IllegalArgumentException ex) { - // UpnpRequest constructor can throw IllegalArgumentException on invalid URI - // IllegalArgumentException can also be thrown by Apache HttpClient on blank URI in send() - log.warning( - "Device descriptor retrieval failed: " - + rd.getIdentity().getDescriptorURL() - + ", possibly invalid URL: " + ex); - return ; - } - - if (deviceDescMsg == null) { - log.warning( - "Device descriptor retrieval failed, no response: " + rd.getIdentity().getDescriptorURL() - ); - return; - } - - if (deviceDescMsg.getOperation().isFailed()) { - log.warning( - "Device descriptor retrieval failed: " - + rd.getIdentity().getDescriptorURL() + - ", " - + deviceDescMsg.getOperation().getResponseDetails() - ); - return; - } - - if (!deviceDescMsg.isContentTypeTextUDA()) { - log.fine( - "Received device descriptor without or with invalid Content-Type: " - + rd.getIdentity().getDescriptorURL()); - // We continue despite the invalid UPnP message because we can still hope to convert the content - } - - String descriptorContent = deviceDescMsg.getBodyString(); - if (descriptorContent == null || descriptorContent.length() == 0) { - log.warning("Received empty device descriptor:" + rd.getIdentity().getDescriptorURL()); - return; - } - - log.fine("Received root device descriptor: " + deviceDescMsg); - describe(descriptorContent); - } - - protected void describe(String descriptorXML) throws RouterException { - - boolean notifiedStart = false; - RemoteDevice describedDevice = null; - try { - - DeviceDescriptorBinder deviceDescriptorBinder = - getUpnpService().getConfiguration().getDeviceDescriptorBinderUDA10(); - - describedDevice = deviceDescriptorBinder.describe( - rd, - descriptorXML - ); - - log.fine("Remote device described (without services) notifying listeners: " + describedDevice); - notifiedStart = getUpnpService().getRegistry().notifyDiscoveryStart(describedDevice); - - log.fine("Hydrating described device's services: " + describedDevice); - RemoteDevice hydratedDevice = describeServices(describedDevice); - if (hydratedDevice == null) { - if(!errorsAlreadyLogged.contains(rd.getIdentity().getUdn())) { - errorsAlreadyLogged.add(rd.getIdentity().getUdn()); - log.warning("Device service description failed: " + rd); - } - if (notifiedStart) - getUpnpService().getRegistry().notifyDiscoveryFailure( - describedDevice, - new DescriptorBindingException("Device service description failed: " + rd) - ); - return; - } else { - log.fine("Adding fully hydrated remote device to registry: " + hydratedDevice); - // The registry will do the right thing: A new root device is going to be added, if it's - // already present or we just received the descriptor again (because we got an embedded - // devices' notification), it will simply update the expiration timestamp of the root - // device. - getUpnpService().getRegistry().addDevice(hydratedDevice); - } - - } catch (ValidationException ex) { - // Avoid error log spam each time device is discovered, errors are logged once per device. - if(!errorsAlreadyLogged.contains(rd.getIdentity().getUdn())) { - errorsAlreadyLogged.add(rd.getIdentity().getUdn()); - log.warning("Could not validate device model: " + rd); - for (ValidationError validationError : ex.getErrors()) { - log.warning(validationError.toString()); - } - if (describedDevice != null && notifiedStart) - getUpnpService().getRegistry().notifyDiscoveryFailure(describedDevice, ex); - } - - } catch (DescriptorBindingException ex) { - log.warning("Could not hydrate device or its services from descriptor: " + rd); - log.warning("Cause was: " + Exceptions.unwrap(ex)); - if (describedDevice != null && notifiedStart) - getUpnpService().getRegistry().notifyDiscoveryFailure(describedDevice, ex); - - } catch (RegistrationException ex) { - log.warning("Adding hydrated device to registry failed: " + rd); - log.warning("Cause was: " + ex.toString()); - if (describedDevice != null && notifiedStart) - getUpnpService().getRegistry().notifyDiscoveryFailure(describedDevice, ex); - } - } - - protected RemoteDevice describeServices(RemoteDevice currentDevice) - throws RouterException, DescriptorBindingException, ValidationException { - - List describedServices = new ArrayList<>(); - if (currentDevice.hasServices()) { - List filteredServices = filterExclusiveServices(currentDevice.getServices()); - for (RemoteService service : filteredServices) { - RemoteService svc = describeService(service); - // Skip invalid services (yes, we can continue with only some services available) - if (svc != null) - describedServices.add(svc); - else - log.warning("Skipping invalid service '" + service + "' of: " + currentDevice); - } - } - - List describedEmbeddedDevices = new ArrayList<>(); - if (currentDevice.hasEmbeddedDevices()) { - for (RemoteDevice embeddedDevice : currentDevice.getEmbeddedDevices()) { - // Skip invalid embedded device - if (embeddedDevice == null) - continue; - RemoteDevice describedEmbeddedDevice = describeServices(embeddedDevice); - // Skip invalid embedded services - if (describedEmbeddedDevice != null) - describedEmbeddedDevices.add(describedEmbeddedDevice); - } - } - - Icon[] iconDupes = new Icon[currentDevice.getIcons().length]; - for (int i = 0; i < currentDevice.getIcons().length; i++) { - Icon icon = currentDevice.getIcons()[i]; - iconDupes[i] = icon.deepCopy(); - } - - // Yes, we create a completely new immutable graph here - return currentDevice.newInstance( - currentDevice.getIdentity().getUdn(), - currentDevice.getVersion(), - currentDevice.getType(), - currentDevice.getDetails(), - iconDupes, - currentDevice.toServiceArray(describedServices), - describedEmbeddedDevices - ); - } - - protected RemoteService describeService(RemoteService service) - throws RouterException, DescriptorBindingException, ValidationException { - - URL descriptorURL; - try { - descriptorURL = service.getDevice().normalizeURI(service.getDescriptorURI()); - } catch(IllegalArgumentException e) { - log.warning("Could not normalize service descriptor URL: " + service.getDescriptorURI()); - return null; - } - - StreamRequestMessage serviceDescRetrievalMsg = new StreamRequestMessage(UpnpRequest.Method.GET, descriptorURL); - - // Extra headers - UpnpHeaders headers = - getUpnpService().getConfiguration().getDescriptorRetrievalHeaders(service.getDevice().getIdentity()); - if (headers != null) - serviceDescRetrievalMsg.getHeaders().putAll(headers); - - log.fine("Sending service descriptor retrieval message: " + serviceDescRetrievalMsg); - StreamResponseMessage serviceDescMsg = getUpnpService().getRouter().send(serviceDescRetrievalMsg); - - if (serviceDescMsg == null) { - log.warning("Could not retrieve service descriptor, no response: " + service); - return null; - } - - if (serviceDescMsg.getOperation().isFailed()) { - log.warning("Service descriptor retrieval failed: " - + descriptorURL - + ", " - + serviceDescMsg.getOperation().getResponseDetails()); - return null; - } - - if (!serviceDescMsg.isContentTypeTextUDA()) { - log.fine("Received service descriptor without or with invalid Content-Type: " + descriptorURL); - // We continue despite the invalid UPnP message because we can still hope to convert the content - } - - String descriptorContent = serviceDescMsg.getBodyString(); - if (descriptorContent == null || descriptorContent.length() == 0) { - log.warning("Received empty service descriptor:" + descriptorURL); - return null; - } - - log.fine("Received service descriptor, hydrating service model: " + serviceDescMsg); - ServiceDescriptorBinder serviceDescriptorBinder = - getUpnpService().getConfiguration().getServiceDescriptorBinderUDA10(); - - return serviceDescriptorBinder.describe(service, descriptorContent); - } - - protected List filterExclusiveServices(RemoteService[] services) { - ServiceType[] exclusiveTypes = getUpnpService().getConfiguration().getExclusiveServiceTypes(); - - if (exclusiveTypes == null || exclusiveTypes.length == 0) - return Arrays.asList(services); - - List exclusiveServices = new ArrayList<>(); - for (RemoteService discoveredService : services) { - for (ServiceType exclusiveType : exclusiveTypes) { - if (discoveredService.getServiceType().implementsVersion(exclusiveType)) { - log.fine("Including exclusive service: " + discoveredService); - exclusiveServices.add(discoveredService); - } else { - log.fine("Excluding unwanted service: " + exclusiveType); - } - } - } - return exclusiveServices; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/SendingAsync.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/SendingAsync.java deleted file mode 100644 index 7ee685c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/SendingAsync.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.transport.RouterException; -import org.seamless.util.Exceptions; - -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Supertype for all synchronously executing protocols, sending UPnP messages. - *

- * After instantiation by the {@link ProtocolFactory}, this protocol run()s and - * calls its {@link #execute()} method. - *

- *

- * A {@link RouterException} during execution will be wrapped in a fatal RuntimeException, - * unless its cause is an InterruptedException, in which case an INFO message will be logged. - *

- * - * @author Christian Bauer - */ -public abstract class SendingAsync implements Runnable { - - final private static Logger log = Logger.getLogger(UpnpService.class.getName()); - - private final UpnpService upnpService; - - protected SendingAsync(UpnpService upnpService) { - this.upnpService = upnpService; - } - - public UpnpService getUpnpService() { - return upnpService; - } - - public void run() { - try { - execute(); - } catch (Exception ex) { - Throwable cause = Exceptions.unwrap(ex); - if (cause instanceof InterruptedException) { - log.log(Level.INFO, "Interrupted protocol '" + getClass().getSimpleName() + "': " + ex, cause); - } else { - throw new RuntimeException( - "Fatal error while executing protocol '" + getClass().getSimpleName() + "': " + ex, ex - ); - } - } - } - - protected abstract void execute() throws RouterException; - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ")"; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/SendingSync.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/SendingSync.java deleted file mode 100644 index 251a3aa..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/SendingSync.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol; - -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.transport.RouterException; - -/** - * Supertype for all synchronously executing protocols, sending UPnP messages. - *

- * After instantiation by the {@link ProtocolFactory}, this protocol run()s and - * calls its {@link #executeSync()} method. - *

- * - * @param The type of request UPnP message send by this protocol. - * @param The type of response UPnP message expected by this protocol. - * - * @author Christian Bauer - */ -public abstract class SendingSync extends SendingAsync { - - final private IN inputMessage; - protected OUT outputMessage; - - protected SendingSync(UpnpService upnpService, IN inputMessage) { - super(upnpService); - this.inputMessage = inputMessage; - } - - public IN getInputMessage() { - return inputMessage; - } - - public OUT getOutputMessage() { - return outputMessage; - } - - final protected void execute() throws RouterException { - outputMessage = executeSync(); - } - - protected abstract OUT executeSync() throws RouterException; - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ")"; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingNotification.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingNotification.java deleted file mode 100644 index 7a2cd66..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingNotification.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.async; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.discovery.IncomingNotificationRequest; -import org.fourthline.cling.model.meta.RemoteDevice; -import org.fourthline.cling.model.meta.RemoteDeviceIdentity; -import org.fourthline.cling.model.types.UDN; -import org.fourthline.cling.protocol.ReceivingAsync; -import org.fourthline.cling.protocol.RetrieveRemoteDescriptors; -import org.fourthline.cling.transport.RouterException; - -import java.util.logging.Logger; - -/** - * Handles reception of notification messages. - *

- * First, the UDN is created from the received message. - *

- *

- * If an ALIVE message has been received, a new background process will be started - * running {@link org.fourthline.cling.protocol.RetrieveRemoteDescriptors}. - *

- *

- * If a BYEBYE message has been received, the device will be removed from the registry - * directly. - *

- *

- * The following was added to the UDA 1.1 spec (in 1.3), clarifying the handling of messages: - *

- *

- * "If a control point has received at least one 'byebye' message of a root device, embedded device, or - * service, then the control point can assume that all are no longer available." - *

- *

- * Of course, they contradict this a little later: - *

- *

- * "Only when all original advertisements of a root device, embedded device, and services have - * expired can a control point assume that they are no longer available." - *

- *

- * This could mean that even if we get 'byeby'e for the root device, we still have to assume that its services - * are available. That clearly makes no sense at all and I think it's just badly worded and relates to the - * previous sentence wich says "if you don't get byebye's, rely on the expiration timeout". It does not - * imply that a service or embedded device lives beyond its root device. It actually reinforces that we are - * free to ignore anything that happens as long as the root device is not gone with 'byebye' or has expired. - * In other words: There is no reason at all why SSDP sends dozens of messages for all embedded devices and - * services. The composite is the root device and the composite defines the lifecycle of all. - *

- * - * @author Christian Bauer - */ -public class ReceivingNotification extends ReceivingAsync { - - final private static Logger log = Logger.getLogger(ReceivingNotification.class.getName()); - - public ReceivingNotification(UpnpService upnpService, IncomingDatagramMessage inputMessage) { - super(upnpService, new IncomingNotificationRequest(inputMessage)); - } - - protected void execute() throws RouterException { - - UDN udn = getInputMessage().getUDN(); - if (udn == null) { - log.fine("Ignoring notification message without UDN: " + getInputMessage()); - return; - } - - RemoteDeviceIdentity rdIdentity = new RemoteDeviceIdentity(getInputMessage()); - log.fine("Received device notification: " + rdIdentity); - - RemoteDevice rd; - try { - rd = new RemoteDevice(rdIdentity); - } catch (ValidationException ex) { - log.warning("Validation errors of device during discovery: " + rdIdentity); - for (ValidationError validationError : ex.getErrors()) { - log.warning(validationError.toString()); - } - return; - } - - if (getInputMessage().isAliveMessage()) { - - log.fine("Received device ALIVE advertisement, descriptor location is: " + rdIdentity.getDescriptorURL()); - - if (rdIdentity.getDescriptorURL() == null) { - log.finer("Ignoring message without location URL header: " + getInputMessage()); - return; - } - - if (rdIdentity.getMaxAgeSeconds() == null) { - log.finer("Ignoring message without max-age header: " + getInputMessage()); - return; - } - - if (getUpnpService().getRegistry().update(rdIdentity)) { - log.finer("Remote device was already known: " + udn); - return; - } - - // Unfortunately, we always have to retrieve the descriptor because at this point we - // have no idea if it's a root or embedded device - getUpnpService().getConfiguration().getAsyncProtocolExecutor().execute( - new RetrieveRemoteDescriptors(getUpnpService(), rd) - ); - - } else if (getInputMessage().isByeByeMessage()) { - - log.fine("Received device BYEBYE advertisement"); - boolean removed = getUpnpService().getRegistry().removeDevice(rd); - if (removed) { - log.fine("Removed remote device from registry: " + rd); - } - - } else { - log.finer("Ignoring unknown notification message: " + getInputMessage()); - } - - } - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingSearch.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingSearch.java deleted file mode 100644 index 1c8db1f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingSearch.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.async; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Random; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.DiscoveryOptions; -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.NetworkAddress; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.discovery.IncomingSearchRequest; -import org.fourthline.cling.model.message.discovery.OutgoingSearchResponse; -import org.fourthline.cling.model.message.discovery.OutgoingSearchResponseDeviceType; -import org.fourthline.cling.model.message.discovery.OutgoingSearchResponseRootDevice; -import org.fourthline.cling.model.message.discovery.OutgoingSearchResponseServiceType; -import org.fourthline.cling.model.message.discovery.OutgoingSearchResponseUDN; -import org.fourthline.cling.model.message.header.DeviceTypeHeader; -import org.fourthline.cling.model.message.header.MXHeader; -import org.fourthline.cling.model.message.header.RootDeviceHeader; -import org.fourthline.cling.model.message.header.STAllHeader; -import org.fourthline.cling.model.message.header.ServiceTypeHeader; -import org.fourthline.cling.model.message.header.UDNHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; -import org.fourthline.cling.protocol.ReceivingAsync; -import org.fourthline.cling.transport.RouterException; - -/** - * Handles reception of search requests, responds for local registered devices. - *

- * Waits a random time between 0 and the requested MX (maximum 120 seconds) - * before executing. Only waits if there are actually any registered local devices. - *

- *

- * Extracts the search target, builds and sends the dozens of messages - * required by the UPnP specification, depending on the search target and what - * local devices and services are found in the {@link org.fourthline.cling.registry.Registry}. - *

- * - * @author Christian Bauer - */ -public class ReceivingSearch extends ReceivingAsync { - - final private static Logger log = Logger.getLogger(ReceivingSearch.class.getName()); - - private static final boolean LOG_ENABLED = log.isLoggable(Level.FINE); - - final protected Random randomGenerator = new Random(); - - public ReceivingSearch(UpnpService upnpService, IncomingDatagramMessage inputMessage) { - super(upnpService, new IncomingSearchRequest(inputMessage)); - } - - protected void execute() throws RouterException { - if (getUpnpService().getRouter() == null) { - // TODO: http://mailinglists.945824.n3.nabble.com/rare-NPE-on-start-tp3078213p3142767.html - log.fine("Router hasn't completed initialization, ignoring received search message"); - return; - } - - if (!getInputMessage().isMANSSDPDiscover()) { - log.fine("Invalid search request, no or invalid MAN ssdp:discover header: " + getInputMessage()); - return; - } - - UpnpHeader searchTarget = getInputMessage().getSearchTarget(); - - if (searchTarget == null) { - log.fine("Invalid search request, did not contain ST header: " + getInputMessage()); - return; - } - - List activeStreamServers = - getUpnpService().getRouter().getActiveStreamServers(getInputMessage().getLocalAddress()); - if (activeStreamServers.size() == 0) { - log.fine("Aborting search response, no active stream servers found (network disabled?)"); - return; - } - - for (NetworkAddress activeStreamServer : activeStreamServers) { - sendResponses(searchTarget, activeStreamServer); - } - } - - @Override - protected boolean waitBeforeExecution() throws InterruptedException { - - Integer mx = getInputMessage().getMX(); - - if (mx == null) { - log.fine("Invalid search request, did not contain MX header: " + getInputMessage()); - return false; - } - - // Spec says we should assume "less" if it's 120 or more - // From the spec, MX should be "greater than or equal to 1" - // Prevent negative MX to make nextInt() throw IllegalArgumentException below - if (mx > 120 || mx <= 0) mx = MXHeader.DEFAULT_VALUE; - - // Only wait if there is something to wait for - if (getUpnpService().getRegistry().getLocalDevices().size() > 0) { - int sleepTime = randomGenerator.nextInt(mx * 1000); - log.fine("Sleeping " + sleepTime + " milliseconds to avoid flooding with search responses"); - Thread.sleep(sleepTime); - } - - return true; - } - - protected void sendResponses(UpnpHeader searchTarget, NetworkAddress activeStreamServer) throws RouterException { - if (searchTarget instanceof STAllHeader) { - - sendSearchResponseAll(activeStreamServer); - - } else if (searchTarget instanceof RootDeviceHeader) { - - sendSearchResponseRootDevices(activeStreamServer); - - } else if (searchTarget instanceof UDNHeader) { - - sendSearchResponseUDN((UDN) searchTarget.getValue(), activeStreamServer); - - } else if (searchTarget instanceof DeviceTypeHeader) { - - sendSearchResponseDeviceType((DeviceType) searchTarget.getValue(), activeStreamServer); - - } else if (searchTarget instanceof ServiceTypeHeader) { - - sendSearchResponseServiceType((ServiceType) searchTarget.getValue(), activeStreamServer); - - } else { - log.warning("Non-implemented search request target: " + searchTarget.getClass()); - } - } - - protected void sendSearchResponseAll(NetworkAddress activeStreamServer) throws RouterException { - if (LOG_ENABLED) { - log.fine("Responding to 'all' search with advertisement messages for all local devices"); - } - for (LocalDevice localDevice : getUpnpService().getRegistry().getLocalDevices()) { - - if (isAdvertisementDisabled(localDevice)) - continue; - - // We are re-using the regular notification messages here but override the NT with the ST header - if (LOG_ENABLED) { - log.finer("Sending root device messages: " + localDevice); - } - List rootDeviceMsgs = - createDeviceMessages(localDevice, activeStreamServer); - for (OutgoingSearchResponse upnpMessage : rootDeviceMsgs) { - getUpnpService().getRouter().send(upnpMessage); - } - - if (localDevice.hasEmbeddedDevices()) { - for (LocalDevice embeddedDevice : localDevice.findEmbeddedDevices()) { - if (LOG_ENABLED) { - log.finer("Sending embedded device messages: " + embeddedDevice); - } - List embeddedDeviceMsgs = - createDeviceMessages(embeddedDevice, activeStreamServer); - for (OutgoingSearchResponse upnpMessage : embeddedDeviceMsgs) { - getUpnpService().getRouter().send(upnpMessage); - } - } - } - - List serviceTypeMsgs = - createServiceTypeMessages(localDevice, activeStreamServer); - if (serviceTypeMsgs.size() > 0) { - if (LOG_ENABLED) { - log.finer("Sending service type messages"); - } - for (OutgoingSearchResponse upnpMessage : serviceTypeMsgs) { - getUpnpService().getRouter().send(upnpMessage); - } - } - - } - } - - protected List createDeviceMessages(LocalDevice device, - NetworkAddress activeStreamServer) { - List msgs = new ArrayList<>(); - - // See the tables in UDA 1.0 section 1.1.2 - - if (device.isRoot()) { - msgs.add( - new OutgoingSearchResponseRootDevice( - getInputMessage(), - getDescriptorLocation(activeStreamServer, device), - device - ) - ); - } - - msgs.add( - new OutgoingSearchResponseUDN( - getInputMessage(), - getDescriptorLocation(activeStreamServer, device), - device - ) - ); - - msgs.add( - new OutgoingSearchResponseDeviceType( - getInputMessage(), - getDescriptorLocation(activeStreamServer, device), - device - ) - ); - - for (OutgoingSearchResponse msg : msgs) { - prepareOutgoingSearchResponse(msg); - } - - return msgs; - } - - protected List createServiceTypeMessages(LocalDevice device, - NetworkAddress activeStreamServer) { - List msgs = new ArrayList<>(); - for (ServiceType serviceType : device.findServiceTypes()) { - OutgoingSearchResponse message = - new OutgoingSearchResponseServiceType( - getInputMessage(), - getDescriptorLocation(activeStreamServer, device), - device, - serviceType - ); - prepareOutgoingSearchResponse(message); - msgs.add(message); - } - return msgs; - } - - protected void sendSearchResponseRootDevices(NetworkAddress activeStreamServer) throws RouterException { - log.fine("Responding to root device search with advertisement messages for all local root devices"); - for (LocalDevice device : getUpnpService().getRegistry().getLocalDevices()) { - - if (isAdvertisementDisabled(device)) - continue; - - OutgoingSearchResponse message = - new OutgoingSearchResponseRootDevice( - getInputMessage(), - getDescriptorLocation(activeStreamServer, device), - device - ); - prepareOutgoingSearchResponse(message); - getUpnpService().getRouter().send(message); - } - } - - protected void sendSearchResponseUDN(UDN udn, NetworkAddress activeStreamServer) throws RouterException { - Device device = getUpnpService().getRegistry().getDevice(udn, false); - if (device != null && device instanceof LocalDevice) { - - if (isAdvertisementDisabled((LocalDevice)device)) - return; - - log.fine("Responding to UDN device search: " + udn); - OutgoingSearchResponse message = - new OutgoingSearchResponseUDN( - getInputMessage(), - getDescriptorLocation(activeStreamServer, (LocalDevice) device), - (LocalDevice) device - ); - prepareOutgoingSearchResponse(message); - getUpnpService().getRouter().send(message); - } - } - - protected void sendSearchResponseDeviceType(DeviceType deviceType, NetworkAddress activeStreamServer) throws RouterException{ - log.fine("Responding to device type search: " + deviceType); - Collection devices = getUpnpService().getRegistry().getDevices(deviceType); - for (Device device : devices) { - if (device instanceof LocalDevice) { - - if (isAdvertisementDisabled((LocalDevice)device)) - continue; - - log.finer("Sending matching device type search result for: " + device); - OutgoingSearchResponse message = - new OutgoingSearchResponseDeviceType( - getInputMessage(), - getDescriptorLocation(activeStreamServer, (LocalDevice) device), - (LocalDevice) device - ); - prepareOutgoingSearchResponse(message); - getUpnpService().getRouter().send(message); - } - } - } - - protected void sendSearchResponseServiceType(ServiceType serviceType, NetworkAddress activeStreamServer) throws RouterException { - log.fine("Responding to service type search: " + serviceType); - Collection devices = getUpnpService().getRegistry().getDevices(serviceType); - for (Device device : devices) { - if (device instanceof LocalDevice) { - - if (isAdvertisementDisabled((LocalDevice)device)) - continue; - - log.finer("Sending matching service type search result: " + device); - OutgoingSearchResponse message = - new OutgoingSearchResponseServiceType( - getInputMessage(), - getDescriptorLocation(activeStreamServer, (LocalDevice) device), - (LocalDevice) device, - serviceType - ); - prepareOutgoingSearchResponse(message); - getUpnpService().getRouter().send(message); - } - } - } - - protected Location getDescriptorLocation(NetworkAddress activeStreamServer, LocalDevice device) { - return new Location( - activeStreamServer, - getUpnpService().getConfiguration().getNamespace().getDescriptorPathString(device) - ); - } - - protected boolean isAdvertisementDisabled(LocalDevice device) { - DiscoveryOptions options = - getUpnpService().getRegistry().getDiscoveryOptions(device.getIdentity().getUdn()); - return options != null && !options.isAdvertised(); - } - - /** - * Override this to edit the outgoing message, e.g. by adding headers. - */ - protected void prepareOutgoingSearchResponse(OutgoingSearchResponse message) { - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingSearchResponse.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingSearchResponse.java deleted file mode 100644 index cf1707f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/ReceivingSearchResponse.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.async; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.ValidationError; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.discovery.IncomingSearchResponse; -import org.fourthline.cling.model.meta.RemoteDevice; -import org.fourthline.cling.model.meta.RemoteDeviceIdentity; -import org.fourthline.cling.model.types.UDN; -import org.fourthline.cling.protocol.ReceivingAsync; -import org.fourthline.cling.protocol.RetrieveRemoteDescriptors; -import org.fourthline.cling.transport.RouterException; - -import java.util.logging.Logger; - -/** - * Handles reception of search response messages. - *

- * This protocol implementation is basically the same as - * the {@link org.fourthline.cling.protocol.async.ReceivingNotification} protocol for - * an ALIVE message. - *

- * - * @author Christian Bauer - */ -public class ReceivingSearchResponse extends ReceivingAsync { - - final private static Logger log = Logger.getLogger(ReceivingSearchResponse.class.getName()); - - public ReceivingSearchResponse(UpnpService upnpService, IncomingDatagramMessage inputMessage) { - super(upnpService, new IncomingSearchResponse(inputMessage)); - } - - protected void execute() throws RouterException { - - if (!getInputMessage().isSearchResponseMessage()) { - log.fine("Ignoring invalid search response message: " + getInputMessage()); - return; - } - - UDN udn = getInputMessage().getRootDeviceUDN(); - if (udn == null) { - log.fine("Ignoring search response message without UDN: " + getInputMessage()); - return; - } - - RemoteDeviceIdentity rdIdentity = new RemoteDeviceIdentity(getInputMessage()); - log.fine("Received device search response: " + rdIdentity); - - if (getUpnpService().getRegistry().update(rdIdentity)) { - log.fine("Remote device was already known: " + udn); - return; - } - - RemoteDevice rd; - try { - rd = new RemoteDevice(rdIdentity); - } catch (ValidationException ex) { - log.warning("Validation errors of device during discovery: " + rdIdentity); - for (ValidationError validationError : ex.getErrors()) { - log.warning(validationError.toString()); - } - return; - } - - if (rdIdentity.getDescriptorURL() == null) { - log.finer("Ignoring message without location URL header: " + getInputMessage()); - return; - } - - if (rdIdentity.getMaxAgeSeconds() == null) { - log.finer("Ignoring message without max-age header: " + getInputMessage()); - return; - } - - // Unfortunately, we always have to retrieve the descriptor because at this point we - // have no idea if it's a root or embedded device - getUpnpService().getConfiguration().getAsyncProtocolExecutor().execute( - new RetrieveRemoteDescriptors(getUpnpService(), rd) - ); - - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotification.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotification.java deleted file mode 100644 index 41f4592..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotification.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.async; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.Location; -import org.fourthline.cling.model.NetworkAddress; -import org.fourthline.cling.model.message.discovery.OutgoingNotificationRequest; -import org.fourthline.cling.model.message.discovery.OutgoingNotificationRequestDeviceType; -import org.fourthline.cling.model.message.discovery.OutgoingNotificationRequestRootDevice; -import org.fourthline.cling.model.message.discovery.OutgoingNotificationRequestServiceType; -import org.fourthline.cling.model.message.discovery.OutgoingNotificationRequestUDN; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.types.NotificationSubtype; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.protocol.SendingAsync; -import org.fourthline.cling.transport.RouterException; - -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -/** - * Sending notification messages for a registered local device. - *

- * Sends all required (dozens) of messages three times, waits between 0 and 150 - * milliseconds between each bulk sending procedure. - *

- * - * @author Christian Bauer - */ -public abstract class SendingNotification extends SendingAsync { - - final private static Logger log = Logger.getLogger(SendingNotification.class.getName()); - - private LocalDevice device; - - public SendingNotification(UpnpService upnpService, LocalDevice device) { - super(upnpService); - this.device = device; - } - - public LocalDevice getDevice() { - return device; - } - - protected void execute() throws RouterException { - - List activeStreamServers = - getUpnpService().getRouter().getActiveStreamServers(null); - if (activeStreamServers.size() == 0) { - log.fine("Aborting notifications, no active stream servers found (network disabled?)"); - return; - } - - // Prepare it once, it's the same for each repetition - List descriptorLocations = new ArrayList<>(); - for (NetworkAddress activeStreamServer : activeStreamServers) { - descriptorLocations.add( - new Location( - activeStreamServer, - getUpnpService().getConfiguration().getNamespace().getDescriptorPathString(getDevice()) - ) - ); - } - - for (int i = 0; i < getBulkRepeat(); i++) { - try { - - for (Location descriptorLocation : descriptorLocations) { - sendMessages(descriptorLocation); - } - - // UDA 1.0 is silent about this but UDA 1.1 recomments "a few hundred milliseconds" - log.finer("Sleeping " + getBulkIntervalMilliseconds() + " milliseconds"); - Thread.sleep(getBulkIntervalMilliseconds()); - - } catch (InterruptedException ex) { - log.warning("Advertisement thread was interrupted: " + ex); - } - } - } - - protected int getBulkRepeat() { - return 3; // UDA 1.0 says maximum 3 times for alive messages, let's just do it for all - } - - protected int getBulkIntervalMilliseconds() { - return 150; - } - - public void sendMessages(Location descriptorLocation) throws RouterException { - log.finer("Sending root device messages: " + getDevice()); - List rootDeviceMsgs = - createDeviceMessages(getDevice(), descriptorLocation); - for (OutgoingNotificationRequest upnpMessage : rootDeviceMsgs) { - getUpnpService().getRouter().send(upnpMessage); - } - - if (getDevice().hasEmbeddedDevices()) { - for (LocalDevice embeddedDevice : getDevice().findEmbeddedDevices()) { - log.finer("Sending embedded device messages: " + embeddedDevice); - List embeddedDeviceMsgs = - createDeviceMessages(embeddedDevice, descriptorLocation); - for (OutgoingNotificationRequest upnpMessage : embeddedDeviceMsgs) { - getUpnpService().getRouter().send(upnpMessage); - } - } - } - - List serviceTypeMsgs = - createServiceTypeMessages(getDevice(), descriptorLocation); - if (serviceTypeMsgs.size() > 0) { - log.finer("Sending service type messages"); - for (OutgoingNotificationRequest upnpMessage : serviceTypeMsgs) { - getUpnpService().getRouter().send(upnpMessage); - } - } - } - - protected List createDeviceMessages(LocalDevice device, - Location descriptorLocation) { - List msgs = new ArrayList<>(); - - // See the tables in UDA 1.0 section 1.1.2 - - if (device.isRoot()) { - msgs.add( - new OutgoingNotificationRequestRootDevice( - descriptorLocation, - device, - getNotificationSubtype() - ) - ); - } - - msgs.add( - new OutgoingNotificationRequestUDN( - descriptorLocation, device, getNotificationSubtype() - ) - ); - msgs.add( - new OutgoingNotificationRequestDeviceType( - descriptorLocation, device, getNotificationSubtype() - ) - ); - - return msgs; - } - - protected List createServiceTypeMessages(LocalDevice device, - Location descriptorLocation) { - List msgs = new ArrayList<>(); - - for (ServiceType serviceType : device.findServiceTypes()) { - msgs.add( - new OutgoingNotificationRequestServiceType( - descriptorLocation, device, - getNotificationSubtype(), serviceType - ) - ); - } - - return msgs; - } - - protected abstract NotificationSubtype getNotificationSubtype(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotificationAlive.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotificationAlive.java deleted file mode 100644 index 8b1abf8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotificationAlive.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.async; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.types.NotificationSubtype; -import org.fourthline.cling.transport.RouterException; - -import java.util.logging.Logger; - -/** - * Sending ALIVE notification messages for a registered local device. - * - * @author Christian Bauer - */ -public class SendingNotificationAlive extends SendingNotification { - - final private static Logger log = Logger.getLogger(SendingNotification.class.getName()); - - public SendingNotificationAlive(UpnpService upnpService, LocalDevice device) { - super(upnpService, device); - } - - @Override - protected void execute() throws RouterException { - log.fine("Sending alive messages ("+getBulkRepeat()+" times) for: " + getDevice()); - super.execute(); - } - - protected NotificationSubtype getNotificationSubtype() { - return NotificationSubtype.ALIVE; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotificationByebye.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotificationByebye.java deleted file mode 100644 index 6a8809d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingNotificationByebye.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.async; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.types.NotificationSubtype; -import org.fourthline.cling.transport.RouterException; - -import java.util.logging.Logger; - -/** - * Sending BYEBYE notification messages for a registered local device. - * - * @author Christian Bauer - */ -public class SendingNotificationByebye extends SendingNotification { - - final private static Logger log = Logger.getLogger(SendingNotification.class.getName()); - - public SendingNotificationByebye(UpnpService upnpService, LocalDevice device) { - super(upnpService, device); - } - - // The UDA 1.0 spec says "a message corresponding to /each/ of the ssd:alive messages" but - // it's not clear if that means the "required" messages according to the tables only or if - // it includes the triple (or whatever) repeated messages that have been sent to protect - // against networking problems. It also says, a little later, that "each of the messages should - // be send more than once". So we are also sending them three times - hell, why not pollute the - // network with useless stuff, that is going to make this more reliable for sure... - - // In other words: The superclass method is fine even for byebye. - - @Override - protected void execute() throws RouterException { - log.fine("Sending byebye messages ("+getBulkRepeat()+" times) for: " + getDevice()); - super.execute(); - } - - protected NotificationSubtype getNotificationSubtype() { - return NotificationSubtype.BYEBYE; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingSearch.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingSearch.java deleted file mode 100644 index adbfd6d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/async/SendingSearch.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.async; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.message.discovery.OutgoingSearchRequest; -import org.fourthline.cling.model.message.header.MXHeader; -import org.fourthline.cling.model.message.header.STAllHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.protocol.SendingAsync; -import org.fourthline.cling.transport.RouterException; - -import java.util.logging.Logger; - -/** - * Sending search request messages using the supplied search type. - *

- * Sends all search messages 5 times, waits 0 to 500 - * milliseconds between each sending procedure. - *

- * - * @author Christian Bauer - */ -public class SendingSearch extends SendingAsync { - - final private static Logger log = Logger.getLogger(SendingSearch.class.getName()); - - private final UpnpHeader searchTarget; - private final int mxSeconds; - - /** - * Defaults to {@link org.fourthline.cling.model.message.header.STAllHeader} and an MX of 3 seconds. - */ - public SendingSearch(UpnpService upnpService) { - this(upnpService, new STAllHeader()); - } - - /** - * Defaults to an MX value of 3 seconds. - */ - public SendingSearch(UpnpService upnpService, UpnpHeader searchTarget) { - this(upnpService, searchTarget, MXHeader.DEFAULT_VALUE); - } - - /** - * @param mxSeconds The time in seconds a host should wait before responding. - */ - public SendingSearch(UpnpService upnpService, UpnpHeader searchTarget, int mxSeconds) { - super(upnpService); - - if (!UpnpHeader.Type.ST.isValidHeaderType(searchTarget.getClass())) { - throw new IllegalArgumentException( - "Given search target instance is not a valid header class for type ST: " + searchTarget.getClass() - ); - } - this.searchTarget = searchTarget; - this.mxSeconds = mxSeconds; - } - - public UpnpHeader getSearchTarget() { - return searchTarget; - } - - public int getMxSeconds() { - return mxSeconds; - } - - protected void execute() throws RouterException { - - log.fine("Executing search for target: " + searchTarget.getString() + " with MX seconds: " + getMxSeconds()); - - OutgoingSearchRequest msg = new OutgoingSearchRequest(searchTarget, getMxSeconds()); - prepareOutgoingSearchRequest(msg); - - for (int i = 0; i < getBulkRepeat(); i++) { - try { - - getUpnpService().getRouter().send(msg); - - // UDA 1.0 is silent about this but UDA 1.1 recommends "a few hundred milliseconds" - log.finer("Sleeping " + getBulkIntervalMilliseconds() + " milliseconds"); - Thread.sleep(getBulkIntervalMilliseconds()); - - } catch (InterruptedException ex) { - // Interruption means we stop sending search messages, e.g. on shutdown of thread pool - break; - } - } - } - - public int getBulkRepeat() { - return 5; // UDA 1.0 says "repeat more than once" - } - - public int getBulkIntervalMilliseconds() { - return 500; // That should be plenty on an ethernet LAN - } - - /** - * Override this to edit the outgoing message, e.g. by adding headers. - */ - protected void prepareOutgoingSearchRequest(OutgoingSearchRequest message) { - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingAction.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingAction.java deleted file mode 100644 index 72c6da9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingAction.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.sync; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.action.ActionCancelledException; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.RemoteActionInvocation; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.control.IncomingActionRequestMessage; -import org.fourthline.cling.model.message.control.OutgoingActionResponseMessage; -import org.fourthline.cling.model.message.header.ContentTypeHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.resource.ServiceControlResource; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.protocol.ReceivingSync; -import org.fourthline.cling.model.UnsupportedDataException; -import org.fourthline.cling.transport.RouterException; -import org.seamless.util.Exceptions; - -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Handles reception of control messages, invoking actions on local services. - *

- * Actions are invoked through the {@link org.fourthline.cling.model.action.ActionExecutor} returned - * by the registered {@link org.fourthline.cling.model.meta.LocalService#getExecutor(org.fourthline.cling.model.meta.Action)} - * method. - *

- * - * @author Christian Bauer - */ -public class ReceivingAction extends ReceivingSync { - - final private static Logger log = Logger.getLogger(ReceivingAction.class.getName()); - - public ReceivingAction(UpnpService upnpService, StreamRequestMessage inputMessage) { - super(upnpService, inputMessage); - } - - protected StreamResponseMessage executeSync() throws RouterException{ - - ContentTypeHeader contentTypeHeader = - getInputMessage().getHeaders().getFirstHeader(UpnpHeader.Type.CONTENT_TYPE, ContentTypeHeader.class); - - // Special rules for action messages! UDA 1.0 says: - // 'If the CONTENT-TYPE header specifies an unsupported value (other then "text/xml") the - // device must return an HTTP status code "415 Unsupported Media Type".' - if (contentTypeHeader != null && !contentTypeHeader.isUDACompliantXML()) { - log.warning("Received invalid Content-Type '" + contentTypeHeader + "': " + getInputMessage()); - return new StreamResponseMessage(new UpnpResponse(UpnpResponse.Status.UNSUPPORTED_MEDIA_TYPE)); - } - - if (contentTypeHeader == null) { - log.warning("Received without Content-Type: " + getInputMessage()); - } - - ServiceControlResource resource = - getUpnpService().getRegistry().getResource( - ServiceControlResource.class, - getInputMessage().getUri() - ); - - if (resource == null) { - log.fine("No local resource found: " + getInputMessage()); - return null; - } - - log.fine("Found local action resource matching relative request URI: " + getInputMessage().getUri()); - - RemoteActionInvocation invocation; - OutgoingActionResponseMessage responseMessage = null; - - try { - - // Throws ActionException if the action can't be found - IncomingActionRequestMessage requestMessage = - new IncomingActionRequestMessage(getInputMessage(), resource.getModel()); - - log.finer("Created incoming action request message: " + requestMessage); - invocation = new RemoteActionInvocation(requestMessage.getAction(), getRemoteClientInfo()); - - // Throws UnsupportedDataException if the body can't be read - log.fine("Reading body of request message"); - getUpnpService().getConfiguration().getSoapActionProcessor().readBody(requestMessage, invocation); - - log.fine("Executing on local service: " + invocation); - resource.getModel().getExecutor(invocation.getAction()).execute(invocation); - - if (invocation.getFailure() == null) { - responseMessage = - new OutgoingActionResponseMessage(invocation.getAction()); - } else { - - if (invocation.getFailure() instanceof ActionCancelledException) { - log.fine("Action execution was cancelled, returning 404 to client"); - // A 404 status is appropriate for this situation: The resource is gone/not available and it's - // a temporary condition. Most likely the cancellation happened because the client connection - // has been dropped, so it doesn't really matter what we return here anyway. - return null; - } else { - responseMessage = - new OutgoingActionResponseMessage( - UpnpResponse.Status.INTERNAL_SERVER_ERROR, - invocation.getAction() - ); - } - } - - } catch (ActionException ex) { - log.finer("Error executing local action: " + ex); - - invocation = new RemoteActionInvocation(ex, getRemoteClientInfo()); - responseMessage = new OutgoingActionResponseMessage(UpnpResponse.Status.INTERNAL_SERVER_ERROR); - - } catch (UnsupportedDataException ex) { - log.log(Level.WARNING, "Error reading action request XML body: " + ex.toString(), Exceptions.unwrap(ex)); - - invocation = - new RemoteActionInvocation( - Exceptions.unwrap(ex) instanceof ActionException - ? (ActionException)Exceptions.unwrap(ex) - : new ActionException(ErrorCode.ACTION_FAILED, ex.getMessage()), - getRemoteClientInfo() - ); - responseMessage = new OutgoingActionResponseMessage(UpnpResponse.Status.INTERNAL_SERVER_ERROR); - - } - - try { - - log.fine("Writing body of response message"); - getUpnpService().getConfiguration().getSoapActionProcessor().writeBody(responseMessage, invocation); - - log.fine("Returning finished response message: " + responseMessage); - return responseMessage; - - } catch (UnsupportedDataException ex) { - log.warning("Failure writing body of response message, sending '500 Internal Server Error' without body"); - log.log(Level.WARNING, "Exception root cause: ", Exceptions.unwrap(ex)); - return new StreamResponseMessage(UpnpResponse.Status.INTERNAL_SERVER_ERROR); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingEvent.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingEvent.java deleted file mode 100644 index cc2ba66..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingEvent.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.sync; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.gena.IncomingEventRequestMessage; -import org.fourthline.cling.model.message.gena.OutgoingEventResponseMessage; -import org.fourthline.cling.model.resource.ServiceEventCallbackResource; -import org.fourthline.cling.protocol.ReceivingSync; -import org.fourthline.cling.model.UnsupportedDataException; -import org.fourthline.cling.transport.RouterException; - -import java.util.logging.Logger; - -/** - * Handles incoming GENA event messages. - *

- * Attempts to find an outgoing (remote) subscription matching the callback and subscription identifier. - * Once found, the GENA event message payload will be transformed and the - * {@link org.fourthline.cling.model.gena.RemoteGENASubscription#receive(org.fourthline.cling.model.types.UnsignedIntegerFourBytes, - * java.util.Collection)} method will be called asynchronously using the executor - * returned by {@link org.fourthline.cling.UpnpServiceConfiguration#getRegistryListenerExecutor()}. - *

- * - * @author Christian Bauer - */ -public class ReceivingEvent extends ReceivingSync { - - final private static Logger log = Logger.getLogger(ReceivingEvent.class.getName()); - - public ReceivingEvent(UpnpService upnpService, StreamRequestMessage inputMessage) { - super(upnpService, inputMessage); - } - - protected OutgoingEventResponseMessage executeSync() throws RouterException{ - - if (!getInputMessage().isContentTypeTextUDA()) { - log.warning("Received without or with invalid Content-Type: " + getInputMessage()); - // We continue despite the invalid UPnP message because we can still hope to convert the content - // return new StreamResponseMessage(new UpnpResponse(UpnpResponse.Status.UNSUPPORTED_MEDIA_TYPE)); - } - - ServiceEventCallbackResource resource = - getUpnpService().getRegistry().getResource( - ServiceEventCallbackResource.class, - getInputMessage().getUri() - ); - - if (resource == null) { - log.fine("No local resource found: " + getInputMessage()); - return new OutgoingEventResponseMessage(new UpnpResponse(UpnpResponse.Status.NOT_FOUND)); - } - - final IncomingEventRequestMessage requestMessage = - new IncomingEventRequestMessage(getInputMessage(), resource.getModel()); - - // Error conditions UDA 1.0 section 4.2.1 - if (requestMessage.getSubscrptionId() == null) { - log.fine("Subscription ID missing in event request: " + getInputMessage()); - return new OutgoingEventResponseMessage(new UpnpResponse(UpnpResponse.Status.PRECONDITION_FAILED)); - } - - if (!requestMessage.hasValidNotificationHeaders()) { - log.fine("Missing NT and/or NTS headers in event request: " + getInputMessage()); - return new OutgoingEventResponseMessage(new UpnpResponse(UpnpResponse.Status.BAD_REQUEST)); - } - - if (!requestMessage.hasValidNotificationHeaders()) { - log.fine("Invalid NT and/or NTS headers in event request: " + getInputMessage()); - return new OutgoingEventResponseMessage(new UpnpResponse(UpnpResponse.Status.PRECONDITION_FAILED)); - } - - if (requestMessage.getSequence() == null) { - log.fine("Sequence missing in event request: " + getInputMessage()); - return new OutgoingEventResponseMessage(new UpnpResponse(UpnpResponse.Status.PRECONDITION_FAILED)); - } - - try { - - getUpnpService().getConfiguration().getGenaEventProcessor().readBody(requestMessage); - - } catch (final UnsupportedDataException ex) { - log.fine("Can't read event message request body, " + ex); - - // Pass the parsing failure on to any listeners, so they can take action if necessary - final RemoteGENASubscription subscription = - getUpnpService().getRegistry().getRemoteSubscription(requestMessage.getSubscrptionId()); - if (subscription != null) { - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - subscription.invalidMessage(ex); - } - } - ); - } - - return new OutgoingEventResponseMessage(new UpnpResponse(UpnpResponse.Status.INTERNAL_SERVER_ERROR)); - } - - // get the remove subscription, if the subscription can't be found, wait for pending subscription - // requests to finish - final RemoteGENASubscription subscription = - getUpnpService().getRegistry().getWaitRemoteSubscription(requestMessage.getSubscrptionId()); - - if (subscription == null) { - log.severe("Invalid subscription ID, no active subscription: " + requestMessage); - return new OutgoingEventResponseMessage(new UpnpResponse(UpnpResponse.Status.PRECONDITION_FAILED)); - } - - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - log.fine("Calling active subscription with event state variable values"); - subscription.receive( - requestMessage.getSequence(), - requestMessage.getStateVariableValues() - ); - } - } - ); - - return new OutgoingEventResponseMessage(); - - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingRetrieval.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingRetrieval.java deleted file mode 100644 index f70a30f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingRetrieval.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.sync; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.binding.xml.DescriptorBindingException; -import org.fourthline.cling.binding.xml.DeviceDescriptorBinder; -import org.fourthline.cling.binding.xml.ServiceDescriptorBinder; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.header.ContentTypeHeader; -import org.fourthline.cling.model.message.header.ServerHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.model.meta.Icon; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.resource.DeviceDescriptorResource; -import org.fourthline.cling.model.resource.IconResource; -import org.fourthline.cling.model.resource.Resource; -import org.fourthline.cling.model.resource.ServiceDescriptorResource; -import org.fourthline.cling.protocol.ReceivingSync; -import org.fourthline.cling.transport.RouterException; -import org.seamless.util.Exceptions; - -import java.net.URI; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Handles reception of device/service descriptor and icon retrieval messages. - * - *

- * Requested device and service XML descriptors are generated on-the-fly for every request. - *

- *

- * Descriptor XML is dynamically generated depending on the control point - some control - * points require different metadata than others for the same device and services. - *

- * - * @author Christian Bauer - */ -public class ReceivingRetrieval extends ReceivingSync { - - final private static Logger log = Logger.getLogger(ReceivingRetrieval.class.getName()); - - public ReceivingRetrieval(UpnpService upnpService, StreamRequestMessage inputMessage) { - super(upnpService, inputMessage); - } - - protected StreamResponseMessage executeSync() throws RouterException { - - if (!getInputMessage().hasHostHeader()) { - log.fine("Ignoring message, missing HOST header: " + getInputMessage()); - return new StreamResponseMessage(new UpnpResponse(UpnpResponse.Status.PRECONDITION_FAILED)); - } - - URI requestedURI = getInputMessage().getOperation().getURI(); - - Resource foundResource = getUpnpService().getRegistry().getResource(requestedURI); - - if (foundResource == null) { - foundResource = onResourceNotFound(requestedURI); - if (foundResource == null) { - log.fine("No local resource found: " + getInputMessage()); - return null; - } - } - - return createResponse(requestedURI, foundResource); - } - - protected StreamResponseMessage createResponse(URI requestedURI, Resource resource) { - - StreamResponseMessage response; - - try { - - if (DeviceDescriptorResource.class.isAssignableFrom(resource.getClass())) { - - log.fine("Found local device matching relative request URI: " + requestedURI); - LocalDevice device = (LocalDevice) resource.getModel(); - - DeviceDescriptorBinder deviceDescriptorBinder = - getUpnpService().getConfiguration().getDeviceDescriptorBinderUDA10(); - String deviceDescriptor = deviceDescriptorBinder.generate( - device, - getRemoteClientInfo(), - getUpnpService().getConfiguration().getNamespace() - ); - response = new StreamResponseMessage( - deviceDescriptor, - new ContentTypeHeader(ContentTypeHeader.DEFAULT_CONTENT_TYPE) - ); - } else if (ServiceDescriptorResource.class.isAssignableFrom(resource.getClass())) { - - - log.fine("Found local service matching relative request URI: " + requestedURI); - LocalService service = (LocalService) resource.getModel(); - - ServiceDescriptorBinder serviceDescriptorBinder = - getUpnpService().getConfiguration().getServiceDescriptorBinderUDA10(); - String serviceDescriptor = serviceDescriptorBinder.generate(service); - response = new StreamResponseMessage( - serviceDescriptor, - new ContentTypeHeader(ContentTypeHeader.DEFAULT_CONTENT_TYPE) - ); - - } else if (IconResource.class.isAssignableFrom(resource.getClass())) { - - log.fine("Found local icon matching relative request URI: " + requestedURI); - Icon icon = (Icon) resource.getModel(); - response = new StreamResponseMessage(icon.getData(), icon.getMimeType()); - - } else { - - log.fine("Ignoring GET for found local resource: " + resource); - return null; - } - - } catch (DescriptorBindingException ex) { - log.warning("Error generating requested device/service descriptor: " + ex.toString()); - log.log(Level.WARNING, "Exception root cause: ", Exceptions.unwrap(ex)); - response = new StreamResponseMessage(UpnpResponse.Status.INTERNAL_SERVER_ERROR); - } - - response.getHeaders().add(UpnpHeader.Type.SERVER, new ServerHeader()); - - return response; - } - - /** - * Called if the {@link org.fourthline.cling.registry.Registry} had no result. - * - * @param requestedURIPath The requested URI path - * @return null or your own {@link Resource} - */ - protected Resource onResourceNotFound(URI requestedURIPath) { - return null; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingSubscribe.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingSubscribe.java deleted file mode 100644 index 143d5a3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingSubscribe.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.sync; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.gena.CancelReason; -import org.fourthline.cling.model.gena.LocalGENASubscription; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.gena.IncomingSubscribeRequestMessage; -import org.fourthline.cling.model.message.gena.OutgoingSubscribeResponseMessage; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.resource.ServiceEventSubscriptionResource; -import org.fourthline.cling.protocol.ReceivingSync; -import org.fourthline.cling.transport.RouterException; -import org.seamless.util.Exceptions; - -import java.net.URL; -import java.util.List; -import java.util.logging.Logger; - -/** - * Handles reception of GENA event subscription (initial and renewal) messages. - *

- * This protocol tries to find a local event subscription URI matching the requested URI, - * then creates a new {@link org.fourthline.cling.model.gena.LocalGENASubscription} if no - * subscription identifer was supplied. - *

- *

- * The subscription is however only registered with the local service, and monitoring - * of state changes is established, if the response of this protocol was successfully - * delivered to the client which requested the subscription. - *

- *

- * Once registration and monitoring is active, an initial event with the current - * state of the service is send to the subscriber. This will only happen after the - * subscription response message was successfully delivered to the subscriber. - *

- * - * @author Christian Bauer - */ -public class ReceivingSubscribe extends ReceivingSync { - - final private static Logger log = Logger.getLogger(ReceivingSubscribe.class.getName()); - - protected LocalGENASubscription subscription; - - public ReceivingSubscribe(UpnpService upnpService, StreamRequestMessage inputMessage) { - super(upnpService, inputMessage); - } - - protected OutgoingSubscribeResponseMessage executeSync() throws RouterException { - - ServiceEventSubscriptionResource resource = - getUpnpService().getRegistry().getResource( - ServiceEventSubscriptionResource.class, - getInputMessage().getUri() - ); - - if (resource == null) { - log.fine("No local resource found: " + getInputMessage()); - return null; - } - - log.fine("Found local event subscription matching relative request URI: " + getInputMessage().getUri()); - - IncomingSubscribeRequestMessage requestMessage = - new IncomingSubscribeRequestMessage(getInputMessage(), resource.getModel()); - - // Error conditions UDA 1.0 section 4.1.1 and 4.1.2 - if (requestMessage.getSubscriptionId() != null && - (requestMessage.hasNotificationHeader() || requestMessage.getCallbackURLs() != null)) { - log.fine("Subscription ID and NT or Callback in subscribe request: " + getInputMessage()); - return new OutgoingSubscribeResponseMessage(UpnpResponse.Status.BAD_REQUEST); - } - - if (requestMessage.getSubscriptionId() != null) { - return processRenewal(resource.getModel(), requestMessage); - } else if (requestMessage.hasNotificationHeader() && requestMessage.getCallbackURLs() != null){ - return processNewSubscription(resource.getModel(), requestMessage); - } else { - log.fine("No subscription ID, no NT or Callback, neither subscription or renewal: " + getInputMessage()); - return new OutgoingSubscribeResponseMessage(UpnpResponse.Status.PRECONDITION_FAILED); - } - - } - - protected OutgoingSubscribeResponseMessage processRenewal(LocalService service, - IncomingSubscribeRequestMessage requestMessage) { - - subscription = getUpnpService().getRegistry().getLocalSubscription(requestMessage.getSubscriptionId()); - - // Error conditions UDA 1.0 section 4.1.1 and 4.1.2 - if (subscription == null) { - log.fine("Invalid subscription ID for renewal request: " + getInputMessage()); - return new OutgoingSubscribeResponseMessage(UpnpResponse.Status.PRECONDITION_FAILED); - } - - log.fine("Renewing subscription: " + subscription); - subscription.setSubscriptionDuration(requestMessage.getRequestedTimeoutSeconds()); - if (getUpnpService().getRegistry().updateLocalSubscription(subscription)) { - return new OutgoingSubscribeResponseMessage(subscription); - } else { - log.fine("Subscription went away before it could be renewed: " + getInputMessage()); - return new OutgoingSubscribeResponseMessage(UpnpResponse.Status.PRECONDITION_FAILED); - } - } - - protected OutgoingSubscribeResponseMessage processNewSubscription(LocalService service, - IncomingSubscribeRequestMessage requestMessage) { - List callbackURLs = requestMessage.getCallbackURLs(); - - // Error conditions UDA 1.0 section 4.1.1 and 4.1.2 - if (callbackURLs == null || callbackURLs.size() == 0) { - log.fine("Missing or invalid Callback URLs in subscribe request: " + getInputMessage()); - return new OutgoingSubscribeResponseMessage(UpnpResponse.Status.PRECONDITION_FAILED); - } - - if (!requestMessage.hasNotificationHeader()) { - log.fine("Missing or invalid NT header in subscribe request: " + getInputMessage()); - return new OutgoingSubscribeResponseMessage(UpnpResponse.Status.PRECONDITION_FAILED); - } - - Integer timeoutSeconds; - if(getUpnpService().getConfiguration().isReceivedSubscriptionTimeoutIgnored()) { - timeoutSeconds = null; // Use default value - } else { - timeoutSeconds = requestMessage.getRequestedTimeoutSeconds(); - } - - try { - subscription = new LocalGENASubscription(service, timeoutSeconds, callbackURLs) { - public void established() { - } - - public void ended(CancelReason reason) { - } - - public void eventReceived() { - // The only thing we are interested in, sending an event when the state changes - getUpnpService().getConfiguration().getSyncProtocolExecutorService().execute( - getUpnpService().getProtocolFactory().createSendingEvent(this) - ); - } - }; - } catch (Exception ex) { - log.warning("Couldn't create local subscription to service: " + Exceptions.unwrap(ex)); - return new OutgoingSubscribeResponseMessage(UpnpResponse.Status.INTERNAL_SERVER_ERROR); - } - - log.fine("Adding subscription to registry: " + subscription); - getUpnpService().getRegistry().addLocalSubscription(subscription); - - log.fine("Returning subscription response, waiting to send initial event"); - return new OutgoingSubscribeResponseMessage(subscription); - } - - @Override - public void responseSent(StreamResponseMessage responseMessage) { - if (subscription == null) return; // Preconditions failed very early on - if (responseMessage != null - && !responseMessage.getOperation().isFailed() - && subscription.getCurrentSequence().getValue() == 0) { // Note that renewals should not have 0 - - // This is a minor concurrency issue: If we now register on the service and henceforth send a new - // event message whenever the state of the service changes, there is still a chance that the initial - // event message arrives later than the first on-change event message. Shouldn't be a problem as the - // subscriber is supposed to figure out what to do with out-of-sequence messages. I would be - // surprised though if actual implementations won't crash! - log.fine("Establishing subscription"); - subscription.registerOnService(); - subscription.establish(); - - log.fine("Response to subscription sent successfully, now sending initial event asynchronously"); - getUpnpService().getConfiguration().getAsyncProtocolExecutor().execute( - getUpnpService().getProtocolFactory().createSendingEvent(subscription) - ); - - } else if (subscription.getCurrentSequence().getValue() == 0) { - log.fine("Subscription request's response aborted, not sending initial event"); - if (responseMessage == null) { - log.fine("Reason: No response at all from subscriber"); - } else { - log.fine("Reason: " + responseMessage.getOperation()); - } - log.fine("Removing subscription from registry: " + subscription); - getUpnpService().getRegistry().removeLocalSubscription(subscription); - } - } - - @Override - public void responseException(Throwable t) { - if (subscription == null) return; // Nothing to do, we didn't get that far - log.fine("Response could not be send to subscriber, removing local GENA subscription: " + subscription); - getUpnpService().getRegistry().removeLocalSubscription(subscription); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingUnsubscribe.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingUnsubscribe.java deleted file mode 100644 index 014e31b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/ReceivingUnsubscribe.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.sync; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.gena.LocalGENASubscription; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.gena.IncomingUnsubscribeRequestMessage; -import org.fourthline.cling.model.resource.ServiceEventSubscriptionResource; -import org.fourthline.cling.protocol.ReceivingSync; -import org.fourthline.cling.transport.RouterException; - -import java.util.logging.Logger; - -/** - * Handles reception of GENA event unsubscribe messages. - * - * @author Christian Bauer - */ -public class ReceivingUnsubscribe extends ReceivingSync { - - final private static Logger log = Logger.getLogger(ReceivingUnsubscribe.class.getName()); - - public ReceivingUnsubscribe(UpnpService upnpService, StreamRequestMessage inputMessage) { - super(upnpService, inputMessage); - } - - protected StreamResponseMessage executeSync() throws RouterException { - - ServiceEventSubscriptionResource resource = - getUpnpService().getRegistry().getResource( - ServiceEventSubscriptionResource.class, - getInputMessage().getUri() - ); - - if (resource == null) { - log.fine("No local resource found: " + getInputMessage()); - return null; - } - - log.fine("Found local event subscription matching relative request URI: " + getInputMessage().getUri()); - - IncomingUnsubscribeRequestMessage requestMessage = - new IncomingUnsubscribeRequestMessage(getInputMessage(), resource.getModel()); - - // Error conditions UDA 1.0 section 4.1.3 - if (requestMessage.getSubscriptionId() != null && - (requestMessage.hasNotificationHeader() || requestMessage.hasCallbackHeader())) { - log.fine("Subscription ID and NT or Callback in unsubcribe request: " + getInputMessage()); - return new StreamResponseMessage(UpnpResponse.Status.BAD_REQUEST); - } - - LocalGENASubscription subscription = - getUpnpService().getRegistry().getLocalSubscription(requestMessage.getSubscriptionId()); - - if (subscription == null) { - log.fine("Invalid subscription ID for unsubscribe request: " + getInputMessage()); - return new StreamResponseMessage(UpnpResponse.Status.PRECONDITION_FAILED); - } - - log.fine("Unregistering subscription: " + subscription); - if (getUpnpService().getRegistry().removeLocalSubscription(subscription)) { - subscription.end(null); // No reason, just an unsubscribe - } else { - log.fine("Subscription was already removed from registry"); - } - - return new StreamResponseMessage(UpnpResponse.Status.OK); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingAction.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingAction.java deleted file mode 100644 index b86efc5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingAction.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.sync; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.action.ActionCancelledException; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.control.IncomingActionResponseMessage; -import org.fourthline.cling.model.message.control.OutgoingActionRequestMessage; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.protocol.SendingSync; -import org.fourthline.cling.model.UnsupportedDataException; -import org.fourthline.cling.transport.RouterException; -import org.seamless.util.Exceptions; - -import java.net.URL; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Sending control message, transforming a local {@link org.fourthline.cling.model.action.ActionInvocation}. - *

- * Writes the outgoing message's body with the {@link org.fourthline.cling.transport.spi.SOAPActionProcessor}. - * This protocol will return null if no response was received from the control target host. - * In all other cases, even if only the processing of message content failed, this protocol will - * return an {@link org.fourthline.cling.model.message.control.IncomingActionResponseMessage}. Any error - * details of a failed response ({@link org.fourthline.cling.model.message.UpnpResponse#isFailed()}) are - * available with - * {@link org.fourthline.cling.model.action.ActionInvocation#setFailure(org.fourthline.cling.model.action.ActionException)}. - *

- * - * @author Christian Bauer - */ -public class SendingAction extends SendingSync { - - final private static Logger log = Logger.getLogger(SendingAction.class.getName()); - - final protected ActionInvocation actionInvocation; - - public SendingAction(UpnpService upnpService, ActionInvocation actionInvocation, URL controlURL) { - super(upnpService, new OutgoingActionRequestMessage(actionInvocation, controlURL)); - this.actionInvocation = actionInvocation; - } - - protected IncomingActionResponseMessage executeSync() throws RouterException { - return invokeRemote(getInputMessage()); - } - - protected IncomingActionResponseMessage invokeRemote(OutgoingActionRequestMessage requestMessage) throws RouterException { - Device device = actionInvocation.getAction().getService().getDevice(); - - log.fine("Sending outgoing action call '" + actionInvocation.getAction().getName() + "' to remote service of: " + device); - IncomingActionResponseMessage responseMessage = null; - try { - - StreamResponseMessage streamResponse = sendRemoteRequest(requestMessage); - - if (streamResponse == null) { - log.fine("No connection or no no response received, returning null"); - actionInvocation.setFailure(new ActionException(ErrorCode.ACTION_FAILED, "Connection error or no response received")); - return null; - } - - responseMessage = new IncomingActionResponseMessage(streamResponse); - - if (responseMessage.isFailedNonRecoverable()) { - log.fine("Response was a non-recoverable failure: " + responseMessage); - throw new ActionException( - ErrorCode.ACTION_FAILED, "Non-recoverable remote execution failure: " + responseMessage.getOperation().getResponseDetails() - ); - } else if (responseMessage.isFailedRecoverable()) { - handleResponseFailure(responseMessage); - } else { - handleResponse(responseMessage); - } - - return responseMessage; - - - } catch (ActionException ex) { - log.fine("Remote action invocation failed, returning Internal Server Error message: " + ex.getMessage()); - actionInvocation.setFailure(ex); - if (responseMessage == null || !responseMessage.getOperation().isFailed()) { - return new IncomingActionResponseMessage(new UpnpResponse(UpnpResponse.Status.INTERNAL_SERVER_ERROR)); - } else { - return responseMessage; - } - } - } - - protected StreamResponseMessage sendRemoteRequest(OutgoingActionRequestMessage requestMessage) - throws ActionException, RouterException { - - try { - log.fine("Writing SOAP request body of: " + requestMessage); - getUpnpService().getConfiguration().getSoapActionProcessor().writeBody(requestMessage, actionInvocation); - - log.fine("Sending SOAP body of message as stream to remote device"); - return getUpnpService().getRouter().send(requestMessage); - } catch (RouterException ex) { - Throwable cause = Exceptions.unwrap(ex); - if (cause instanceof InterruptedException) { - if (log.isLoggable(Level.FINE)) { - log.fine("Sending action request message was interrupted: " + cause); - } - throw new ActionCancelledException((InterruptedException)cause); - } - throw ex; - } catch (UnsupportedDataException ex) { - if (log.isLoggable(Level.FINE)) { - log.fine("Error writing SOAP body: " + ex); - log.log(Level.FINE, "Exception root cause: ", Exceptions.unwrap(ex)); - } - throw new ActionException(ErrorCode.ACTION_FAILED, "Error writing request message. " + ex.getMessage()); - } - } - - protected void handleResponse(IncomingActionResponseMessage responseMsg) throws ActionException { - - try { - log.fine("Received response for outgoing call, reading SOAP response body: " + responseMsg); - getUpnpService().getConfiguration().getSoapActionProcessor().readBody(responseMsg, actionInvocation); - } catch (UnsupportedDataException ex) { - log.fine("Error reading SOAP body: " + ex); - log.log(Level.FINE, "Exception root cause: ", Exceptions.unwrap(ex)); - throw new ActionException( - ErrorCode.ACTION_FAILED, - "Error reading SOAP response message. " + ex.getMessage(), - false - ); - } - } - - protected void handleResponseFailure(IncomingActionResponseMessage responseMsg) throws ActionException { - - try { - log.fine("Received response with Internal Server Error, reading SOAP failure message"); - getUpnpService().getConfiguration().getSoapActionProcessor().readBody(responseMsg, actionInvocation); - } catch (UnsupportedDataException ex) { - log.fine("Error reading SOAP body: " + ex); - log.log(Level.FINE, "Exception root cause: ", Exceptions.unwrap(ex)); - throw new ActionException( - ErrorCode.ACTION_FAILED, - "Error reading SOAP response failure message. " + ex.getMessage(), - false - ); - } - } - -} - -/* - -- send request - - UnsupportedDataException: Can't write body - -- streamResponseMessage is null: No response received, return null to client - -- streamResponseMessage >= 300 && !(405 || 500): Response was HTTP failure, set on anemic response and return - -- streamResponseMessage >= 300 && 405: Try request again with different headers - - UnsupportedDataException: Can't write body - - (The whole streamResponse conditions apply again but this time, ignore 405) - -- streamResponseMessage >= 300 && 500 && lastExecutionFailure != null: Try to read SOAP failure body - - UnsupportedDataException: Can't read body - -- streamResponseMessage < 300: Response was OK, try to read response body - - UnsupportedDataException: Can't read body - - -*/ \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingEvent.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingEvent.java deleted file mode 100644 index 9204963..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingEvent.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.sync; - -import java.util.logging.Logger; -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.gena.LocalGENASubscription; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.gena.OutgoingEventRequestMessage; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.protocol.SendingSync; -import org.fourthline.cling.transport.RouterException; - -import java.net.URL; - -/** - * Sending GENA event messages to remote subscribers. - *

- * Any {@link org.fourthline.cling.model.gena.LocalGENASubscription} instantiates and executes this protocol - * when the state of a local service changes. However, a remote subscriber might require event - * notification messages on more than one callback URL, so this protocol potentially sends - * many messages. What is returned is always the last response, that is, the response for the - * message sent to the last callback URL in the list of the subscriber. - *

- * - * @author Christian Bauer - */ -public class SendingEvent extends SendingSync { - - final private static Logger log = Logger.getLogger(SendingEvent.class.getName()); - - final protected String subscriptionId; - final protected OutgoingEventRequestMessage[] requestMessages; - final protected UnsignedIntegerFourBytes currentSequence; - - public SendingEvent(UpnpService upnpService, LocalGENASubscription subscription) { - super(upnpService, null); // Special case, we actually need to send several messages to each callback URL - - // TODO: Ugly design! It is critical (concurrency) that we prepare the event messages here, in the constructor thread! - - subscriptionId = subscription.getSubscriptionId(); - - requestMessages = new OutgoingEventRequestMessage[subscription.getCallbackURLs().size()]; - int i = 0; - for (URL url : subscription.getCallbackURLs()) { - requestMessages[i] = new OutgoingEventRequestMessage(subscription, url); - getUpnpService().getConfiguration().getGenaEventProcessor().writeBody(requestMessages[i]); - i++; - } - - currentSequence = subscription.getCurrentSequence(); - - // Always increment sequence now, as (its value) has already been set on the headers and the - // next event will use the incremented value - subscription.incrementSequence(); - } - - protected StreamResponseMessage executeSync() throws RouterException { - - log.fine("Sending event for subscription: " + subscriptionId); - - StreamResponseMessage lastResponse = null; - - for (OutgoingEventRequestMessage requestMessage : requestMessages) { - - if (currentSequence.getValue() == 0) { - log.fine("Sending initial event message to callback URL: " + requestMessage.getUri()); - } else { - log.fine("Sending event message '"+currentSequence+"' to callback URL: " + requestMessage.getUri()); - } - - - // Send request - lastResponse = getUpnpService().getRouter().send(requestMessage); - log.fine("Received event callback response: " + lastResponse); - - } - - // It's not really used, so just return the last one - we have only one callback URL most of the - // time anyway - return lastResponse; - - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingRenewal.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingRenewal.java deleted file mode 100644 index 0dcfcea..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingRenewal.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.sync; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.gena.CancelReason; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.gena.IncomingSubscribeResponseMessage; -import org.fourthline.cling.model.message.gena.OutgoingRenewalRequestMessage; -import org.fourthline.cling.protocol.SendingSync; -import org.fourthline.cling.transport.RouterException; - -import java.util.logging.Logger; - -/** - * Renewing a GENA event subscription with a remote host. - *

- * This protocol is executed periodically by the local registry, for any established GENA - * subscription to a remote service. If renewal failed, the subscription will be removed - * from the registry and the - * {@link org.fourthline.cling.model.gena.RemoteGENASubscription#end(org.fourthline.cling.model.gena.CancelReason, org.fourthline.cling.model.message.UpnpResponse)} - * method will be called. The RENEWAL_FAILED reason will be used, however, - * the response might be null if no response was received from the remote host. - *

- * @author Christian Bauer - */ -public class SendingRenewal extends SendingSync { - - final private static Logger log = Logger.getLogger(SendingRenewal.class.getName()); - - final protected RemoteGENASubscription subscription; - - public SendingRenewal(UpnpService upnpService, RemoteGENASubscription subscription) { - super( - upnpService, - new OutgoingRenewalRequestMessage( - subscription, - upnpService.getConfiguration().getEventSubscriptionHeaders(subscription.getService()) - ) - ); - this.subscription = subscription; - } - - protected IncomingSubscribeResponseMessage executeSync() throws RouterException { - log.fine("Sending subscription renewal request: " + getInputMessage()); - - StreamResponseMessage response; - try { - response = getUpnpService().getRouter().send(getInputMessage()); - } catch (RouterException ex) { - onRenewalFailure(); - throw ex; - } - - if (response == null) { - onRenewalFailure(); - return null; - } - - final IncomingSubscribeResponseMessage responseMessage = new IncomingSubscribeResponseMessage(response); - - if (response.getOperation().isFailed()) { - log.fine("Subscription renewal failed, response was: " + response); - getUpnpService().getRegistry().removeRemoteSubscription(subscription); - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - subscription.end(CancelReason.RENEWAL_FAILED,responseMessage.getOperation()); - } - } - ); - } else if (!responseMessage.isValidHeaders()) { - log.severe("Subscription renewal failed, invalid or missing (SID, Timeout) response headers"); - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - subscription.end(CancelReason.RENEWAL_FAILED, responseMessage.getOperation()); - } - } - ); - } else { - log.fine("Subscription renewed, updating in registry, response was: " + response); - subscription.setActualSubscriptionDurationSeconds(responseMessage.getSubscriptionDurationSeconds()); - getUpnpService().getRegistry().updateRemoteSubscription(subscription); - } - - return responseMessage; - } - - protected void onRenewalFailure() { - log.fine("Subscription renewal failed, removing subscription from registry"); - getUpnpService().getRegistry().removeRemoteSubscription(subscription); - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - subscription.end(CancelReason.RENEWAL_FAILED, null); - } - } - ); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingSubscribe.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingSubscribe.java deleted file mode 100644 index 3d231df..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingSubscribe.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.sync; - -import org.fourthline.cling.model.NetworkAddress; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.gena.IncomingSubscribeResponseMessage; -import org.fourthline.cling.model.message.gena.OutgoingSubscribeRequestMessage; -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.protocol.SendingSync; -import org.fourthline.cling.transport.RouterException; - -import java.util.List; -import java.util.logging.Logger; - -/** - * Establishing a GENA event subscription with a remote host. - *

- * Calls the {@link org.fourthline.cling.model.gena.RemoteGENASubscription#establish()} method - * if the subscription request was responded to correctly. - *

- *

- * The {@link org.fourthline.cling.model.gena.RemoteGENASubscription#fail(org.fourthline.cling.model.message.UpnpResponse)} - * method will be called if the request failed. No response from the remote host is indicated with - * a null argument value. Note that this is also the response if the subscription has - * to be aborted early, when no local stream server for callback URL creation is available. This is - * the case when the local network transport layer is switched off, subscriptions will fail - * immediately with no response. - *

- * - * @author Christian Bauer - */ -public class SendingSubscribe extends SendingSync { - - final private static Logger log = Logger.getLogger(SendingSubscribe.class.getName()); - - final protected RemoteGENASubscription subscription; - - public SendingSubscribe(UpnpService upnpService, - RemoteGENASubscription subscription, - List activeStreamServers) { - super( - upnpService, - new OutgoingSubscribeRequestMessage( - subscription, - subscription.getEventCallbackURLs( - activeStreamServers, - upnpService.getConfiguration().getNamespace() - ), - upnpService.getConfiguration().getEventSubscriptionHeaders(subscription.getService()) - ) - ); - - this.subscription = subscription; - } - - protected IncomingSubscribeResponseMessage executeSync() throws RouterException { - - if (!getInputMessage().hasCallbackURLs()) { - log.fine("Subscription failed, no active local callback URLs available (network disabled?)"); - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - subscription.fail(null); - } - } - ); - return null; - } - - log.fine("Sending subscription request: " + getInputMessage()); - - try { - // register this pending Subscription to bloc if the notification is received before the - // registration result. - getUpnpService().getRegistry().registerPendingRemoteSubscription(subscription); - - StreamResponseMessage response = null; - try { - response = getUpnpService().getRouter().send(getInputMessage()); - } catch (RouterException ex) { - onSubscriptionFailure(); - return null; - } - - if (response == null) { - onSubscriptionFailure(); - return null; - } - - final IncomingSubscribeResponseMessage responseMessage = new IncomingSubscribeResponseMessage(response); - - if (response.getOperation().isFailed()) { - log.fine("Subscription failed, response was: " + responseMessage); - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - subscription.fail(responseMessage.getOperation()); - } - } - ); - } else if (!responseMessage.isValidHeaders()) { - log.severe("Subscription failed, invalid or missing (SID, Timeout) response headers"); - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - subscription.fail(responseMessage.getOperation()); - } - } - ); - } else { - - log.fine("Subscription established, adding to registry, response was: " + response); - subscription.setSubscriptionId(responseMessage.getSubscriptionId()); - subscription.setActualSubscriptionDurationSeconds(responseMessage.getSubscriptionDurationSeconds()); - - getUpnpService().getRegistry().addRemoteSubscription(subscription); - - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - subscription.establish(); - } - } - ); - - } - return responseMessage; - } finally { - getUpnpService().getRegistry().unregisterPendingRemoteSubscription(subscription); - } - } - - protected void onSubscriptionFailure() { - log.fine("Subscription failed"); - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - subscription.fail(null); - } - } - ); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingUnsubscribe.java b/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingUnsubscribe.java deleted file mode 100644 index 77488d0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/protocol/sync/SendingUnsubscribe.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.protocol.sync; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.model.gena.CancelReason; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.gena.OutgoingUnsubscribeRequestMessage; -import org.fourthline.cling.protocol.SendingSync; -import org.fourthline.cling.transport.RouterException; - -import java.util.logging.Logger; - -/** - * Disconnecting a GENA event subscription with a remote host. - *

- * Calls the {@link org.fourthline.cling.model.gena.RemoteGENASubscription#end(org.fourthline.cling.model.gena.CancelReason, org.fourthline.cling.model.message.UpnpResponse)} - * method if the subscription request was responded to correctly. No {@link org.fourthline.cling.model.gena.CancelReason} - * will be provided if the unsubscribe procedure completed as expected, otherwise UNSUBSCRIBE_FAILED - * is used. The response might be null if no response was received from the remote host. - *

- * - * @author Christian Bauer - */ -public class SendingUnsubscribe extends SendingSync { - - final private static Logger log = Logger.getLogger(SendingUnsubscribe.class.getName()); - - final protected RemoteGENASubscription subscription; - - public SendingUnsubscribe(UpnpService upnpService, RemoteGENASubscription subscription) { - super( - upnpService, - new OutgoingUnsubscribeRequestMessage( - subscription, - upnpService.getConfiguration().getEventSubscriptionHeaders(subscription.getService()) - ) - ); - this.subscription = subscription; - } - - protected StreamResponseMessage executeSync() throws RouterException { - - log.fine("Sending unsubscribe request: " + getInputMessage()); - - StreamResponseMessage response = null; - try { - response = getUpnpService().getRouter().send(getInputMessage()); - return response; - } finally { - onUnsubscribe(response); - } - } - - protected void onUnsubscribe(final StreamResponseMessage response) { - // Always remove from the registry and end the subscription properly - even if it's failed - getUpnpService().getRegistry().removeRemoteSubscription(subscription); - - getUpnpService().getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - if (response == null) { - log.fine("Unsubscribe failed, no response received"); - subscription.end(CancelReason.UNSUBSCRIBE_FAILED, null); - } else if (response.getOperation().isFailed()) { - log.fine("Unsubscribe failed, response was: " + response); - subscription.end(CancelReason.UNSUBSCRIBE_FAILED, response.getOperation()); - } else { - log.fine("Unsubscribe successful, response was: " + response); - subscription.end(null, response.getOperation()); - } - } - } - ); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/DefaultRegistryListener.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/DefaultRegistryListener.java deleted file mode 100644 index f05f15d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/DefaultRegistryListener.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry; - -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.meta.RemoteDevice; - -/** - * Convenience class, provides empty implementations of all methods. - *

- * Also unifies local and remote device additions and removals with - * {@link #deviceAdded(Registry, org.fourthline.cling.model.meta.Device)} and - * {@link #deviceRemoved(Registry, org.fourthline.cling.model.meta.Device)} methods. - *

- * - * @author Christian Bauer - */ -public class DefaultRegistryListener implements RegistryListener { - - public void remoteDeviceDiscoveryStarted(Registry registry, RemoteDevice device) { - - } - - public void remoteDeviceDiscoveryFailed(Registry registry, RemoteDevice device, Exception ex) { - - } - - /** - * Calls the {@link #deviceAdded(Registry, org.fourthline.cling.model.meta.Device)} method. - * - * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device A validated and hydrated device metadata graph, with complete service metadata. - */ - public void remoteDeviceAdded(Registry registry, RemoteDevice device) { - deviceAdded(registry, device); - } - - public void remoteDeviceUpdated(Registry registry, RemoteDevice device) { - - } - - /** - * Calls the {@link #deviceRemoved(Registry, org.fourthline.cling.model.meta.Device)} method. - * - * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device A validated and hydrated device metadata graph, with complete service metadata. - */ - public void remoteDeviceRemoved(Registry registry, RemoteDevice device) { - deviceRemoved(registry, device); - } - - /** - * Calls the {@link #deviceAdded(Registry, org.fourthline.cling.model.meta.Device)} method. - * - * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device The local device added to the {@link org.fourthline.cling.registry.Registry}. - */ - public void localDeviceAdded(Registry registry, LocalDevice device) { - deviceAdded(registry, device); - } - - /** - * Calls the {@link #deviceRemoved(Registry, org.fourthline.cling.model.meta.Device)} method. - * - * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device The local device removed from the {@link org.fourthline.cling.registry.Registry}. - */ - public void localDeviceRemoved(Registry registry, LocalDevice device) { - deviceRemoved(registry, device); - } - - public void deviceAdded(Registry registry, Device device) { - - } - - public void deviceRemoved(Registry registry, Device device) { - - } - - public void beforeShutdown(Registry registry) { - - } - - public void afterShutdown() { - - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/LocalItems.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/LocalItems.java deleted file mode 100644 index cf1e9c0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/LocalItems.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry; - -import org.fourthline.cling.model.DiscoveryOptions; -import org.fourthline.cling.model.resource.Resource; -import org.fourthline.cling.model.gena.CancelReason; -import org.fourthline.cling.model.gena.LocalGENASubscription; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.types.UDN; -import org.fourthline.cling.protocol.SendingAsync; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.logging.Logger; - -/** - * Internal class, required by {@link RegistryImpl}. - * - * @author Christian Bauer - */ -class LocalItems extends RegistryItems { - - private static Logger log = Logger.getLogger(Registry.class.getName()); - - protected Map discoveryOptions = new HashMap<>(); - protected long lastAliveIntervalTimestamp = 0; - - LocalItems(RegistryImpl registry) { - super(registry); - } - - protected void setDiscoveryOptions(UDN udn, DiscoveryOptions options) { - if (options != null) - this.discoveryOptions.put(udn, options); - else - this.discoveryOptions.remove(udn); - } - - protected DiscoveryOptions getDiscoveryOptions(UDN udn) { - return this.discoveryOptions.get(udn); - } - - protected boolean isAdvertised(UDN udn) { - // Defaults to true - return getDiscoveryOptions(udn) == null || getDiscoveryOptions(udn).isAdvertised(); - } - - protected boolean isByeByeBeforeFirstAlive(UDN udn) { - // Defaults to false - return getDiscoveryOptions(udn) != null && getDiscoveryOptions(udn).isByeByeBeforeFirstAlive(); - } - - void add(LocalDevice localDevice) throws RegistrationException { - add(localDevice, null); - } - - void add(final LocalDevice localDevice, DiscoveryOptions options) throws RegistrationException { - - // Always set/override the options, even if we don't end up adding the device - setDiscoveryOptions(localDevice.getIdentity().getUdn(), options); - - if (registry.getDevice(localDevice.getIdentity().getUdn(), false) != null) { - log.fine("Ignoring addition, device already registered: " + localDevice); - return; - } - - log.fine("Adding local device to registry: " + localDevice); - - for (Resource deviceResource : getResources(localDevice)) { - - if (registry.getResource(deviceResource.getPathQuery()) != null) { - throw new RegistrationException("URI namespace conflict with already registered resource: " + deviceResource); - } - - registry.addResource(deviceResource); - log.fine("Registered resource: " + deviceResource); - - } - - log.fine("Adding item to registry with expiration in seconds: " + localDevice.getIdentity().getMaxAgeSeconds()); - - RegistryItem localItem = new RegistryItem<>( - localDevice.getIdentity().getUdn(), - localDevice, - localDevice.getIdentity().getMaxAgeSeconds() - ); - - getDeviceItems().add(localItem); - log.fine("Registered local device: " + localItem); - - if (isByeByeBeforeFirstAlive(localItem.getKey())) - advertiseByebye(localDevice, true); - - if (isAdvertised(localItem.getKey())) - advertiseAlive(localDevice); - - for (final RegistryListener listener : registry.getListeners()) { - registry.getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - listener.localDeviceAdded(registry, localDevice); - } - } - ); - } - - } - - Collection get() { - Set c = new HashSet<>(); - for (RegistryItem item : getDeviceItems()) { - c.add(item.getItem()); - } - return Collections.unmodifiableCollection(c); - } - - boolean remove(final LocalDevice localDevice) throws RegistrationException { - return remove(localDevice, false); - } - - boolean remove(final LocalDevice localDevice, boolean shuttingDown) throws RegistrationException { - - LocalDevice registeredDevice = get(localDevice.getIdentity().getUdn(), true); - if (registeredDevice != null) { - - log.fine("Removing local device from registry: " + localDevice); - - setDiscoveryOptions(localDevice.getIdentity().getUdn(), null); - getDeviceItems().remove(new RegistryItem(localDevice.getIdentity().getUdn())); - - for (Resource deviceResource : getResources(localDevice)) { - if (registry.removeResource(deviceResource)) { - log.fine("Unregistered resource: " + deviceResource); - } - } - - // Active subscriptions - Iterator> it = getSubscriptionItems().iterator(); - while (it.hasNext()) { - final RegistryItem incomingSubscription = it.next(); - - UDN subscriptionForUDN = - incomingSubscription.getItem().getService().getDevice().getIdentity().getUdn(); - - if (subscriptionForUDN.equals(registeredDevice.getIdentity().getUdn())) { - log.fine("Removing incoming subscription: " + incomingSubscription.getKey()); - it.remove(); - if (!shuttingDown) { - registry.getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - incomingSubscription.getItem().end(CancelReason.DEVICE_WAS_REMOVED); - } - } - ); - } - } - } - - if (isAdvertised(localDevice.getIdentity().getUdn())) - advertiseByebye(localDevice, !shuttingDown); - - if (!shuttingDown) { - for (final RegistryListener listener : registry.getListeners()) { - registry.getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - listener.localDeviceRemoved(registry, localDevice); - } - } - ); - } - } - - return true; - } - - return false; - } - - void removeAll() { - removeAll(false); - } - - void removeAll(boolean shuttingDown) { - LocalDevice[] allDevices = get().toArray(new LocalDevice[get().size()]); - for (LocalDevice device : allDevices) { - remove(device, shuttingDown); - } - } - - /* ############################################################################################################ */ - - public void advertiseLocalDevices() { - for (RegistryItem localItem : deviceItems) { - if (isAdvertised(localItem.getKey())) - advertiseAlive(localItem.getItem()); - } - } - - /* ############################################################################################################ */ - - void maintain() { - - if(getDeviceItems().isEmpty()) return ; - - Set> expiredLocalItems = new HashSet<>(); - - // "Flooding" is enabled, check if we need to send advertisements for all devices - int aliveIntervalMillis = registry.getConfiguration().getAliveIntervalMillis(); - if(aliveIntervalMillis > 0) { - long now = System.currentTimeMillis(); - if(now - lastAliveIntervalTimestamp > aliveIntervalMillis) { - lastAliveIntervalTimestamp = now; - for (RegistryItem localItem : getDeviceItems()) { - if (isAdvertised(localItem.getKey())) { - log.finer("Flooding advertisement of local item: " + localItem); - expiredLocalItems.add(localItem); - } - } - } - } else { - // Reset, the configuration might dynamically switch the alive interval - lastAliveIntervalTimestamp = 0; - - // Alive interval is not enabled, regular expiration check of all devices - for (RegistryItem localItem : getDeviceItems()) { - if (isAdvertised(localItem.getKey()) && localItem.getExpirationDetails().hasExpired(true)) { - log.finer("Local item has expired: " + localItem); - expiredLocalItems.add(localItem); - } - } - } - - // Now execute the advertisements - for (RegistryItem expiredLocalItem : expiredLocalItems) { - log.fine("Refreshing local device advertisement: " + expiredLocalItem.getItem()); - advertiseAlive(expiredLocalItem.getItem()); - expiredLocalItem.getExpirationDetails().stampLastRefresh(); - } - - // Expire incoming subscriptions - Set> expiredIncomingSubscriptions = new HashSet<>(); - for (RegistryItem item : getSubscriptionItems()) { - if (item.getExpirationDetails().hasExpired(false)) { - expiredIncomingSubscriptions.add(item); - } - } - for (RegistryItem subscription : expiredIncomingSubscriptions) { - log.fine("Removing expired: " + subscription); - removeSubscription(subscription.getItem()); - subscription.getItem().end(CancelReason.EXPIRED); - } - - } - - void shutdown() { - log.fine("Clearing all registered subscriptions to local devices during shutdown"); - getSubscriptionItems().clear(); - - log.fine("Removing all local devices from registry during shutdown"); - removeAll(true); - } - - /* ############################################################################################################ */ - - protected Random randomGenerator = new Random(); - - protected void advertiseAlive(final LocalDevice localDevice) { - registry.executeAsyncProtocol(new Runnable() { - public void run() { - try { - log.finer("Sleeping some milliseconds to avoid flooding the network with ALIVE msgs"); - Thread.sleep(randomGenerator.nextInt(100)); - } catch (InterruptedException ex) { - log.severe("Background execution interrupted: " + ex.getMessage()); - } - registry.getProtocolFactory().createSendingNotificationAlive(localDevice).run(); - } - }); - } - - protected void advertiseByebye(final LocalDevice localDevice, boolean asynchronous) { - final SendingAsync prot = registry.getProtocolFactory().createSendingNotificationByebye(localDevice); - if (asynchronous) { - registry.executeAsyncProtocol(prot); - } else { - prot.run(); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistrationException.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistrationException.java deleted file mode 100644 index 0d19040..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistrationException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry; - -import org.fourthline.cling.model.ValidationError; - -import java.util.List; - -/** - * A recoverable error, thrown if device metadata could not be registered. - * - * @author Christian Bauer - */ -public class RegistrationException extends RuntimeException { - - public List errors; - - public RegistrationException(String s) { - super(s); - } - - public RegistrationException(String s, Throwable throwable) { - super(s, throwable); - } - - public RegistrationException(String s, List errors) { - super(s); - this.errors = errors; - } - - public List getErrors() { - return errors; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/Registry.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/Registry.java deleted file mode 100644 index 07b1f92..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/Registry.java +++ /dev/null @@ -1,452 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.model.DiscoveryOptions; -import org.fourthline.cling.model.resource.Resource; -import org.fourthline.cling.model.ServiceReference; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.meta.RemoteDevice; -import org.fourthline.cling.model.gena.LocalGENASubscription; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.meta.RemoteDeviceIdentity; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; -import org.fourthline.cling.protocol.ProtocolFactory; - -import java.net.URI; -import java.util.Collection; - -/** - * The core of the UPnP stack, keeping track of known devices and resources. - *

- * A running UPnP stack has one Registry. Any discovered device is added - * to this registry, as well as any exposed local device. The registry then maintains - * these devices continuously (see {@link RegistryMaintainer}) and when needed refreshes - * their announcements on the network or removes them when they have expired. The registry - * also keeps track of GENA event subscriptions. - *

- *

- * UPnP client applications typically monitor activity of the registry - * via {@link RegistryListener}, they are inherently asynchronous. - *

- *

- * The registry has to be {@link #shutdown()} properly, so it can notify all participants - * on the network that local devices will no longer be available and cancel all - * GENA subscriptions. - *

- * An implementation has to be thread-safe. - *

- * - * @author Christian Bauer - */ -public interface Registry { - - public UpnpService getUpnpService(); - public UpnpServiceConfiguration getConfiguration(); - public ProtocolFactory getProtocolFactory(); - - // ################################################################################################# - - /** - * Typically called internally when the UPnP stack is stopping. - *

- * Unsubscribe all local devices and GENA subscriptions. - *

- */ - public void shutdown(); - - /** - * Stops background maintenance (thread) of registered items. - *

- * When paused, the registry will no longer remove expired remote devices if their - * discovery announcements stop for some reason (device was turned off). Your local - * control point will now see potentially unavailable remote devices. Outbound - * GENA subscriptions from your local control point to remote services will not - * be renewed automatically anymore, a remote service might drop your subscriptions - * if you don't resume maintenance within the subscription's expiration timeout. - *

- *

- * Local devices and services will not be announced periodically anymore to remote - * control points, only when they are manually added are removed from the registry. - * The registry will also no longer remove expired inbound GENA subscriptions to - * local service from remote control points, if that control point for some reason - * stops sending subscription renewal messages. - *

- */ - public void pause(); - - /** - * Resumes background maintenance (thread) of registered items. - *

- * A local control point has to handle the following situations when resuming - * registry maintenance: - *

- * A remote device registration might have expired. This is the case when the remote - * device stopped sending announcements while the registry was paused (maybe because - * the device was switched off) and the registry was paused longer than the device - * advertisement's maximum age. The registry will not know if the device is still - * available when it resumes maintenance. However, it will simply assume that the - * remote device is still available and restart its expiration check cycle. That means - * a device will finally be removed from the registry, if no further announcements - * from the device are received, when the maximum age of the device has elapsed - * after the registry resumed operation. - *

- *

- * Secondly, a remote device registration might not have expired but some of your - * outbound GENA subscriptions to its services have not been renewed within the expected renewal - * period. Therefore your outbound subscriptions might be invalid, because the remote - * service can drop subscriptions when you don't renew them. On resume, the registry - * will attempt to send renewals for all outbound GENA subscriptions that require - * renewal, on devices that still haven't expired. If renewal fails, your subscription will - * end with {@link org.fourthline.cling.model.gena.CancelReason#RENEWAL_FAILED}. Although - * you then might conclude that the remote device is no longer available, a GENA renewal - * can also fail for other reasons. The remote device will be kept and maintained in the - * registry until it announces itself or it expires, even after a failed GENA renewal. - *

- *

- * If you are providing local devices and services, resuming registry maintenance has - * the following effects: - *

- *

- * Local devices and their services are announced again immediately if the registry - * has been paused for longer than half of the device's maximum age. Remote control - * points will either see this as a new device advertisement (if they have dropped - * your device while you paused maintenance) or as a regular update if you didn't - * pause longer than the device's maximum age/expiration timeout. - *

- *

- * Inbound GENA subscriptions to your local services are active, even in - * paused state - remote control points should continue renewing the subscription. - * If a remote control point stopped renewing a subscription without unsubscribing - * (hard power off), an outdated inbound subscription will be detected when you - * resume maintenance. This subscription will be cleaned up immediately on resume. - *

- */ - public void resume(); - - /** - * @return true if the registry has currently no running background - * maintenance (thread). - */ - public boolean isPaused(); - - // ################################################################################################# - - public void addListener(RegistryListener listener); - - public void removeListener(RegistryListener listener); - - public Collection getListeners(); - - /** - * Called internally by the UPnP stack when the discovery protocol starts. - *

- * The registry will notify all registered listeners of this event, unless the - * given device was already in the registry. - *

- * - * @param device The half-hydrated (without services) metadata of the discovered device. - * @return false if the device was already registered. - */ - public boolean notifyDiscoveryStart(RemoteDevice device); - - /** - * Called internally by the UPnP stack when the discovery protocol stopped abnormally. - *

- * The registry will notify all registered listeners of this event. - *

- * - * @param device The half-hydrated (without services) metadata of the discovered device. - * @param ex The cause for the interruption of the discovery protocol. - */ - public void notifyDiscoveryFailure(RemoteDevice device, Exception ex); - - // ################################################################################################# - - /** - * Call this method to add your local device metadata. - * - * @param localDevice The device to add and maintain. - * @throws RegistrationException If a conflict with an already registered device was detected. - */ - public void addDevice(LocalDevice localDevice) throws RegistrationException; - - /** - * Call this method to add your local device metadata. - * - * @param localDevice The device to add and maintain. - * @param options Immediately effective when this device is registered. - * @throws RegistrationException If a conflict with an already registered device was detected. - */ - public void addDevice(LocalDevice localDevice, DiscoveryOptions options) throws RegistrationException; - - /** - * Change the active {@link DiscoveryOptions} for the given (local device) UDN. - * - * @param options Set to null to disable any options. - */ - public void setDiscoveryOptions(UDN udn, DiscoveryOptions options); - - /** - * Get the currently active {@link DiscoveryOptions} for the given (local device) UDN. - * - * @return null if there are no active discovery options for the given UDN. - */ - public DiscoveryOptions getDiscoveryOptions(UDN udn); - - /** - * Called internally by the UPnP discovery protocol. - * - * @throws RegistrationException If a conflict with an already registered device was detected. - */ - public void addDevice(RemoteDevice remoteDevice) throws RegistrationException; - - /** - * Called internally by the UPnP discovery protocol. - */ - public boolean update(RemoteDeviceIdentity rdIdentity); - - /** - * Call this to remove your local device metadata. - * - * @return true if the device was registered and has been removed. - */ - public boolean removeDevice(LocalDevice localDevice); - - /** - * Called internally by the UPnP discovery protocol. - */ - public boolean removeDevice(RemoteDevice remoteDevice); - - /** - * Call this to remove any device metadata with the given UDN. - * - * @return true if the device was registered and has been removed. - */ - public boolean removeDevice(UDN udn); - - /** - * Clear the registry of all locally registered device metadata. - */ - public void removeAllLocalDevices(); - - /** - * Clear the registry of all discovered remote device metadata. - */ - public void removeAllRemoteDevices(); - - /** - * @param udn The device name to lookup. - * @param rootOnly If true, only matches of root devices are returned. - * @return The registered root or embedded device metadata, or null. - */ - public Device getDevice(UDN udn, boolean rootOnly); - - /** - * @param udn The device name to lookup. - * @param rootOnly If true, only matches of root devices are returned. - * @return The registered root or embedded device metadata, or null. - */ - public LocalDevice getLocalDevice(UDN udn, boolean rootOnly); - - /** - * @param udn The device name to lookup. - * @param rootOnly If true, only matches of root devices are returned. - * @return The registered root or embedded device metadata, or null. - */ - public RemoteDevice getRemoteDevice(UDN udn, boolean rootOnly); - - /** - * @return All locally registered device metadata, in no particular order, or an empty collection. - */ - public Collection getLocalDevices(); - - /** - * @return All discovered remote device metadata, in no particular order, or an empty collection. - */ - public Collection getRemoteDevices(); - - /** - * @return All device metadata, in no particular order, or an empty collection. - */ - public Collection getDevices(); - - /** - * @return All device metadata of devices which implement the given type, in no particular order, - * or an empty collection. - */ - public Collection getDevices(DeviceType deviceType); - - /** - * @return All device metadata of devices which have a service that implements the given type, - * in no particular order, or an empty collection. - */ - public Collection getDevices(ServiceType serviceType); - - /** - * @return Complete service metadata for a service reference or null if no service - * for the given reference has been registered. - */ - public Service getService(ServiceReference serviceReference); - - // ################################################################################################# - - /** - * Stores an arbitrary resource in the registry. - * - * @param resource The resource to maintain indefinitely (until it is manually removed). - */ - public void addResource(Resource resource); - - /** - * Stores an arbitrary resource in the registry. - *

- * Call this method repeatedly to refresh and prevent expiration of the resource. - *

- * - * @param resource The resource to maintain. - * @param maxAgeSeconds The time after which the registry will automatically remove the resource. - */ - public void addResource(Resource resource, int maxAgeSeconds); - - /** - * Removes a resource from the registry. - * - * @param resource The resource to remove. - * @return true if the resource was registered and has been removed. - */ - public boolean removeResource(Resource resource); - - /** - * @param pathQuery The path and optional query string of the resource's - * registration URI (e.g. /dev/somefile.xml?param=value) - * @return Any registered resource that matches the given URI path. - * @throws IllegalArgumentException If the given URI was absolute, only path and query are allowed. - */ - public Resource getResource(URI pathQuery) throws IllegalArgumentException; - - /** - * @param The required subtype of the {@link org.fourthline.cling.model.resource.Resource}. - * @param pathQuery The path and optional query string of the resource's - * registration URI (e.g. /dev/somefile.xml?param=value) - * @param resourceType The required subtype of the {@link org.fourthline.cling.model.resource.Resource}. - * @return Any registered resource that matches the given URI path and subtype. - * @throws IllegalArgumentException If the given URI was absolute, only path and query are allowed. - */ - public T getResource(Class resourceType, URI pathQuery) throws IllegalArgumentException; - - /** - * @return All registered resources, in no particular order, or an empty collection. - */ - public Collection getResources(); - - /** - * @param The required subtype of the {@link org.fourthline.cling.model.resource.Resource}. - * @param resourceType The required subtype of the {@link org.fourthline.cling.model.resource.Resource}. - * @return Any registered resource that matches the given subtype. - */ - public Collection getResources(Class resourceType); - - // ################################################################################################# - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - */ - public void addLocalSubscription(LocalGENASubscription subscription); - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - */ - public LocalGENASubscription getLocalSubscription(String subscriptionId); - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - */ - public boolean updateLocalSubscription(LocalGENASubscription subscription); - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - */ - public boolean removeLocalSubscription(LocalGENASubscription subscription); - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - */ - public void addRemoteSubscription(RemoteGENASubscription subscription); - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - */ - public RemoteGENASubscription getRemoteSubscription(String subscriptionId); - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - */ - public void updateRemoteSubscription(RemoteGENASubscription subscription); - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - */ - public void removeRemoteSubscription(RemoteGENASubscription subscription); - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - *

- * When subscribing with a remote host, the remote host might send the - * initial event message faster than the response for the subscription - * request. This method register that the subscription procedure is - * executing. - *

- */ - public void registerPendingRemoteSubscription(RemoteGENASubscription subscription); - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - *

- * Notify that the subscription procedure has terminated. - *

- */ - public void unregisterPendingRemoteSubscription(RemoteGENASubscription subscription); - - /** - * Called internally by the UPnP stack, during GENA protocol execution. - *

- * Get a remote subscription from its subscriptionId. If the subscription can't be found, - * wait for one of the pending remote subscription procedures from the registry background - * maintainer to terminate, until the subscription has been found or until there are no - * more pending subscription procedures. - *

- */ - public RemoteGENASubscription getWaitRemoteSubscription(String subscriptionId); - - // ################################################################################################# - - /** - * Manually trigger advertisement messages for all local devices. - *

- * No messages will be send for devices with disabled advertisements, see - * {@link DiscoveryOptions}! - *

- */ - public void advertiseLocalDevices(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryImpl.java deleted file mode 100644 index cf83352..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryImpl.java +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry; - -import org.fourthline.cling.UpnpService; -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.model.DiscoveryOptions; -import org.fourthline.cling.model.ExpirationDetails; -import org.fourthline.cling.model.ServiceReference; -import org.fourthline.cling.model.gena.LocalGENASubscription; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.meta.RemoteDevice; -import org.fourthline.cling.model.meta.RemoteDeviceIdentity; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.resource.Resource; -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; -import org.fourthline.cling.protocol.ProtocolFactory; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Default implementation of {@link Registry}. - * - * @author Christian Bauer - */ -@ApplicationScoped -public class RegistryImpl implements Registry { - - private static Logger log = Logger.getLogger(Registry.class.getName()); - - protected UpnpService upnpService; - protected RegistryMaintainer registryMaintainer; - protected final Set pendingSubscriptionsLock = new HashSet<>(); - - public RegistryImpl() { - } - - /** - * Starts background maintenance immediately. - */ - @Inject - public RegistryImpl(UpnpService upnpService) { - log.fine("Creating Registry: " + getClass().getName()); - - this.upnpService = upnpService; - - log.fine("Starting registry background maintenance..."); - registryMaintainer = createRegistryMaintainer(); - if (registryMaintainer != null) { - getConfiguration().getRegistryMaintainerExecutor().execute(registryMaintainer); - } - } - - public UpnpService getUpnpService() { - return upnpService; - } - - public UpnpServiceConfiguration getConfiguration() { - return getUpnpService().getConfiguration(); - } - - public ProtocolFactory getProtocolFactory() { - return getUpnpService().getProtocolFactory(); - } - - protected RegistryMaintainer createRegistryMaintainer() { - return new RegistryMaintainer( - this, - getConfiguration().getRegistryMaintenanceIntervalMillis() - ); - } - - // ################################################################################################# - - protected final Set registryListeners = new HashSet<>(); - protected final Set> resourceItems = new HashSet<>(); - protected final List pendingExecutions = new ArrayList<>(); - - protected final RemoteItems remoteItems = new RemoteItems(this); - protected final LocalItems localItems = new LocalItems(this); - - // ################################################################################################# - - synchronized public void addListener(RegistryListener listener) { - registryListeners.add(listener); - } - - synchronized public void removeListener(RegistryListener listener) { - registryListeners.remove(listener); - } - - synchronized public Collection getListeners() { - return Collections.unmodifiableCollection(registryListeners); - } - - synchronized public boolean notifyDiscoveryStart(final RemoteDevice device) { - // Exit if we have it already, this is atomic inside this method, finally - if (getUpnpService().getRegistry().getRemoteDevice(device.getIdentity().getUdn(), true) != null) { - log.finer("Not notifying listeners, already registered: " + device); - return false; - } - for (final RegistryListener listener : getListeners()) { - getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - listener.remoteDeviceDiscoveryStarted(RegistryImpl.this, device); - } - } - ); - } - return true; - } - - synchronized public void notifyDiscoveryFailure(final RemoteDevice device, final Exception ex) { - for (final RegistryListener listener : getListeners()) { - getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - listener.remoteDeviceDiscoveryFailed(RegistryImpl.this, device, ex); - } - } - ); - } - } - - // ################################################################################################# - - synchronized public void addDevice(LocalDevice localDevice) { - localItems.add(localDevice); - } - - synchronized public void addDevice(LocalDevice localDevice, DiscoveryOptions options) { - localItems.add(localDevice, options); - } - - synchronized public void setDiscoveryOptions(UDN udn, DiscoveryOptions options) { - localItems.setDiscoveryOptions(udn, options); - } - - synchronized public DiscoveryOptions getDiscoveryOptions(UDN udn) { - return localItems.getDiscoveryOptions(udn); - } - - synchronized public void addDevice(RemoteDevice remoteDevice) { - remoteItems.add(remoteDevice); - } - - synchronized public boolean update(RemoteDeviceIdentity rdIdentity) { - return remoteItems.update(rdIdentity); - } - - synchronized public boolean removeDevice(LocalDevice localDevice) { - return localItems.remove(localDevice); - } - - synchronized public boolean removeDevice(RemoteDevice remoteDevice) { - return remoteItems.remove(remoteDevice); - } - - synchronized public void removeAllLocalDevices() { - localItems.removeAll(); - } - - synchronized public void removeAllRemoteDevices() { - remoteItems.removeAll(); - } - - synchronized public boolean removeDevice(UDN udn) { - Device device = getDevice(udn, true); - if (device != null && device instanceof LocalDevice) - return removeDevice((LocalDevice) device); - if (device != null && device instanceof RemoteDevice) - return removeDevice((RemoteDevice) device); - return false; - } - - synchronized public Device getDevice(UDN udn, boolean rootOnly) { - Device device; - if ((device = localItems.get(udn, rootOnly)) != null) return device; - if ((device = remoteItems.get(udn, rootOnly)) != null) return device; - return null; - } - - synchronized public LocalDevice getLocalDevice(UDN udn, boolean rootOnly) { - return localItems.get(udn, rootOnly); - } - - synchronized public RemoteDevice getRemoteDevice(UDN udn, boolean rootOnly) { - return remoteItems.get(udn, rootOnly); - } - - synchronized public Collection getLocalDevices() { - return Collections.unmodifiableCollection(localItems.get()); - } - - synchronized public Collection getRemoteDevices() { - return Collections.unmodifiableCollection(remoteItems.get()); - } - - synchronized public Collection getDevices() { - Set all = new HashSet<>(); - all.addAll(localItems.get()); - all.addAll(remoteItems.get()); - return Collections.unmodifiableCollection(all); - } - - synchronized public Collection getDevices(DeviceType deviceType) { - Collection devices = new HashSet<>(); - - devices.addAll(localItems.get(deviceType)); - devices.addAll(remoteItems.get(deviceType)); - - return Collections.unmodifiableCollection(devices); - } - - synchronized public Collection getDevices(ServiceType serviceType) { - Collection devices = new HashSet<>(); - - devices.addAll(localItems.get(serviceType)); - devices.addAll(remoteItems.get(serviceType)); - - return Collections.unmodifiableCollection(devices); - } - - synchronized public Service getService(ServiceReference serviceReference) { - Device device; - if ((device = getDevice(serviceReference.getUdn(), false)) != null) { - return device.findService(serviceReference.getServiceId()); - } - return null; - } - - // ################################################################################################# - - synchronized public Resource getResource(URI pathQuery) throws IllegalArgumentException { - if (pathQuery.isAbsolute()) { - throw new IllegalArgumentException("Resource URI can not be absolute, only path and query:" + pathQuery); - } - - // Note: Uses field access on resourceItems for performance reasons - - for (RegistryItem resourceItem : resourceItems) { - Resource resource = resourceItem.getItem(); - if (resource.matches(pathQuery)) { - return resource; - } - } - - // TODO: UPNP VIOLATION: Fuppes on my ReadyNAS thinks it's a cool idea to add a slash at the end of the callback URI... - // It also cuts off any query parameters in the callback URL - nice! - if (pathQuery.getPath().endsWith("/")) { - URI pathQueryWithoutSlash = URI.create(pathQuery.toString().substring(0, pathQuery.toString().length() - 1)); - - for (RegistryItem resourceItem : resourceItems) { - Resource resource = resourceItem.getItem(); - if (resource.matches(pathQueryWithoutSlash)) { - return resource; - } - } - } - - return null; - } - - synchronized public T getResource(Class resourceType, URI pathQuery) throws IllegalArgumentException { - Resource resource = getResource(pathQuery); - if (resource != null && resourceType.isAssignableFrom(resource.getClass())) { - return (T) resource; - } - return null; - } - - synchronized public Collection getResources() { - Collection s = new HashSet<>(); - for (RegistryItem resourceItem : resourceItems) { - s.add(resourceItem.getItem()); - } - return s; - } - - synchronized public Collection getResources(Class resourceType) { - Collection s = new HashSet<>(); - for (RegistryItem resourceItem : resourceItems) { - if (resourceType.isAssignableFrom(resourceItem.getItem().getClass())) - s.add((T) resourceItem.getItem()); - } - return s; - } - - synchronized public void addResource(Resource resource) { - addResource(resource, ExpirationDetails.UNLIMITED_AGE); - } - - synchronized public void addResource(Resource resource, int maxAgeSeconds) { - RegistryItem resourceItem = new RegistryItem(resource.getPathQuery(), resource, maxAgeSeconds); - resourceItems.remove(resourceItem); - resourceItems.add(resourceItem); - } - - synchronized public boolean removeResource(Resource resource) { - return resourceItems.remove(new RegistryItem(resource.getPathQuery())); - } - - // ################################################################################################# - - synchronized public void addLocalSubscription(LocalGENASubscription subscription) { - localItems.addSubscription(subscription); - } - - synchronized public LocalGENASubscription getLocalSubscription(String subscriptionId) { - return localItems.getSubscription(subscriptionId); - } - - synchronized public boolean updateLocalSubscription(LocalGENASubscription subscription) { - return localItems.updateSubscription(subscription); - } - - synchronized public boolean removeLocalSubscription(LocalGENASubscription subscription) { - return localItems.removeSubscription(subscription); - } - - synchronized public void addRemoteSubscription(RemoteGENASubscription subscription) { - remoteItems.addSubscription(subscription); - } - - synchronized public RemoteGENASubscription getRemoteSubscription(String subscriptionId) { - return remoteItems.getSubscription(subscriptionId); - } - - synchronized public void updateRemoteSubscription(RemoteGENASubscription subscription) { - remoteItems.updateSubscription(subscription); - } - - synchronized public void removeRemoteSubscription(RemoteGENASubscription subscription) { - remoteItems.removeSubscription(subscription); - } - - /* ############################################################################################################ */ - - synchronized public void advertiseLocalDevices() { - localItems.advertiseLocalDevices(); - } - - /* ############################################################################################################ */ - - // When you call this, make sure you have the Router lock before this lock is obtained! - synchronized public void shutdown() { - log.fine("Shutting down registry..."); - - if (registryMaintainer != null) - registryMaintainer.stop(); - - // Final cleanup run to flush out pending executions which might - // not have been caught by the maintainer before it stopped - log.finest("Executing final pending operations on shutdown: " + pendingExecutions.size()); - runPendingExecutions(false); - - for (RegistryListener listener : registryListeners) { - listener.beforeShutdown(this); - } - - RegistryItem[] resources = resourceItems.toArray(new RegistryItem[resourceItems.size()]); - for (RegistryItem resourceItem : resources) { - resourceItem.getItem().shutdown(); - } - - remoteItems.shutdown(); - localItems.shutdown(); - - for (RegistryListener listener : registryListeners) { - listener.afterShutdown(); - } - } - - synchronized public void pause() { - if (registryMaintainer != null) { - log.fine("Pausing registry maintenance"); - runPendingExecutions(true); - registryMaintainer.stop(); - registryMaintainer = null; - } - } - - synchronized public void resume() { - if (registryMaintainer == null) { - log.fine("Resuming registry maintenance"); - remoteItems.resume(); - registryMaintainer = createRegistryMaintainer(); - if (registryMaintainer != null) { - getConfiguration().getRegistryMaintainerExecutor().execute(registryMaintainer); - } - } - } - - synchronized public boolean isPaused() { - return registryMaintainer == null; - } - - /* ############################################################################################################ */ - - synchronized void maintain() { - - if (log.isLoggable(Level.FINEST)) - log.finest("Maintaining registry..."); - - // Remove expired resources - Iterator> it = resourceItems.iterator(); - while (it.hasNext()) { - RegistryItem item = it.next(); - if (item.getExpirationDetails().hasExpired()) { - if (log.isLoggable(Level.FINER)) - log.finer("Removing expired resource: " + item); - it.remove(); - } - } - - // Let each resource do its own maintenance - for (RegistryItem resourceItem : resourceItems) { - resourceItem.getItem().maintain( - pendingExecutions, - resourceItem.getExpirationDetails() - ); - } - - // These add all their operations to the pendingExecutions queue - remoteItems.maintain(); - localItems.maintain(); - - // We now run the queue asynchronously so the maintenance thread can continue its loop undisturbed - runPendingExecutions(true); - } - - synchronized void executeAsyncProtocol(Runnable runnable) { - pendingExecutions.add(runnable); - } - - synchronized void runPendingExecutions(boolean async) { - if (log.isLoggable(Level.FINEST)) - log.finest("Executing pending operations: " + pendingExecutions.size()); - for (Runnable pendingExecution : pendingExecutions) { - if (async) - getConfiguration().getAsyncProtocolExecutor().execute(pendingExecution); - else - pendingExecution.run(); - } - if (pendingExecutions.size() > 0) { - pendingExecutions.clear(); - } - } - - /* ############################################################################################################ */ - - public void printDebugLog() { - if (log.isLoggable(Level.FINE)) { - log.fine("==================================== REMOTE ================================================"); - - for (RemoteDevice remoteDevice : remoteItems.get()) { - log.fine(remoteDevice.toString()); - } - - log.fine("==================================== LOCAL ================================================"); - - for (LocalDevice localDevice : localItems.get()) { - log.fine(localDevice.toString()); - } - - log.fine("==================================== RESOURCES ================================================"); - - for (RegistryItem resourceItem : resourceItems) { - log.fine(resourceItem.toString()); - } - - log.fine("================================================================================================="); - - } - - } - - @Override - public void registerPendingRemoteSubscription(RemoteGENASubscription subscription) { - synchronized (pendingSubscriptionsLock) { - pendingSubscriptionsLock.add(subscription); - } - } - - @Override - public void unregisterPendingRemoteSubscription(RemoteGENASubscription subscription) { - synchronized (pendingSubscriptionsLock) { - if(pendingSubscriptionsLock.remove(subscription)) { - pendingSubscriptionsLock.notifyAll(); - } - } - } - - @Override - public RemoteGENASubscription getWaitRemoteSubscription(String subscriptionId) { - synchronized (pendingSubscriptionsLock) { - RemoteGENASubscription subscription = getRemoteSubscription(subscriptionId); - while (subscription == null && !pendingSubscriptionsLock.isEmpty()) { - try { - log.finest("Subscription not found, waiting for pending subscription procedure to terminate."); - pendingSubscriptionsLock.wait(); - } catch (InterruptedException e) { - } - subscription = getRemoteSubscription(subscriptionId); - } - return subscription; - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryItem.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryItem.java deleted file mode 100644 index 0087c9c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryItem.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry; - -import org.fourthline.cling.model.ExpirationDetails; - -/** - * Internal class, required by {@link RegistryImpl}. - * - * @author Christian Bauer - */ -class RegistryItem { - - private K key; - private I item; - private ExpirationDetails expirationDetails = new ExpirationDetails(); - - RegistryItem(K key) { - this.key = key; - } - - RegistryItem(K key, I item, int maxAgeSeconds) { - this.key = key; - this.item = item; - this.expirationDetails = new ExpirationDetails(maxAgeSeconds); - } - - public K getKey() { - return key; - } - - public I getItem() { - return item; - } - - public ExpirationDetails getExpirationDetails() { - return expirationDetails; - } - - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - RegistryItem that = (RegistryItem) o; - - return key.equals(that.key); - } - - public int hashCode() { - return key.hashCode(); - } - - @Override - public String toString() { - return "("+getClass().getSimpleName()+") " + getExpirationDetails() + " KEY: " + getKey() + " ITEM: " + getItem(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryItems.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryItems.java deleted file mode 100644 index 523e429..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryItems.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry; - -import org.fourthline.cling.model.resource.Resource; -import org.fourthline.cling.model.ValidationException; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.gena.GENASubscription; -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDN; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -/** - * Internal class, required by {@link RegistryImpl}. - * - * @author Christian Bauer - */ -abstract class RegistryItems { - - protected final RegistryImpl registry; - - protected final Set> deviceItems = new HashSet<>(); - protected final Set> subscriptionItems = new HashSet<>(); - - RegistryItems(RegistryImpl registry) { - this.registry = registry; - } - - Set> getDeviceItems() { - return deviceItems; - } - - Set> getSubscriptionItems() { - return subscriptionItems; - } - - abstract void add(D device); - abstract boolean remove(final D device); - abstract void removeAll(); - - abstract void maintain(); - abstract void shutdown(); - - /** - * Returns root and embedded devices registered under the given UDN. - * - * @param udn A unique device name. - * @param rootOnly Set to true if only root devices (no embedded) should be searched - * @return Any registered root or embedded device under the given UDN, null if - * no device with the given UDN has been registered. - */ - D get(UDN udn, boolean rootOnly) { - for (RegistryItem item : deviceItems) { - D device = item.getItem(); - if (device.getIdentity().getUdn().equals(udn)) { - return device; - } - if (!rootOnly) { - D foundDevice = (D)item.getItem().findDevice(udn); - if (foundDevice != null) return foundDevice; - } - } - return null; - } - - /** - * Returns all devices (root or embedded) with a compatible type. - *

- * This routine will check compatible versions, as described by the UDA. - *

- * - * @param deviceType The minimum device type required. - * @return Any registered root or embedded device with a compatible type. - */ - Collection get(DeviceType deviceType) { - Collection devices = new HashSet<>(); - for (RegistryItem item : deviceItems) { - D[] d = (D[])item.getItem().findDevices(deviceType); - if (d != null) { - devices.addAll(Arrays.asList(d)); - } - } - return devices; - } - - /** - * Returns all devices (root or embedded) which have at least one matching service. - * - * @param serviceType The type of service to search for. - * @return Any registered root or embedded device with at least one matching service. - */ - Collection get(ServiceType serviceType) { - Collection devices = new HashSet<>(); - for (RegistryItem item : deviceItems) { - - D[] d = (D[])item.getItem().findDevices(serviceType); - if (d != null) { - devices.addAll(Arrays.asList(d)); - } - } - return devices; - } - - Collection get() { - Collection devices = new HashSet<>(); - for (RegistryItem item : deviceItems) { - devices.add(item.getItem()); - } - return devices; - } - - boolean contains(D device) { - return contains(device.getIdentity().getUdn()); - } - - boolean contains(UDN udn) { - return deviceItems.contains(new RegistryItem(udn)); - } - - void addSubscription(S subscription) { - - RegistryItem subscriptionItem = - new RegistryItem<>( - subscription.getSubscriptionId(), - subscription, - subscription.getActualDurationSeconds() - ); - - subscriptionItems.add(subscriptionItem); - } - - boolean updateSubscription(S subscription) { - if (removeSubscription(subscription)) { - addSubscription(subscription); - return true; - } - return false; - } - - boolean removeSubscription(S subscription) { - return subscriptionItems.remove(new RegistryItem(subscription.getSubscriptionId())); - } - - S getSubscription(String subscriptionId) { - for (RegistryItem registryItem : subscriptionItems) { - if (registryItem.getKey().equals(subscriptionId)) { - return registryItem.getItem(); - } - } - return null; - } - - Resource[] getResources(Device device) throws RegistrationException { - try { - return registry.getConfiguration().getNamespace().getResources(device); - } catch (ValidationException ex) { - throw new RegistrationException("Resource discover error: " + ex.toString(), ex); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryListener.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryListener.java deleted file mode 100644 index f6d37b0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryListener.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry; - -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.meta.RemoteDevice; - -/** - * Notification of discovered device additions, removals, updates. - *

- * Add an instance of this interface to the registry to be notified when a device is - * discovered on your UPnP network, or when it is updated, or when it disappears. - *

- *

- * Implementations will be called concurrently by several threads, they should be thread-safe. - *

- *

- * Listener methods are called in a separate thread, so you can execute - * expensive procedures without spawning a new thread. The {@link #beforeShutdown(Registry)} - * and {@link #afterShutdown()} methods are however called in the thread that is stopping - * the registry and should not be blocking, unless you want to delay the shutdown procedure. - *

- * - * @author Christian Bauer - */ -public interface RegistryListener { - - /** - * Called as soon as possible after a device has been discovered. - *

- * This method will be called after SSDP notification datagrams of a new alive - * UPnP device have been received and processed. The announced device XML descriptor - * will be retrieved and parsed. The given {@link org.fourthline.cling.model.meta.RemoteDevice} metadata - * is validated and partial {@link org.fourthline.cling.model.meta.Service} metadata is available. The - * services are unhydrated, they have no actions or state variable metadata because the - * service descriptors of the device model have not been retrieved at this point. - *

- *

- * You typically do not use this method on a regular machine, this is an optimization - * for slower UPnP hosts (such as Android handsets). - *

- * - * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device A validated and hydrated device metadata graph, with anemic service metadata. - */ - public void remoteDeviceDiscoveryStarted(Registry registry, RemoteDevice device); - - /** - * Called when service metadata couldn't be initialized. - *

- * If you override the {@link #remoteDeviceDiscoveryStarted(Registry, org.fourthline.cling.model.meta.RemoteDevice)} - * method, you might want to override this method as well. - *

- * - * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device A validated and hydrated device metadata graph, with anemic service metadata. - * @param ex The reason why service metadata could not be initialized, or null if service - * descriptors couldn't be retrieved at all. - */ - public void remoteDeviceDiscoveryFailed(Registry registry, RemoteDevice device, Exception ex); - - /** - * Called when complete metadata of a newly discovered device is available. - * - * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device A validated and hydrated device metadata graph, with complete service metadata. - */ - public void remoteDeviceAdded(Registry registry, RemoteDevice device); - - /** - * Called when a discovered device's expiration timestamp is updated. - *

- * This is a signal that a device is still alive and you typically don't have to react to this - * event. You will be notified when a device disappears through timeout. - *

- * - * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device A validated and hydrated device metadata graph, with complete service metadata. - */ - public void remoteDeviceUpdated(Registry registry, RemoteDevice device); - - /** - * Called when a previously discovered device disappears. - *

- * This method will also be called when a discovered device did not update its expiration timeout - * and has been been removed automatically by the local registry. This method will not be called - * when the UPnP stack is shutting down. - *

- * - * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device A validated and hydrated device metadata graph, with complete service metadata. - */ - public void remoteDeviceRemoved(Registry registry, RemoteDevice device); - - /** - * Called after you add your own device to the {@link org.fourthline.cling.registry.Registry}. - * - * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device The local device added to the {@link org.fourthline.cling.registry.Registry}. - */ - public void localDeviceAdded(Registry registry, LocalDevice device); - - /** - * Called after you remove your own device from the {@link org.fourthline.cling.registry.Registry}. - *

- * This method will not be called when the UPnP stack is shutting down. - *

- * @param registry The Cling registry of all devices and services know to the local UPnP stack. - * @param device The local device removed from the {@link org.fourthline.cling.registry.Registry}. - */ - public void localDeviceRemoved(Registry registry, LocalDevice device); - - /** - * Called after registry maintenance stops but before the registry is cleared. - *

- * This method should typically not block, it executes in the thread that shuts down the UPnP stack. - *

- * @param registry The Cling registry of all devices and services know to the local UPnP stack. - */ - public void beforeShutdown(Registry registry); - - /** - * Called after the registry has been cleared on shutdown. - *

- * This method should typically not block, it executes in the thread that shuts down the UPnP stack. - *

- */ - public void afterShutdown(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryMaintainer.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryMaintainer.java deleted file mode 100644 index 49b4336..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/RegistryMaintainer.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry; - -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Runs periodically and calls {@link org.fourthline.cling.registry.RegistryImpl#maintain()}. - * - * @author Christian Bauer - */ -public class RegistryMaintainer implements Runnable { - - private static Logger log = Logger.getLogger(RegistryMaintainer.class.getName()); - - final private RegistryImpl registry; - final private int sleepIntervalMillis; - - private volatile boolean stopped = false; - - public RegistryMaintainer(RegistryImpl registry, int sleepIntervalMillis) { - this.registry = registry; - this.sleepIntervalMillis = sleepIntervalMillis; - } - - public void stop() { - if (log.isLoggable(Level.FINE)) - log.fine("Setting stopped status on thread"); - stopped = true; - } - - public void run() { - stopped = false; - if (log.isLoggable(Level.FINE)) - log.fine("Running registry maintenance loop every milliseconds: " + sleepIntervalMillis); - while (!stopped) { - - try { - registry.maintain(); - Thread.sleep(sleepIntervalMillis); - } catch (InterruptedException ex) { - stopped = true; - } - - } - log.fine("Stopped status on thread received, ending maintenance loop"); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/RemoteItems.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/RemoteItems.java deleted file mode 100644 index c79cefa..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/RemoteItems.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry; - -import org.fourthline.cling.model.resource.Resource; -import org.fourthline.cling.model.gena.CancelReason; -import org.fourthline.cling.model.gena.RemoteGENASubscription; -import org.fourthline.cling.model.meta.LocalDevice; -import org.fourthline.cling.model.meta.RemoteDevice; -import org.fourthline.cling.model.meta.RemoteDeviceIdentity; -import org.fourthline.cling.model.types.UDN; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Internal class, required by {@link RegistryImpl}. - * - * @author Christian Bauer - */ -class RemoteItems extends RegistryItems { - - private static Logger log = Logger.getLogger(Registry.class.getName()); - - RemoteItems(RegistryImpl registry) { - super(registry); - } - - /** - * Adds the given remote device to the registry, or udpates its expiration timestamp. - *

- * This method first checks if there is a remote device with the same UDN already registered. If so, it - * updates the expiration timestamp of the remote device without notifying any registry listeners. If the - * device is truly new, all its resources are tested for conflicts with existing resources in the registry's - * namespace, then it is added to the registry and listeners are notified that a new fully described remote - * device is now available. - *

- * - * @param device The remote device to be added - */ - void add(final RemoteDevice device) { - - if (update(device.getIdentity())) { - log.fine("Ignoring addition, device already registered: " + device); - return; - } - - Resource[] resources = getResources(device); - - for (Resource deviceResource : resources) { - log.fine("Validating remote device resource; " + deviceResource); - if (registry.getResource(deviceResource.getPathQuery()) != null) { - throw new RegistrationException("URI namespace conflict with already registered resource: " + deviceResource); - } - } - - for (Resource validatedResource : resources) { - registry.addResource(validatedResource); - log.fine("Added remote device resource: " + validatedResource); - } - - // Override the device's maximum age if configured (systems without multicast support) - RegistryItem item = new RegistryItem( - device.getIdentity().getUdn(), - device, - registry.getConfiguration().getRemoteDeviceMaxAgeSeconds() != null - ? registry.getConfiguration().getRemoteDeviceMaxAgeSeconds() - : device.getIdentity().getMaxAgeSeconds() - ); - log.fine("Adding hydrated remote device to registry with " - + item.getExpirationDetails().getMaxAgeSeconds() + " seconds expiration: " + device); - getDeviceItems().add(item); - - if (log.isLoggable(Level.FINEST)) { - StringBuilder sb = new StringBuilder(); - sb.append("\n"); - sb.append("-------------------------- START Registry Namespace -----------------------------------\n"); - for (Resource resource : registry.getResources()) { - sb.append(resource).append("\n"); - } - sb.append("-------------------------- END Registry Namespace -----------------------------------"); - log.finest(sb.toString()); - } - - // Only notify the listeners when the device is fully usable - log.fine("Completely hydrated remote device graph available, calling listeners: " + device); - for (final RegistryListener listener : registry.getListeners()) { - registry.getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - listener.remoteDeviceAdded(registry, device); - } - } - ); - } - - } - - boolean update(RemoteDeviceIdentity rdIdentity) { - - for (LocalDevice localDevice : registry.getLocalDevices()) { - if (localDevice.findDevice(rdIdentity.getUdn()) != null) { - log.fine("Ignoring update, a local device graph contains UDN"); - return true; - } - } - - RemoteDevice registeredRemoteDevice = get(rdIdentity.getUdn(), false); - if (registeredRemoteDevice != null) { - - if (!registeredRemoteDevice.isRoot()) { - log.fine("Updating root device of embedded: " + registeredRemoteDevice); - registeredRemoteDevice = registeredRemoteDevice.getRoot(); - } - - // Override the device's maximum age if configured (systems without multicast support) - final RegistryItem item = new RegistryItem<>( - registeredRemoteDevice.getIdentity().getUdn(), - registeredRemoteDevice, - registry.getConfiguration().getRemoteDeviceMaxAgeSeconds() != null - ? registry.getConfiguration().getRemoteDeviceMaxAgeSeconds() - : rdIdentity.getMaxAgeSeconds() - ); - - log.fine("Updating expiration of: " + registeredRemoteDevice); - getDeviceItems().remove(item); - getDeviceItems().add(item); - - log.fine("Remote device updated, calling listeners: " + registeredRemoteDevice); - for (final RegistryListener listener : registry.getListeners()) { - registry.getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - listener.remoteDeviceUpdated(registry, item.getItem()); - } - } - ); - } - - return true; - - } - return false; - } - - /** - * Removes the given device from the registry and notifies registry listeners. - * - * @param remoteDevice The device to remove from the registry. - * @return true if the given device was found and removed from the registry, false if it wasn't registered. - */ - boolean remove(final RemoteDevice remoteDevice) { - return remove(remoteDevice, false); - } - - boolean remove(final RemoteDevice remoteDevice, boolean shuttingDown) throws RegistrationException { - final RemoteDevice registeredDevice = get(remoteDevice.getIdentity().getUdn(), true); - if (registeredDevice != null) { - - log.fine("Removing remote device from registry: " + remoteDevice); - - // Resources - for (Resource deviceResource : getResources(registeredDevice)) { - if (registry.removeResource(deviceResource)) { - log.fine("Unregistered resource: " + deviceResource); - } - } - - // Active subscriptions - Iterator> it = getSubscriptionItems().iterator(); - while (it.hasNext()) { - final RegistryItem outgoingSubscription = it.next(); - - UDN subscriptionForUDN = - outgoingSubscription.getItem().getService().getDevice().getIdentity().getUdn(); - - if (subscriptionForUDN.equals(registeredDevice.getIdentity().getUdn())) { - log.fine("Removing outgoing subscription: " + outgoingSubscription.getKey()); - it.remove(); - if (!shuttingDown) { - registry.getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - outgoingSubscription.getItem().end(CancelReason.DEVICE_WAS_REMOVED, null); - } - } - ); - } - } - } - - // Only notify listeners if we are NOT in the process of shutting down the registry - if (!shuttingDown) { - for (final RegistryListener listener : registry.getListeners()) { - registry.getConfiguration().getRegistryListenerExecutor().execute( - new Runnable() { - public void run() { - listener.remoteDeviceRemoved(registry, registeredDevice); - } - } - ); - } - } - - // Finally, remove the device from the registry - getDeviceItems().remove(new RegistryItem(registeredDevice.getIdentity().getUdn())); - - return true; - } - - return false; - } - - void removeAll() { - removeAll(false); - } - - void removeAll(boolean shuttingDown) { - RemoteDevice[] allDevices = get().toArray(new RemoteDevice[get().size()]); - for (RemoteDevice device : allDevices) { - remove(device, shuttingDown); - } - } - - /* ############################################################################################################ */ - - void start() { - // Noop - } - - void maintain() { - - if (getDeviceItems().isEmpty()) return; - - // Remove expired remote devices - Map expiredRemoteDevices = new HashMap<>(); - for (RegistryItem remoteItem : getDeviceItems()) { - if (log.isLoggable(Level.FINEST)) - log.finest("Device '" + remoteItem.getItem() + "' expires in seconds: " - + remoteItem.getExpirationDetails().getSecondsUntilExpiration()); - if (remoteItem.getExpirationDetails().hasExpired(false)) { - expiredRemoteDevices.put(remoteItem.getKey(), remoteItem.getItem()); - } - } - for (RemoteDevice remoteDevice : expiredRemoteDevices.values()) { - if (log.isLoggable(Level.FINE)) - log.fine("Removing expired: " + remoteDevice); - remove(remoteDevice); - } - - // Renew outgoing subscriptions - Set expiredOutgoingSubscriptions = new HashSet<>(); - for (RegistryItem item : getSubscriptionItems()) { - if (item.getExpirationDetails().hasExpired(true)) { - expiredOutgoingSubscriptions.add(item.getItem()); - } - } - for (RemoteGENASubscription subscription : expiredOutgoingSubscriptions) { - if (log.isLoggable(Level.FINEST)) - log.fine("Renewing outgoing subscription: " + subscription); - renewOutgoingSubscription(subscription); - } - } - - public void resume() { - log.fine("Updating remote device expiration timestamps on resume"); - List toUpdate = new ArrayList<>(); - for (RegistryItem remoteItem : getDeviceItems()) { - toUpdate.add(remoteItem.getItem().getIdentity()); - } - for (RemoteDeviceIdentity identity : toUpdate) { - update(identity); - } - } - - void shutdown() { - log.fine("Cancelling all outgoing subscriptions to remote devices during shutdown"); - List remoteSubscriptions = new ArrayList<>(); - for (RegistryItem item : getSubscriptionItems()) { - remoteSubscriptions.add(item.getItem()); - } - for (RemoteGENASubscription remoteSubscription : remoteSubscriptions) { - // This will remove the active subscription from the registry! - registry.getProtocolFactory() - .createSendingUnsubscribe(remoteSubscription) - .run(); - } - - log.fine("Removing all remote devices from registry during shutdown"); - removeAll(true); - } - - /* ############################################################################################################ */ - - protected void renewOutgoingSubscription(final RemoteGENASubscription subscription) { - registry.executeAsyncProtocol( - registry.getProtocolFactory().createSendingRenewal(subscription) - ); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/After.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/event/After.java deleted file mode 100644 index 7677658..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/After.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry.event; - -import javax.inject.Qualifier; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * @author Christian Bauer - */ -@Qualifier -@Target({FIELD, PARAMETER}) -@Retention(RUNTIME) -public @interface After { -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/Before.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/event/Before.java deleted file mode 100644 index dc16b51..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/Before.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry.event; - -import javax.inject.Qualifier; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * @author Christian Bauer - */ -@Qualifier -@Target({FIELD, PARAMETER}) -@Retention(RUNTIME) -public @interface Before { -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/DeviceDiscovery.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/event/DeviceDiscovery.java deleted file mode 100644 index d80f829..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/DeviceDiscovery.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry.event; - -import org.fourthline.cling.model.meta.Device; - -/** - * An observable event for CDI containers. - * - * @author Christian Bauer - */ -public class DeviceDiscovery { - - protected D device; - - public DeviceDiscovery(D device) { - this.device = device; - } - - public D getDevice() { - return device; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/FailedRemoteDeviceDiscovery.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/event/FailedRemoteDeviceDiscovery.java deleted file mode 100644 index 0e35de9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/FailedRemoteDeviceDiscovery.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry.event; - -import org.fourthline.cling.model.meta.RemoteDevice; - -/** - * @author Christian Bauer - */ -public class FailedRemoteDeviceDiscovery extends DeviceDiscovery { - - protected Exception exception; - - public FailedRemoteDeviceDiscovery(RemoteDevice device, Exception ex) { - super(device); - this.exception = ex; - } - - public Exception getException() { - return exception; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/LocalDeviceDiscovery.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/event/LocalDeviceDiscovery.java deleted file mode 100644 index 54cc895..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/LocalDeviceDiscovery.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry.event; - -import org.fourthline.cling.model.meta.LocalDevice; - -/** - * @author Christian Bauer - */ -public class LocalDeviceDiscovery extends DeviceDiscovery { - - public LocalDeviceDiscovery(LocalDevice device) { - super(device); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/Phase.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/event/Phase.java deleted file mode 100644 index cabc336..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/Phase.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry.event; - -import javax.enterprise.util.AnnotationLiteral; -import javax.inject.Qualifier; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * @author Christian Bauer - */ - -public interface Phase { - - public static AnnotationLiteral ALIVE = new AnnotationLiteral() { - }; - - public static AnnotationLiteral COMPLETE = new AnnotationLiteral() { - }; - - public static AnnotationLiteral BYEBYE = new AnnotationLiteral() { - }; - - public static AnnotationLiteral UPDATED = new AnnotationLiteral() { - }; - - - @Qualifier - @Target({FIELD, PARAMETER}) - @Retention(RUNTIME) - public @interface Alive { - - } - - @Qualifier - @Target({FIELD, PARAMETER}) - @Retention(RUNTIME) - public @interface Complete { - - } - - @Qualifier - @Target({FIELD, PARAMETER}) - @Retention(RUNTIME) - public @interface Byebye { - - } - - @Qualifier - @Target({FIELD, PARAMETER}) - @Retention(RUNTIME) - public @interface Updated { - - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/RegistryShutdown.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/event/RegistryShutdown.java deleted file mode 100644 index 92bf3be..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/RegistryShutdown.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry.event; - -/** - * @author Christian Bauer - */ -public class RegistryShutdown { -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/RemoteDeviceDiscovery.java b/clinglibrary/src/main/java/org/fourthline/cling/registry/event/RemoteDeviceDiscovery.java deleted file mode 100644 index 491205d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/registry/event/RemoteDeviceDiscovery.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.registry.event; - -import org.fourthline.cling.model.meta.RemoteDevice; - -/** - * @author Christian Bauer - */ -public class RemoteDeviceDiscovery extends DeviceDiscovery { - - public RemoteDeviceDiscovery(RemoteDevice device) { - super(device); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AVTransportErrorCode.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AVTransportErrorCode.java deleted file mode 100644 index aa1c9c6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AVTransportErrorCode.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport; - -/** - * - */ -public enum AVTransportErrorCode { - - TRANSITION_NOT_AVAILABLE(701, "The immediate transition from current to desired state not supported"), - NO_CONTENTS(702, "The media does not contain any contents that can be played"), - READ_ERROR(703, "The media cannot be read"), - PLAYBACK_FORMAT_NOT_SUPPORTED(704, "The storage format of the currently loaded media is not supported for playback"), - TRANSPORT_LOCKED(705, "The transport is 'hold locked', e.g. with a keyboard lock"), - WRITE_ERROR(706, "The media cannot be written"), - MEDIA_PROTECTED(707, "The media is write-protected or is of a not writable type"), - RECORD_FORMAT_NOT_SUPPORTED(708, "The storage format of the currently loaded media is not supported for recording"), - MEDIA_FULL(709, "There is no free space left on the loaded media"), - SEEKMODE_NOT_SUPPORTED(710, "The specified seek mode is not supported by the device"), - ILLEGAL_SEEK_TARGET(711, "The specified seek target is not specified in terms of the seek mode, or is not present on the media"), - PLAYMODE_NOT_SUPPORTED(712, "The specified play mode is not supported by the device"), - RECORDQUALITYMODE_NOT_SUPPORTED(713, "The specified record quality mode is not supported by the device"), - ILLEGAL_MIME_TYPE(714, "The specified resource has a MIME-type which is not supported"), - CONTENT_BUSY(715, "The resource is already being played by other means"), - RESOURCE_NOT_FOUND(716, "The specified resource cannot be found in the network"), - INVALID_INSTANCE_ID(718, "The specified instanceID is invalid for this AVTransport"); - - private int code; - private String description; - - AVTransportErrorCode(int code, String description) { - this.code = code; - this.description = description; - } - - public int getCode() { - return code; - } - - public String getDescription() { - return description; - } - - public static AVTransportErrorCode getByCode(int code) { - for (AVTransportErrorCode errorCode : values()) { - if (errorCode.getCode() == code) - return errorCode; - } - return null; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AVTransportException.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AVTransportException.java deleted file mode 100644 index 3cf6e90..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AVTransportException.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport; - -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.types.ErrorCode; - -/** - * - */ -public class AVTransportException extends ActionException { - - public AVTransportException(int errorCode, String message) { - super(errorCode, message); - } - - public AVTransportException(int errorCode, String message, Throwable cause) { - super(errorCode, message, cause); - } - - public AVTransportException(ErrorCode errorCode, String message) { - super(errorCode, message); - } - - public AVTransportException(ErrorCode errorCode) { - super(errorCode); - } - - public AVTransportException(AVTransportErrorCode errorCode, String message) { - super(errorCode.getCode(), errorCode.getDescription() + ". " + message + "."); - } - - public AVTransportException(AVTransportErrorCode errorCode) { - super(errorCode.getCode(), errorCode.getDescription()); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AbstractAVTransportService.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AbstractAVTransportService.java deleted file mode 100644 index 3ca0465..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/AbstractAVTransportService.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport; - -import org.fourthline.cling.binding.annotations.UpnpAction; -import org.fourthline.cling.binding.annotations.UpnpInputArgument; -import org.fourthline.cling.binding.annotations.UpnpOutputArgument; -import org.fourthline.cling.binding.annotations.UpnpService; -import org.fourthline.cling.binding.annotations.UpnpServiceId; -import org.fourthline.cling.binding.annotations.UpnpServiceType; -import org.fourthline.cling.binding.annotations.UpnpStateVariable; -import org.fourthline.cling.binding.annotations.UpnpStateVariables; -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.avtransport.lastchange.AVTransportLastChangeParser; -import org.fourthline.cling.support.avtransport.lastchange.AVTransportVariable; -import org.fourthline.cling.support.lastchange.LastChange; -import org.fourthline.cling.support.lastchange.LastChangeDelegator; -import org.fourthline.cling.support.model.DeviceCapabilities; -import org.fourthline.cling.support.model.MediaInfo; -import org.fourthline.cling.support.model.PlayMode; -import org.fourthline.cling.support.model.PositionInfo; -import org.fourthline.cling.support.model.RecordMediumWriteStatus; -import org.fourthline.cling.support.model.RecordQualityMode; -import org.fourthline.cling.support.model.SeekMode; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.model.TransportAction; -import org.fourthline.cling.support.model.TransportInfo; -import org.fourthline.cling.support.model.TransportSettings; -import org.fourthline.cling.support.model.TransportState; -import org.fourthline.cling.support.model.TransportStatus; - -import java.beans.PropertyChangeSupport; -import java.net.URI; - -/** - * Skeleton of service with "LastChange" eventing support. - * - * @author Christian Bauer - */ -@UpnpService( - serviceId = @UpnpServiceId("AVTransport"), - serviceType = @UpnpServiceType(value = "AVTransport", version = 1), - stringConvertibleTypes = LastChange.class -) -@UpnpStateVariables({ - @UpnpStateVariable( - name = "TransportState", - sendEvents = false, - allowedValuesEnum = TransportState.class), - @UpnpStateVariable( - name = "TransportStatus", - sendEvents = false, - allowedValuesEnum = TransportStatus.class), - @UpnpStateVariable( - name = "PlaybackStorageMedium", - sendEvents = false, - defaultValue = "NONE", - allowedValuesEnum = StorageMedium.class), - @UpnpStateVariable( - name = "RecordStorageMedium", - sendEvents = false, - defaultValue = "NOT_IMPLEMENTED", - allowedValuesEnum = StorageMedium.class), - @UpnpStateVariable( - name = "PossiblePlaybackStorageMedia", - sendEvents = false, - datatype = "string", - defaultValue = "NETWORK"), - @UpnpStateVariable( - name = "PossibleRecordStorageMedia", - sendEvents = false, - datatype = "string", - defaultValue = "NOT_IMPLEMENTED"), - @UpnpStateVariable( // TODO - name = "CurrentPlayMode", - sendEvents = false, - defaultValue = "NORMAL", - allowedValuesEnum = PlayMode.class), - @UpnpStateVariable( // TODO - name = "TransportPlaySpeed", - sendEvents = false, - datatype = "string", - defaultValue = "1"), // 1, 1/2, 2, -1, 1/10, etc. - @UpnpStateVariable( - name = "RecordMediumWriteStatus", - sendEvents = false, - defaultValue = "NOT_IMPLEMENTED", - allowedValuesEnum = RecordMediumWriteStatus.class), - @UpnpStateVariable( - name = "CurrentRecordQualityMode", - sendEvents = false, - defaultValue = "NOT_IMPLEMENTED", - allowedValuesEnum = RecordQualityMode.class), - @UpnpStateVariable( - name = "PossibleRecordQualityModes", - sendEvents = false, - datatype = "string", - defaultValue = "NOT_IMPLEMENTED"), - @UpnpStateVariable( - name = "NumberOfTracks", - sendEvents = false, - datatype = "ui4", - defaultValue = "0"), - @UpnpStateVariable( - name = "CurrentTrack", - sendEvents = false, - datatype = "ui4", - defaultValue = "0"), - @UpnpStateVariable( - name = "CurrentTrackDuration", - sendEvents = false, - datatype = "string"), // H+:MM:SS[.F+] or H+:MM:SS[.F0/F1] - @UpnpStateVariable( - name = "CurrentMediaDuration", - sendEvents = false, - datatype = "string", - defaultValue = "00:00:00"), - @UpnpStateVariable( - name = "CurrentTrackMetaData", - sendEvents = false, - datatype = "string", - defaultValue = "NOT_IMPLEMENTED"), - @UpnpStateVariable( - name = "CurrentTrackURI", - sendEvents = false, - datatype = "string"), - @UpnpStateVariable( - name = "AVTransportURI", - sendEvents = false, - datatype = "string"), - @UpnpStateVariable( - name = "AVTransportURIMetaData", - sendEvents = false, - datatype = "string", - defaultValue = "NOT_IMPLEMENTED"), - @UpnpStateVariable( - name = "NextAVTransportURI", - sendEvents = false, - datatype = "string", - defaultValue = "NOT_IMPLEMENTED"), - @UpnpStateVariable( - name = "NextAVTransportURIMetaData", - sendEvents = false, - datatype = "string", - defaultValue = "NOT_IMPLEMENTED"), - @UpnpStateVariable( - name = "RelativeTimePosition", - sendEvents = false, - datatype = "string"), // H+:MM:SS[.F+] or H+:MM:SS[.F0/F1] (in track) - @UpnpStateVariable( - name = "AbsoluteTimePosition", - sendEvents = false, - datatype = "string"), // H+:MM:SS[.F+] or H+:MM:SS[.F0/F1] (in media) - @UpnpStateVariable( - name = "RelativeCounterPosition", - sendEvents = false, - datatype = "i4", - defaultValue = "2147483647"), // Max value means not implemented - @UpnpStateVariable( - name = "AbsoluteCounterPosition", - sendEvents = false, - datatype = "i4", - defaultValue = "2147483647"), // Max value means not implemented - @UpnpStateVariable( - name = "CurrentTransportActions", - sendEvents = false, - datatype = "string"), // Play, Stop, Pause, Seek, Next, Previous and Record - @UpnpStateVariable( - name = "A_ARG_TYPE_SeekMode", - sendEvents = false, - allowedValuesEnum = SeekMode.class), // The 'type' of seek we can perform (or should perform) - @UpnpStateVariable( - name = "A_ARG_TYPE_SeekTarget", - sendEvents = false, - datatype = "string"), // The actual seek (offset or whatever) value - @UpnpStateVariable( - name = "A_ARG_TYPE_InstanceID", - sendEvents = false, - datatype = "ui4") -}) -public abstract class AbstractAVTransportService implements LastChangeDelegator { - - @UpnpStateVariable(eventMaximumRateMilliseconds = 200) - final private LastChange lastChange; - final protected PropertyChangeSupport propertyChangeSupport; - - protected AbstractAVTransportService() { - this.propertyChangeSupport = new PropertyChangeSupport(this); - this.lastChange = new LastChange(new AVTransportLastChangeParser()); - } - - protected AbstractAVTransportService(LastChange lastChange) { - this.propertyChangeSupport = new PropertyChangeSupport(this); - this.lastChange = lastChange; - } - - protected AbstractAVTransportService(PropertyChangeSupport propertyChangeSupport) { - this.propertyChangeSupport = propertyChangeSupport; - this.lastChange = new LastChange(new AVTransportLastChangeParser()); - } - - protected AbstractAVTransportService(PropertyChangeSupport propertyChangeSupport, LastChange lastChange) { - this.propertyChangeSupport = propertyChangeSupport; - this.lastChange = lastChange; - } - - @Override - public LastChange getLastChange() { - return lastChange; - } - - @Override - public void appendCurrentState(LastChange lc, UnsignedIntegerFourBytes instanceId) throws Exception { - - MediaInfo mediaInfo = getMediaInfo(instanceId); - TransportInfo transportInfo = getTransportInfo(instanceId); - TransportSettings transportSettings = getTransportSettings(instanceId); - PositionInfo positionInfo = getPositionInfo(instanceId); - DeviceCapabilities deviceCaps = getDeviceCapabilities(instanceId); - - lc.setEventedValue( - instanceId, - new AVTransportVariable.AVTransportURI(URI.create(mediaInfo.getCurrentURI())), - new AVTransportVariable.AVTransportURIMetaData(mediaInfo.getCurrentURIMetaData()), - new AVTransportVariable.CurrentMediaDuration(mediaInfo.getMediaDuration()), - new AVTransportVariable.CurrentPlayMode(transportSettings.getPlayMode()), - new AVTransportVariable.CurrentRecordQualityMode(transportSettings.getRecQualityMode()), - new AVTransportVariable.CurrentTrack(positionInfo.getTrack()), - new AVTransportVariable.CurrentTrackDuration(positionInfo.getTrackDuration()), - new AVTransportVariable.CurrentTrackMetaData(positionInfo.getTrackMetaData()), - new AVTransportVariable.CurrentTrackURI(URI.create(positionInfo.getTrackURI())), - new AVTransportVariable.CurrentTransportActions(getCurrentTransportActions(instanceId)), - new AVTransportVariable.NextAVTransportURI(URI.create(mediaInfo.getNextURI())), - new AVTransportVariable.NextAVTransportURIMetaData(mediaInfo.getNextURIMetaData()), - new AVTransportVariable.NumberOfTracks(mediaInfo.getNumberOfTracks()), - new AVTransportVariable.PossiblePlaybackStorageMedia(deviceCaps.getPlayMedia()), - new AVTransportVariable.PossibleRecordQualityModes(deviceCaps.getRecQualityModes()), - new AVTransportVariable.PossibleRecordStorageMedia(deviceCaps.getRecMedia()), - new AVTransportVariable.RecordMediumWriteStatus(mediaInfo.getWriteStatus()), - new AVTransportVariable.RecordStorageMedium(mediaInfo.getRecordMedium()), - new AVTransportVariable.TransportPlaySpeed(transportInfo.getCurrentSpeed()), - new AVTransportVariable.TransportState(transportInfo.getCurrentTransportState()), - new AVTransportVariable.TransportStatus(transportInfo.getCurrentTransportStatus()) - ); - } - - public PropertyChangeSupport getPropertyChangeSupport() { - return propertyChangeSupport; - } - - public static UnsignedIntegerFourBytes getDefaultInstanceID() { - return new UnsignedIntegerFourBytes(0); - } - - @UpnpAction - public abstract void setAVTransportURI(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "CurrentURI", stateVariable = "AVTransportURI") String currentURI, - @UpnpInputArgument(name = "CurrentURIMetaData", stateVariable = "AVTransportURIMetaData") String currentURIMetaData) - throws AVTransportException; - - @UpnpAction - public abstract void setNextAVTransportURI(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "NextURI", stateVariable = "AVTransportURI") String nextURI, - @UpnpInputArgument(name = "NextURIMetaData", stateVariable = "AVTransportURIMetaData") String nextURIMetaData) - throws AVTransportException; - - @UpnpAction(out = { - @UpnpOutputArgument(name = "NrTracks", stateVariable = "NumberOfTracks", getterName = "getNumberOfTracks"), - @UpnpOutputArgument(name = "MediaDuration", stateVariable = "CurrentMediaDuration", getterName = "getMediaDuration"), - @UpnpOutputArgument(name = "CurrentURI", stateVariable = "AVTransportURI", getterName = "getCurrentURI"), - @UpnpOutputArgument(name = "CurrentURIMetaData", stateVariable = "AVTransportURIMetaData", getterName = "getCurrentURIMetaData"), - @UpnpOutputArgument(name = "NextURI", stateVariable = "NextAVTransportURI", getterName = "getNextURI"), - @UpnpOutputArgument(name = "NextURIMetaData", stateVariable = "NextAVTransportURIMetaData", getterName = "getNextURIMetaData"), - @UpnpOutputArgument(name = "PlayMedium", stateVariable = "PlaybackStorageMedium", getterName = "getPlayMedium"), - @UpnpOutputArgument(name = "RecordMedium", stateVariable = "RecordStorageMedium", getterName = "getRecordMedium"), - @UpnpOutputArgument(name = "WriteStatus", stateVariable = "RecordMediumWriteStatus", getterName = "getWriteStatus") - }) - public abstract MediaInfo getMediaInfo(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException; - - @UpnpAction(out = { - @UpnpOutputArgument(name = "CurrentTransportState", stateVariable = "TransportState", getterName = "getCurrentTransportState"), - @UpnpOutputArgument(name = "CurrentTransportStatus", stateVariable = "TransportStatus", getterName = "getCurrentTransportStatus"), - @UpnpOutputArgument(name = "CurrentSpeed", stateVariable = "TransportPlaySpeed", getterName = "getCurrentSpeed") - }) - public abstract TransportInfo getTransportInfo(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException; - - @UpnpAction(out = { - @UpnpOutputArgument(name = "Track", stateVariable = "CurrentTrack", getterName = "getTrack"), - @UpnpOutputArgument(name = "TrackDuration", stateVariable = "CurrentTrackDuration", getterName = "getTrackDuration"), - @UpnpOutputArgument(name = "TrackMetaData", stateVariable = "CurrentTrackMetaData", getterName = "getTrackMetaData"), - @UpnpOutputArgument(name = "TrackURI", stateVariable = "CurrentTrackURI", getterName = "getTrackURI"), - @UpnpOutputArgument(name = "RelTime", stateVariable = "RelativeTimePosition", getterName = "getRelTime"), - @UpnpOutputArgument(name = "AbsTime", stateVariable = "AbsoluteTimePosition", getterName = "getAbsTime"), - @UpnpOutputArgument(name = "RelCount", stateVariable = "RelativeCounterPosition", getterName = "getRelCount"), - @UpnpOutputArgument(name = "AbsCount", stateVariable = "AbsoluteCounterPosition", getterName = "getAbsCount") - }) - public abstract PositionInfo getPositionInfo(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException; - - @UpnpAction(out = { - @UpnpOutputArgument(name = "PlayMedia", stateVariable = "PossiblePlaybackStorageMedia", getterName = "getPlayMediaString"), - @UpnpOutputArgument(name = "RecMedia", stateVariable = "PossibleRecordStorageMedia", getterName = "getRecMediaString"), - @UpnpOutputArgument(name = "RecQualityModes", stateVariable = "PossibleRecordQualityModes", getterName = "getRecQualityModesString") - }) - public abstract DeviceCapabilities getDeviceCapabilities(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException; - - @UpnpAction(out = { - @UpnpOutputArgument(name = "PlayMode", stateVariable = "CurrentPlayMode", getterName = "getPlayMode"), - @UpnpOutputArgument(name = "RecQualityMode", stateVariable = "CurrentRecordQualityMode", getterName = "getRecQualityMode") - }) - public abstract TransportSettings getTransportSettings(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException; - - @UpnpAction - public abstract void stop(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException; - - @UpnpAction - public abstract void play(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Speed", stateVariable = "TransportPlaySpeed") String speed) - throws AVTransportException; - - @UpnpAction - public abstract void pause(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException; - - @UpnpAction - public abstract void record(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException; - - @UpnpAction - public abstract void seek(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Unit", stateVariable = "A_ARG_TYPE_SeekMode") String unit, - @UpnpInputArgument(name = "Target", stateVariable = "A_ARG_TYPE_SeekTarget") String target) - throws AVTransportException; - - @UpnpAction - public abstract void next(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException; - - @UpnpAction - public abstract void previous(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException; - - @UpnpAction - public abstract void setPlayMode(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "NewPlayMode", stateVariable = "CurrentPlayMode") String newPlayMode) - throws AVTransportException; - - @UpnpAction - public abstract void setRecordQualityMode(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "NewRecordQualityMode", stateVariable = "CurrentRecordQualityMode") String newRecordQualityMode) - throws AVTransportException; - - @UpnpAction(name = "GetCurrentTransportActions", out = @UpnpOutputArgument(name = "Actions", stateVariable = "CurrentTransportActions")) - public String getCurrentTransportActionsString(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) - throws AVTransportException { - try { - return ModelUtil.toCommaSeparatedList(getCurrentTransportActions(instanceId)); - } catch (Exception ex) { - return ""; // TODO: Empty string is not defined in spec but seems reasonable for no available action? - } - } - - protected abstract TransportAction[] getCurrentTransportActions(UnsignedIntegerFourBytes instanceId) throws Exception; -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetCurrentTransportActions.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetCurrentTransportActions.java deleted file mode 100644 index 32bfaf3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetCurrentTransportActions.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.TransportAction; - -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public abstract class GetCurrentTransportActions extends ActionCallback { - - private static Logger log = Logger.getLogger(GetCurrentTransportActions.class.getName()); - - public GetCurrentTransportActions(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - - public GetCurrentTransportActions(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("GetCurrentTransportActions"))); - getActionInvocation().setInput("InstanceID", instanceId); - } - - public void success(ActionInvocation invocation) { - String actionsString = (String)invocation.getOutput("Actions").getValue(); - received(invocation, TransportAction.valueOfCommaSeparatedList(actionsString)); - } - - public abstract void received(ActionInvocation actionInvocation, TransportAction[] actions); - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetDeviceCapabilities.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetDeviceCapabilities.java deleted file mode 100644 index b01ae4e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetDeviceCapabilities.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.DeviceCapabilities; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class GetDeviceCapabilities extends ActionCallback { - - private static Logger log = Logger.getLogger(GetDeviceCapabilities.class.getName()); - - public GetDeviceCapabilities(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - - public GetDeviceCapabilities(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("GetDeviceCapabilities"))); - getActionInvocation().setInput("InstanceID", instanceId); - } - - public void success(ActionInvocation invocation) { - DeviceCapabilities caps = new DeviceCapabilities(invocation.getOutputMap()); - received(invocation, caps); - } - - public abstract void received(ActionInvocation actionInvocation, DeviceCapabilities caps); - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetMediaInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetMediaInfo.java deleted file mode 100644 index 69635ff..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetMediaInfo.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.MediaInfo; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class GetMediaInfo extends ActionCallback { - - private static Logger log = Logger.getLogger(GetMediaInfo.class.getName()); - - public GetMediaInfo(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - - public GetMediaInfo(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("GetMediaInfo"))); - getActionInvocation().setInput("InstanceID", instanceId); - } - - public void success(ActionInvocation invocation) { - MediaInfo mediaInfo = new MediaInfo(invocation.getOutputMap()); - received(invocation, mediaInfo); - } - - public abstract void received(ActionInvocation invocation, MediaInfo mediaInfo); - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetPositionInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetPositionInfo.java deleted file mode 100644 index a25e784..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetPositionInfo.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.PositionInfo; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class GetPositionInfo extends ActionCallback { - - private static Logger log = Logger.getLogger(GetPositionInfo.class.getName()); - - public GetPositionInfo(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - - public GetPositionInfo(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("GetPositionInfo"))); - getActionInvocation().setInput("InstanceID", instanceId); - } - - public void success(ActionInvocation invocation) { - PositionInfo positionInfo = new PositionInfo(invocation.getOutputMap()); - received(invocation, positionInfo); - } - - public abstract void received(ActionInvocation invocation, PositionInfo positionInfo); - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetTransportInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetTransportInfo.java deleted file mode 100644 index 1194580..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/GetTransportInfo.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.TransportInfo; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class GetTransportInfo extends ActionCallback { - - private static Logger log = Logger.getLogger(GetTransportInfo.class.getName()); - - public GetTransportInfo(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - - public GetTransportInfo(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("GetTransportInfo"))); - getActionInvocation().setInput("InstanceID", instanceId); - } - - public void success(ActionInvocation invocation) { - TransportInfo transportInfo = new TransportInfo(invocation.getOutputMap()); - received(invocation, transportInfo); - } - - public abstract void received(ActionInvocation invocation, TransportInfo transportInfo); - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Next.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Next.java deleted file mode 100644 index 6c75656..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Next.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class Next extends ActionCallback { - - private static Logger log = Logger.getLogger(Next.class.getName()); - - protected Next(ActionInvocation actionInvocation, ControlPoint controlPoint) { - super(actionInvocation, controlPoint); - } - - protected Next(ActionInvocation actionInvocation) { - super(actionInvocation); - } - - public Next(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - - public Next(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("Next"))); - getActionInvocation().setInput("InstanceID", instanceId); - } - - @Override - public void success(ActionInvocation invocation) { - log.fine("Execution successful"); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Pause.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Pause.java deleted file mode 100644 index 96512ea..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Pause.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class Pause extends ActionCallback { - - private static Logger log = Logger.getLogger(Pause.class.getName()); - - protected Pause(ActionInvocation actionInvocation, ControlPoint controlPoint) { - super(actionInvocation, controlPoint); - } - - protected Pause(ActionInvocation actionInvocation) { - super(actionInvocation); - } - - public Pause(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - - public Pause(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("Pause"))); - getActionInvocation().setInput("InstanceID", instanceId); - } - - @Override - public void success(ActionInvocation invocation) { - log.fine("Execution successful"); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Play.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Play.java deleted file mode 100644 index 6179fe6..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Play.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class Play extends ActionCallback { - - private static Logger log = Logger.getLogger(Play.class.getName()); - - public Play(Service service) { - this(new UnsignedIntegerFourBytes(0), service, "1"); - } - - public Play(Service service, String speed) { - this(new UnsignedIntegerFourBytes(0), service, speed); - } - - public Play(UnsignedIntegerFourBytes instanceId, Service service) { - this(instanceId, service, "1"); - } - - public Play(UnsignedIntegerFourBytes instanceId, Service service, String speed) { - super(new ActionInvocation(service.getAction("Play"))); - getActionInvocation().setInput("InstanceID", instanceId); - getActionInvocation().setInput("Speed", speed); - } - - @Override - public void success(ActionInvocation invocation) { - log.fine("Execution successful"); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Previous.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Previous.java deleted file mode 100644 index ae3b80d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Previous.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class Previous extends ActionCallback { - - private static Logger log = Logger.getLogger(Previous.class.getName()); - - protected Previous(ActionInvocation actionInvocation, ControlPoint controlPoint) { - super(actionInvocation, controlPoint); - } - - protected Previous(ActionInvocation actionInvocation) { - super(actionInvocation); - } - - public Previous(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - - public Previous(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("Previous"))); - getActionInvocation().setInput("InstanceID", instanceId); - } - - @Override - public void success(ActionInvocation invocation) { - log.fine("Execution successful"); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Seek.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Seek.java deleted file mode 100644 index 1da559e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Seek.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.SeekMode; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class Seek extends ActionCallback { - - private static Logger log = Logger.getLogger(Seek.class.getName()); - - public Seek(Service service, String relativeTimeTarget) { - this(new UnsignedIntegerFourBytes(0), service, SeekMode.REL_TIME, relativeTimeTarget); - } - - public Seek(UnsignedIntegerFourBytes instanceId, Service service, String relativeTimeTarget) { - this(instanceId, service, SeekMode.REL_TIME, relativeTimeTarget); - } - - public Seek(Service service, SeekMode mode, String target) { - this(new UnsignedIntegerFourBytes(0), service, mode, target); - } - - public Seek(UnsignedIntegerFourBytes instanceId, Service service, SeekMode mode, String target) { - super(new ActionInvocation(service.getAction("Seek"))); - getActionInvocation().setInput("InstanceID", instanceId); - getActionInvocation().setInput("Unit", mode.name()); - getActionInvocation().setInput("Target", target); - } - - @Override - public void success(ActionInvocation invocation) { - log.fine("Execution successful"); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/SetAVTransportURI.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/SetAVTransportURI.java deleted file mode 100644 index 159e3b5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/SetAVTransportURI.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public abstract class SetAVTransportURI extends ActionCallback { - - private static Logger log = Logger.getLogger(SetAVTransportURI.class.getName()); - - public SetAVTransportURI(Service service, String uri) { - this(new UnsignedIntegerFourBytes(0), service, uri, null); - } - - public SetAVTransportURI(Service service, String uri, String metadata) { - this(new UnsignedIntegerFourBytes(0), service, uri, metadata); - } - - public SetAVTransportURI(UnsignedIntegerFourBytes instanceId, Service service, String uri) { - this(instanceId, service, uri, null); - } - - public SetAVTransportURI(UnsignedIntegerFourBytes instanceId, Service service, String uri, String metadata) { - super(new ActionInvocation(service.getAction("SetAVTransportURI"))); - log.fine("Creating SetAVTransportURI action for URI: " + uri); - getActionInvocation().setInput("InstanceID", instanceId); - getActionInvocation().setInput("CurrentURI", uri); - getActionInvocation().setInput("CurrentURIMetaData", metadata); - } - - @Override - public void success(ActionInvocation invocation) { - log.fine("Execution successful"); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/SetPlayMode.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/SetPlayMode.java deleted file mode 100644 index 8463766..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/SetPlayMode.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.PlayMode; - -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public abstract class SetPlayMode extends ActionCallback { - - private static Logger log = Logger.getLogger(SetPlayMode.class.getName()); - - public SetPlayMode(Service service, PlayMode playMode) { - this(new UnsignedIntegerFourBytes(0), service, playMode); - } - - public SetPlayMode(UnsignedIntegerFourBytes instanceId, Service service, PlayMode playMode) { - super(new ActionInvocation(service.getAction("SetPlayMode"))); - getActionInvocation().setInput("InstanceID", instanceId); - getActionInvocation().setInput("NewPlayMode", playMode.toString()); - } - - @Override - public void success(ActionInvocation invocation) { - log.fine("Execution successful"); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Stop.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Stop.java deleted file mode 100644 index 8a83a57..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/callback/Stop.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class Stop extends ActionCallback { - - private static Logger log = Logger.getLogger(Stop.class.getName()); - - public Stop(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - - public Stop(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("Stop"))); - getActionInvocation().setInput("InstanceID", instanceId); - } - - @Override - public void success(ActionInvocation invocation) { - log.fine("Execution successful"); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/AVTransportService.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/AVTransportService.java deleted file mode 100644 index d595432..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/AVTransportService.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.impl; - -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.avtransport.AVTransportErrorCode; -import org.fourthline.cling.support.avtransport.AVTransportException; -import org.fourthline.cling.support.avtransport.AbstractAVTransportService; -import org.fourthline.cling.support.avtransport.impl.state.AbstractState; -import org.fourthline.cling.support.lastchange.LastChange; -import org.fourthline.cling.support.model.AVTransport; -import org.fourthline.cling.support.model.DeviceCapabilities; -import org.fourthline.cling.support.model.MediaInfo; -import org.fourthline.cling.support.model.PlayMode; -import org.fourthline.cling.support.model.PositionInfo; -import org.fourthline.cling.support.model.RecordQualityMode; -import org.fourthline.cling.support.model.SeekMode; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.model.TransportAction; -import org.fourthline.cling.support.model.TransportInfo; -import org.fourthline.cling.support.model.TransportSettings; -import org.seamless.statemachine.StateMachineBuilder; -import org.seamless.statemachine.TransitionException; - -import java.net.URI; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; - -/** - * State-machine based implementation of AVTransport service. - *

- * One logical AVTransport is represented by: - *

- *
    - *
  • - * One {@link org.fourthline.cling.support.avtransport.impl.AVTransportStateMachine} - * instance that accepts the action method call as a proxy. - *
  • - *
  • - * Each state machine holds several instances of - * {@link org.fourthline.cling.support.avtransport.impl.state.AbstractState}, created on - * instantation of the state machine. The "current" state will be the target of - * the action call. It is the state implementation that decides how to handle the - * call and what the next state is after a possible transition. - *
  • - *
  • - * Each state has a reference to an implementation of - * {@link org.fourthline.cling.support.model.AVTransport}, where the state can hold - * information about well, the state. - *
  • - *
- *

- * Simplified, this means that each AVTransport instance ID is typically handled by - * one state machine, and the internal state of that machine is stored in an - * AVTransport. - *

- *

- * Override the {@link #createTransport(org.fourthline.cling.model.types.UnsignedIntegerFourBytes, org.fourthline.cling.support.lastchange.LastChange)} - * method to utilize a subclass of AVTransport as your internal state holder. - *

- * - * @author Christian Bauer - */ -public class AVTransportService extends AbstractAVTransportService { - - final private static Logger log = Logger.getLogger(AVTransportService.class.getName()); - - final private Map stateMachines = new ConcurrentHashMap(); - - final Class stateMachineDefinition; - final Class initialState; - final Class transportClass; - - public AVTransportService(Class stateMachineDefinition, - Class initialState) { - this(stateMachineDefinition, initialState, (Class)AVTransport.class); - } - - public AVTransportService(Class stateMachineDefinition, - Class initialState, - Class transportClass) { - this.stateMachineDefinition = stateMachineDefinition; - this.initialState = initialState; - this.transportClass = transportClass; - } - - public void setAVTransportURI(UnsignedIntegerFourBytes instanceId, - String currentURI, - String currentURIMetaData) throws AVTransportException { - - URI uri; - try { - uri = new URI(currentURI); - } catch (Exception ex) { - throw new AVTransportException( - ErrorCode.INVALID_ARGS, "CurrentURI can not be null or malformed" - ); - } - - try { - AVTransportStateMachine transportStateMachine = findStateMachine(instanceId, true); - transportStateMachine.setTransportURI(uri, currentURIMetaData); - } catch (TransitionException ex) { - throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); - } - } - - public void setNextAVTransportURI(UnsignedIntegerFourBytes instanceId, - String nextURI, - String nextURIMetaData) throws AVTransportException { - - URI uri; - try { - uri = new URI(nextURI); - } catch (Exception ex) { - throw new AVTransportException( - ErrorCode.INVALID_ARGS, "NextURI can not be null or malformed" - ); - } - - try { - AVTransportStateMachine transportStateMachine = findStateMachine(instanceId, true); - transportStateMachine.setNextTransportURI(uri, nextURIMetaData); - } catch (TransitionException ex) { - throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); - } - } - - public void setPlayMode(UnsignedIntegerFourBytes instanceId, String newPlayMode) throws AVTransportException { - AVTransport transport = findStateMachine(instanceId).getCurrentState().getTransport(); - try { - transport.setTransportSettings( - new TransportSettings( - PlayMode.valueOf(newPlayMode), - transport.getTransportSettings().getRecQualityMode() - ) - ); - } catch (IllegalArgumentException ex) { - throw new AVTransportException( - AVTransportErrorCode.PLAYMODE_NOT_SUPPORTED, "Unsupported play mode: " + newPlayMode - ); - } - } - - public void setRecordQualityMode(UnsignedIntegerFourBytes instanceId, String newRecordQualityMode) throws AVTransportException { - AVTransport transport = findStateMachine(instanceId).getCurrentState().getTransport(); - try { - transport.setTransportSettings( - new TransportSettings( - transport.getTransportSettings().getPlayMode(), - RecordQualityMode.valueOrExceptionOf(newRecordQualityMode) - ) - ); - } catch (IllegalArgumentException ex) { - throw new AVTransportException( - AVTransportErrorCode.RECORDQUALITYMODE_NOT_SUPPORTED, "Unsupported record quality mode: " + newRecordQualityMode - ); - } - } - - public MediaInfo getMediaInfo(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - return findStateMachine(instanceId).getCurrentState().getTransport().getMediaInfo(); - } - - public TransportInfo getTransportInfo(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - return findStateMachine(instanceId).getCurrentState().getTransport().getTransportInfo(); - } - - public PositionInfo getPositionInfo(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - return findStateMachine(instanceId).getCurrentState().getTransport().getPositionInfo(); - } - - public DeviceCapabilities getDeviceCapabilities(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - return findStateMachine(instanceId).getCurrentState().getTransport().getDeviceCapabilities(); - } - - public TransportSettings getTransportSettings(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - return findStateMachine(instanceId).getCurrentState().getTransport().getTransportSettings(); - } - - public void stop(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - try { - findStateMachine(instanceId).stop(); - } catch (TransitionException ex) { - throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); - } - } - - public void play(UnsignedIntegerFourBytes instanceId, String speed) throws AVTransportException { - try { - findStateMachine(instanceId).play(speed); - } catch (TransitionException ex) { - throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); - } - } - - public void pause(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - try { - findStateMachine(instanceId).pause(); - } catch (TransitionException ex) { - throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); - } - } - - public void record(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - try { - findStateMachine(instanceId).record(); - } catch (TransitionException ex) { - throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); - } - } - - public void seek(UnsignedIntegerFourBytes instanceId, String unit, String target) throws AVTransportException { - SeekMode seekMode; - try { - seekMode = SeekMode.valueOrExceptionOf(unit); - } catch (IllegalArgumentException ex) { - throw new AVTransportException( - AVTransportErrorCode.SEEKMODE_NOT_SUPPORTED, "Unsupported seek mode: " + unit - ); - } - - try { - findStateMachine(instanceId).seek(seekMode, target); - } catch (TransitionException ex) { - throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); - } - } - - public void next(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - try { - findStateMachine(instanceId).next(); - } catch (TransitionException ex) { - throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); - } - } - - public void previous(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - try { - findStateMachine(instanceId).previous(); - } catch (TransitionException ex) { - throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); - } - } - - @Override - protected TransportAction[] getCurrentTransportActions(UnsignedIntegerFourBytes instanceId) throws Exception { - AVTransportStateMachine stateMachine = findStateMachine(instanceId); - try { - return stateMachine.getCurrentState().getCurrentTransportActions(); - } catch (TransitionException ex) { - return new TransportAction[0]; - } - } - - @Override - public UnsignedIntegerFourBytes[] getCurrentInstanceIds() { - synchronized (stateMachines) { - UnsignedIntegerFourBytes[] ids = new UnsignedIntegerFourBytes[stateMachines.size()]; - int i = 0; - for (Long id : stateMachines.keySet()) { - ids[i] = new UnsignedIntegerFourBytes(id); - i++; - } - return ids; - } - } - - protected AVTransportStateMachine findStateMachine(UnsignedIntegerFourBytes instanceId) throws AVTransportException { - return findStateMachine(instanceId, true); - } - - protected AVTransportStateMachine findStateMachine(UnsignedIntegerFourBytes instanceId, boolean createDefaultTransport) throws AVTransportException { - synchronized (stateMachines) { - long id = instanceId.getValue(); - AVTransportStateMachine stateMachine = stateMachines.get(id); - if (stateMachine == null && id == 0 && createDefaultTransport) { - log.fine("Creating default transport instance with ID '0'"); - stateMachine = createStateMachine(instanceId); - stateMachines.put(id, stateMachine); - } else if (stateMachine == null) { - throw new AVTransportException(AVTransportErrorCode.INVALID_INSTANCE_ID); - } - log.fine("Found transport control with ID '" + id + "'"); - return stateMachine; - } - } - - protected AVTransportStateMachine createStateMachine(UnsignedIntegerFourBytes instanceId) { - // Create a proxy that delegates all calls to the right state implementation, working on the T state - return StateMachineBuilder.build( - stateMachineDefinition, - initialState, - new Class[]{transportClass}, - new Object[]{createTransport(instanceId, getLastChange())} - ); - } - - protected AVTransport createTransport(UnsignedIntegerFourBytes instanceId, LastChange lastChange) { - return new AVTransport(instanceId, lastChange, StorageMedium.NETWORK); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/AVTransportStateMachine.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/AVTransportStateMachine.java deleted file mode 100644 index c7ea2ad..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/AVTransportStateMachine.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.impl; - -import org.fourthline.cling.support.avtransport.impl.state.AbstractState; -import org.fourthline.cling.support.model.SeekMode; -import org.seamless.statemachine.StateMachine; - -import java.net.URI; - -public interface AVTransportStateMachine extends StateMachine { - - public abstract void setTransportURI(URI uri, String uriMetaData); - public abstract void setNextTransportURI(URI uri, String uriMetaData); - public abstract void stop(); - public abstract void play(String speed); - public abstract void pause(); - public abstract void record(); - public abstract void seek(SeekMode unit, String target); - public abstract void next(); - public abstract void previous(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/AbstractState.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/AbstractState.java deleted file mode 100644 index 55129ed..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/AbstractState.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.impl.state; - -import org.fourthline.cling.support.model.AVTransport; -import org.fourthline.cling.support.model.TransportAction; - -/** - * - */ -public abstract class AbstractState { - - private T transport; - - public AbstractState(T transport) { - this.transport = transport; - } - - public T getTransport() { - return transport; - } - - public abstract TransportAction[] getCurrentTransportActions(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/NoMediaPresent.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/NoMediaPresent.java deleted file mode 100644 index fd7014c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/NoMediaPresent.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.impl.state; - -import org.fourthline.cling.support.avtransport.lastchange.AVTransportVariable; -import org.fourthline.cling.support.model.AVTransport; -import org.fourthline.cling.support.model.TransportAction; -import org.fourthline.cling.support.model.TransportInfo; -import org.fourthline.cling.support.model.TransportState; - -import java.net.URI; -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public abstract class NoMediaPresent extends AbstractState { - - final private static Logger log = Logger.getLogger(Stopped.class.getName()); - - public NoMediaPresent(T transport) { - super(transport); - } - - public void onEntry() { - log.fine("Setting transport state to NO_MEDIA_PRESENT"); - getTransport().setTransportInfo( - new TransportInfo( - TransportState.NO_MEDIA_PRESENT, - getTransport().getTransportInfo().getCurrentTransportStatus(), - getTransport().getTransportInfo().getCurrentSpeed() - ) - ); - getTransport().getLastChange().setEventedValue( - getTransport().getInstanceId(), - new AVTransportVariable.TransportState(TransportState.NO_MEDIA_PRESENT), - new AVTransportVariable.CurrentTransportActions(getCurrentTransportActions()) - ); - } - - public abstract Class setTransportURI(URI uri, String metaData); - - public TransportAction[] getCurrentTransportActions() { - return new TransportAction[] { - TransportAction.Stop - }; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/PausedPlay.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/PausedPlay.java deleted file mode 100644 index 8d0836c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/PausedPlay.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.impl.state; - -import java.net.URI; -import java.util.logging.Logger; - -import org.fourthline.cling.support.avtransport.lastchange.AVTransportVariable; -import org.fourthline.cling.support.model.AVTransport; -import org.fourthline.cling.support.model.TransportAction; -import org.fourthline.cling.support.model.TransportInfo; -import org.fourthline.cling.support.model.TransportState; - -/** - * @author Christian Bauer - */ -public abstract class PausedPlay extends AbstractState -{ - - final private static Logger log = Logger.getLogger(PausedPlay.class.getName()); - - public PausedPlay(T transport) { - super(transport); - } - - public void onEntry() { - log.fine("Setting transport state to PAUSED_PLAYBACK"); - getTransport().setTransportInfo( - new TransportInfo( - TransportState.PAUSED_PLAYBACK, - getTransport().getTransportInfo().getCurrentTransportStatus(), - getTransport().getTransportInfo().getCurrentSpeed() - ) - ); - getTransport().getLastChange().setEventedValue( - getTransport().getInstanceId(), - new AVTransportVariable.TransportState(TransportState.PAUSED_PLAYBACK), - new AVTransportVariable.CurrentTransportActions(getCurrentTransportActions()) - ); - } - - public abstract Class> setTransportURI(URI uri, String metaData); - public abstract Class> stop(); - public abstract Class> play(String speed); - - public TransportAction[] getCurrentTransportActions() { - return new TransportAction[] { - TransportAction.Stop, - TransportAction.Play - }; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/Playing.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/Playing.java deleted file mode 100644 index 2b4bda4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/Playing.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.impl.state; - -import org.fourthline.cling.support.avtransport.lastchange.AVTransportVariable; -import org.fourthline.cling.support.model.AVTransport; -import org.fourthline.cling.support.model.SeekMode; -import org.fourthline.cling.support.model.TransportAction; -import org.fourthline.cling.support.model.TransportInfo; -import org.fourthline.cling.support.model.TransportState; - -import java.net.URI; -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public abstract class Playing extends AbstractState { - - final private static Logger log = Logger.getLogger(Playing.class.getName()); - - public Playing(T transport) { - super(transport); - } - - public void onEntry() { - log.fine("Setting transport state to PLAYING"); - getTransport().setTransportInfo( - new TransportInfo( - TransportState.PLAYING, - getTransport().getTransportInfo().getCurrentTransportStatus(), - getTransport().getTransportInfo().getCurrentSpeed() - ) - ); - getTransport().getLastChange().setEventedValue( - getTransport().getInstanceId(), - new AVTransportVariable.TransportState(TransportState.PLAYING), - new AVTransportVariable.CurrentTransportActions(getCurrentTransportActions()) - ); - } - - public abstract Class> setTransportURI(URI uri, String metaData); - public abstract Class> stop(); - public abstract Class> play(String speed); - public abstract Class> pause(); - public abstract Class> next(); - public abstract Class> previous(); - public abstract Class> seek(SeekMode unit, String target); - - public TransportAction[] getCurrentTransportActions() { - return new TransportAction[] { - TransportAction.Stop, - TransportAction.Play, - TransportAction.Pause, - TransportAction.Next, - TransportAction.Previous, - TransportAction.Seek - }; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/Stopped.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/Stopped.java deleted file mode 100644 index 0b5bd95..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/impl/state/Stopped.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.impl.state; - -import org.fourthline.cling.support.avtransport.lastchange.AVTransportVariable; -import org.fourthline.cling.support.model.AVTransport; -import org.fourthline.cling.support.model.SeekMode; -import org.fourthline.cling.support.model.TransportAction; -import org.fourthline.cling.support.model.TransportInfo; -import org.fourthline.cling.support.model.TransportState; - -import java.net.URI; -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public abstract class Stopped extends AbstractState { - - final private static Logger log = Logger.getLogger(Stopped.class.getName()); - - public Stopped(T transport) { - super(transport); - } - - public void onEntry() { - log.fine("Setting transport state to STOPPED"); - getTransport().setTransportInfo( - new TransportInfo( - TransportState.STOPPED, - getTransport().getTransportInfo().getCurrentTransportStatus(), - getTransport().getTransportInfo().getCurrentSpeed() - ) - ); - getTransport().getLastChange().setEventedValue( - getTransport().getInstanceId(), - new AVTransportVariable.TransportState(TransportState.STOPPED), - new AVTransportVariable.CurrentTransportActions(getCurrentTransportActions()) - ); - } - - public abstract Class> setTransportURI(URI uri, String metaData); - public abstract Class> stop(); - public abstract Class> play(String speed); - public abstract Class> next(); - public abstract Class> previous(); - public abstract Class> seek(SeekMode unit, String target); - - public TransportAction[] getCurrentTransportActions() { - return new TransportAction[] { - TransportAction.Stop, - TransportAction.Play, - TransportAction.Next, - TransportAction.Previous, - TransportAction.Seek - }; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/lastchange/AVTransportLastChangeParser.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/lastchange/AVTransportLastChangeParser.java deleted file mode 100644 index f197f17..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/lastchange/AVTransportLastChangeParser.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.lastchange; - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.support.lastchange.EventedValue; -import org.fourthline.cling.support.lastchange.LastChangeParser; - -import javax.xml.transform.Source; -import javax.xml.transform.stream.StreamSource; -import java.util.Set; - -/** - * @author Christian Bauer - */ -public class AVTransportLastChangeParser extends LastChangeParser { - - public static final String NAMESPACE_URI = "urn:schemas-upnp-org:metadata-1-0/AVT/"; - public static final String SCHEMA_RESOURCE = "org/fourthline/cling/support/avtransport/metadata-1.01-avt.xsd"; - - @Override - protected String getNamespace() { - return NAMESPACE_URI; - } - - @Override - protected Source[] getSchemaSources() { - // TODO: Android 2.2 has a broken SchemaFactory, we can't validate - // http://code.google.com/p/android/issues/detail?id=9491&q=schemafactory&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars - if (!ModelUtil.ANDROID_RUNTIME) { - return new Source[]{new StreamSource( - Thread.currentThread().getContextClassLoader().getResourceAsStream(SCHEMA_RESOURCE) - )}; - } - return null; - } - - @Override - protected Set> getEventedVariables() { - return AVTransportVariable.ALL; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/lastchange/AVTransportVariable.java b/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/lastchange/AVTransportVariable.java deleted file mode 100644 index dc94324..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/avtransport/lastchange/AVTransportVariable.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.avtransport.lastchange; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.PlayMode; -import org.fourthline.cling.support.model.RecordQualityMode; -import org.fourthline.cling.support.model.TransportAction; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.lastchange.EventedValue; -import org.fourthline.cling.support.lastchange.EventedValueEnum; -import org.fourthline.cling.support.lastchange.EventedValueEnumArray; -import org.fourthline.cling.support.lastchange.EventedValueString; -import org.fourthline.cling.support.lastchange.EventedValueURI; -import org.fourthline.cling.support.lastchange.EventedValueUnsignedIntegerFourBytes; - -import java.net.URI; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * @author Christian Bauer - */ -public class AVTransportVariable { - - public static Set> ALL = new HashSet>() {{ - add(TransportState.class); - add(TransportStatus.class); - add(RecordStorageMedium.class); - add(PossibleRecordStorageMedia.class); - add(PossiblePlaybackStorageMedia.class); - add(CurrentPlayMode.class); - add(TransportPlaySpeed.class); - add(RecordMediumWriteStatus.class); - add(CurrentRecordQualityMode.class); - add(PossibleRecordQualityModes.class); - add(NumberOfTracks.class); - add(CurrentTrack.class); - add(CurrentTrackDuration.class); - add(CurrentMediaDuration.class); - add(CurrentTrackMetaData.class); - add(CurrentTrackURI.class); - add(AVTransportURI.class); - add(NextAVTransportURI.class); - add(AVTransportURIMetaData.class); - add(NextAVTransportURIMetaData.class); - add(CurrentTransportActions.class); - add(RelativeTimePosition.class); - add(AbsoluteTimePosition.class); - add(RelativeCounterPosition.class); - add(AbsoluteCounterPosition.class); - }}; - - public static class TransportState extends EventedValueEnum { - public TransportState(org.fourthline.cling.support.model.TransportState avTransportState) { - super(avTransportState); - } - - public TransportState(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected org.fourthline.cling.support.model.TransportState enumValueOf(String s) { - return org.fourthline.cling.support.model.TransportState.valueOf(s); - } - } - - public static class TransportStatus extends EventedValueEnum { - public TransportStatus(org.fourthline.cling.support.model.TransportStatus transportStatus) { - super(transportStatus); - } - - public TransportStatus(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected org.fourthline.cling.support.model.TransportStatus enumValueOf(String s) { - return org.fourthline.cling.support.model.TransportStatus.valueOf(s); - } - } - - public static class RecordStorageMedium extends EventedValueEnum { - - public RecordStorageMedium(StorageMedium storageMedium) { - super(storageMedium); - } - - public RecordStorageMedium(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected StorageMedium enumValueOf(String s) { - return StorageMedium.valueOf(s); - } - } - - public static class PossibleRecordStorageMedia extends EventedValueEnumArray { - public PossibleRecordStorageMedia(StorageMedium[] e) { - super(e); - } - - public PossibleRecordStorageMedia(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected StorageMedium[] enumValueOf(String[] names) { - List list = new ArrayList<>(); - for (String s : names) { - list.add(StorageMedium.valueOf(s)); - } - return list.toArray(new StorageMedium[list.size()]); - } - } - - public static class PossiblePlaybackStorageMedia extends PossibleRecordStorageMedia { - public PossiblePlaybackStorageMedia(StorageMedium[] e) { - super(e); - } - - public PossiblePlaybackStorageMedia(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class CurrentPlayMode extends EventedValueEnum { - public CurrentPlayMode(PlayMode playMode) { - super(playMode); - } - - public CurrentPlayMode(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected PlayMode enumValueOf(String s) { - return PlayMode.valueOf(s); - } - } - - public static class TransportPlaySpeed extends EventedValueString { - final static Pattern pattern = Pattern.compile("^-?\\d+(/\\d+)?$", Pattern.CASE_INSENSITIVE); - - public TransportPlaySpeed(String value) { - super(value); - if (!pattern.matcher(value).matches()) { - throw new InvalidValueException("Can't parse TransportPlaySpeed speeds."); - } - } - - public TransportPlaySpeed(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class RecordMediumWriteStatus extends EventedValueEnum { - public RecordMediumWriteStatus(org.fourthline.cling.support.model.RecordMediumWriteStatus recordMediumWriteStatus) { - super(recordMediumWriteStatus); - } - - public RecordMediumWriteStatus(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected org.fourthline.cling.support.model.RecordMediumWriteStatus enumValueOf(String s) { - return org.fourthline.cling.support.model.RecordMediumWriteStatus.valueOf(s); - } - } - - public static class CurrentRecordQualityMode extends EventedValueEnum { - public CurrentRecordQualityMode(RecordQualityMode recordQualityMode) { - super(recordQualityMode); - } - - public CurrentRecordQualityMode(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected RecordQualityMode enumValueOf(String s) { - return RecordQualityMode.valueOf(s); - } - } - - public static class PossibleRecordQualityModes extends EventedValueEnumArray { - public PossibleRecordQualityModes(RecordQualityMode[] e) { - super(e); - } - - public PossibleRecordQualityModes(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected RecordQualityMode[] enumValueOf(String[] names) { - List list = new ArrayList<>(); - for (String s : names) { - list.add(RecordQualityMode.valueOf(s)); - } - return list.toArray(new RecordQualityMode[list.size()]); - } - } - - public static class NumberOfTracks extends EventedValueUnsignedIntegerFourBytes { - public NumberOfTracks(UnsignedIntegerFourBytes value) { - super(value); - } - - public NumberOfTracks(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class CurrentTrack extends EventedValueUnsignedIntegerFourBytes { - public CurrentTrack(UnsignedIntegerFourBytes value) { - super(value); - } - - public CurrentTrack(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class CurrentTrackDuration extends EventedValueString { - public CurrentTrackDuration(String value) { - super(value); - } - - public CurrentTrackDuration(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class CurrentMediaDuration extends EventedValueString { - public CurrentMediaDuration(String value) { - super(value); - } - - public CurrentMediaDuration(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class CurrentTrackMetaData extends EventedValueString { - public CurrentTrackMetaData(String value) { - super(value); - } - - public CurrentTrackMetaData(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class CurrentTrackURI extends EventedValueURI { - public CurrentTrackURI(URI value) { - super(value); - } - - public CurrentTrackURI(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class AVTransportURI extends EventedValueURI { - public AVTransportURI(URI value) { - super(value); - } - - public AVTransportURI(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class NextAVTransportURI extends EventedValueURI { - public NextAVTransportURI(URI value) { - super(value); - } - - public NextAVTransportURI(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class AVTransportURIMetaData extends EventedValueString { - public AVTransportURIMetaData(String value) { - super(value); - } - - public AVTransportURIMetaData(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class NextAVTransportURIMetaData extends EventedValueString { - public NextAVTransportURIMetaData(String value) { - super(value); - } - - public NextAVTransportURIMetaData(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class CurrentTransportActions extends EventedValueEnumArray{ - public CurrentTransportActions(TransportAction[] e) { - super(e); - } - - public CurrentTransportActions(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected TransportAction[] enumValueOf(String[] names) { - if (names == null) return new TransportAction[0]; - List list = new ArrayList<>(); - for (String s : names) { - list.add(TransportAction.valueOf(s)); - } - return list.toArray(new TransportAction[list.size()]); - } - } - - public static class RelativeTimePosition extends EventedValueString { - public RelativeTimePosition(String value) { - super(value); - } - - public RelativeTimePosition(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class AbsoluteTimePosition extends EventedValueString { - public AbsoluteTimePosition(String value) { - super(value); - } - - public AbsoluteTimePosition(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class RelativeCounterPosition extends EventedValueString { - public RelativeCounterPosition(String value) { - super(value); - } - - public RelativeCounterPosition(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class AbsoluteCounterPosition extends EventedValueString { - public AbsoluteCounterPosition(String value) { - super(value); - } - - public AbsoluteCounterPosition(Map.Entry[] attributes) { - super(attributes); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/AbstractPeeringConnectionManagerService.java b/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/AbstractPeeringConnectionManagerService.java deleted file mode 100644 index 371a416..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/AbstractPeeringConnectionManagerService.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.connectionmanager; - -import org.fourthline.cling.binding.annotations.UpnpAction; -import org.fourthline.cling.binding.annotations.UpnpInputArgument; -import org.fourthline.cling.binding.annotations.UpnpOutputArgument; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.ServiceReference; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.model.types.csv.CSV; -import org.fourthline.cling.support.connectionmanager.callback.ConnectionComplete; -import org.fourthline.cling.support.connectionmanager.callback.PrepareForConnection; -import org.fourthline.cling.support.model.ConnectionInfo; -import org.fourthline.cling.support.model.ProtocolInfo; -import org.fourthline.cling.support.model.ProtocolInfos; - -import java.beans.PropertyChangeSupport; -import java.util.logging.Logger; - -/** - * Support for setup and teardown of an arbitrary number of connections with a manager peer. - * - * @author Christian Bauer - * @author Alessio Gaeta - */ -public abstract class AbstractPeeringConnectionManagerService extends ConnectionManagerService { - - final private static Logger log = Logger.getLogger(AbstractPeeringConnectionManagerService.class.getName()); - - protected AbstractPeeringConnectionManagerService(ConnectionInfo... activeConnections) { - super(activeConnections); - } - - protected AbstractPeeringConnectionManagerService(ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo, - ConnectionInfo... activeConnections) { - super(sourceProtocolInfo, sinkProtocolInfo, activeConnections); - } - - protected AbstractPeeringConnectionManagerService(PropertyChangeSupport propertyChangeSupport, - ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo, - ConnectionInfo... activeConnections) { - super(propertyChangeSupport, sourceProtocolInfo, sinkProtocolInfo, activeConnections); - } - - synchronized protected int getNewConnectionId() { - int currentHighestID = -1; - for (Integer key : activeConnections.keySet()) { - if (key > currentHighestID) currentHighestID = key; - } - return ++currentHighestID; - } - - synchronized protected void storeConnection(ConnectionInfo info) { - CSV oldConnectionIDs = getCurrentConnectionIDs(); - activeConnections.put(info.getConnectionID(), info); - log.fine("Connection stored, firing event: " + info.getConnectionID()); - CSV newConnectionIDs = getCurrentConnectionIDs(); - getPropertyChangeSupport().firePropertyChange("CurrentConnectionIDs", oldConnectionIDs, newConnectionIDs); - } - - synchronized protected void removeConnection(int connectionID) { - CSV oldConnectionIDs = getCurrentConnectionIDs(); - activeConnections.remove(connectionID); - log.fine("Connection removed, firing event: " + connectionID); - CSV newConnectionIDs = getCurrentConnectionIDs(); - getPropertyChangeSupport().firePropertyChange("CurrentConnectionIDs", oldConnectionIDs, newConnectionIDs); - } - - @UpnpAction(out = { - @UpnpOutputArgument(name = "ConnectionID", stateVariable = "A_ARG_TYPE_ConnectionID", getterName = "getConnectionID"), - @UpnpOutputArgument(name = "AVTransportID", stateVariable = "A_ARG_TYPE_AVTransportID", getterName = "getAvTransportID"), - @UpnpOutputArgument(name = "RcsID", stateVariable = "A_ARG_TYPE_RcsID", getterName = "getRcsID") - }) - synchronized public ConnectionInfo prepareForConnection( - @UpnpInputArgument(name = "RemoteProtocolInfo", stateVariable = "A_ARG_TYPE_ProtocolInfo") ProtocolInfo remoteProtocolInfo, - @UpnpInputArgument(name = "PeerConnectionManager", stateVariable = "A_ARG_TYPE_ConnectionManager") ServiceReference peerConnectionManager, - @UpnpInputArgument(name = "PeerConnectionID", stateVariable = "A_ARG_TYPE_ConnectionID") int peerConnectionId, - @UpnpInputArgument(name = "Direction", stateVariable = "A_ARG_TYPE_Direction") String direction) - throws ActionException { - - int connectionId = getNewConnectionId(); - - ConnectionInfo.Direction dir; - try { - dir = ConnectionInfo.Direction.valueOf(direction); - } catch (Exception ex) { - throw new ConnectionManagerException(ErrorCode.ARGUMENT_VALUE_INVALID, "Unsupported direction: " + direction); - } - - log.fine("Preparing for connection with local new ID " + connectionId + " and peer connection ID: " + peerConnectionId); - - ConnectionInfo newConnectionInfo = createConnection( - connectionId, - peerConnectionId, - peerConnectionManager, - dir, - remoteProtocolInfo - ); - - storeConnection(newConnectionInfo); - - return newConnectionInfo; - } - - @UpnpAction - synchronized public void connectionComplete(@UpnpInputArgument(name = "ConnectionID", stateVariable = "A_ARG_TYPE_ConnectionID") int connectionID) - throws ActionException { - ConnectionInfo info = getCurrentConnectionInfo(connectionID); - log.fine("Closing connection ID " + connectionID); - closeConnection(info); - removeConnection(connectionID); - } - - /** - * Generate a new local connection identifier, prepare the peer, store connection details. - * - * @return -1 if the {@link #peerFailure(org.fourthline.cling.model.action.ActionInvocation, org.fourthline.cling.model.message.UpnpResponse, String)} - * method had to be called, otherwise the local identifier of the established connection. - */ - synchronized public int createConnectionWithPeer(final ServiceReference localServiceReference, - final ControlPoint controlPoint, - final Service peerService, - final ProtocolInfo protInfo, - final ConnectionInfo.Direction direction) { - - // It is important that you synchronize the whole procedure, starting with getNewConnectionID(), - // then preparing the connection on the peer, then storeConnection() - - final int localConnectionID = getNewConnectionId(); - - log.fine("Creating new connection ID " + localConnectionID + " with peer: " + peerService); - final boolean[] failed = new boolean[1]; - new PrepareForConnection( - peerService, - controlPoint, - protInfo, - localServiceReference, - localConnectionID, - direction - ) { - @Override - public void received(ActionInvocation invocation, int peerConnectionID, int rcsID, int avTransportID) { - ConnectionInfo info = new ConnectionInfo( - localConnectionID, - rcsID, - avTransportID, - protInfo, - peerService.getReference(), - peerConnectionID, - direction.getOpposite(), // If I prepared you for output, then I do input - ConnectionInfo.Status.OK - ); - storeConnection(info); - } - - @Override - public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) { - AbstractPeeringConnectionManagerService.this.peerFailure( - invocation, operation, defaultMsg - ); - failed[0] = true; - } - }.run(); // Synchronous execution! We "reserved" a new connection ID earlier! - - return failed[0] ? -1 : localConnectionID; - } - - /** - * Close the connection with the peer, remove the connection details. - */ - synchronized public void closeConnectionWithPeer(ControlPoint controlPoint, - Service peerService, - int connectionID) throws ActionException { - closeConnectionWithPeer(controlPoint, peerService, getCurrentConnectionInfo(connectionID)); - } - - /** - * Close the connection with the peer, remove the connection details. - */ - synchronized public void closeConnectionWithPeer(final ControlPoint controlPoint, - final Service peerService, - final ConnectionInfo connectionInfo) throws ActionException { - - // It is important that you synchronize the whole procedure - log.fine("Closing connection ID " + connectionInfo.getConnectionID() + " with peer: " + peerService); - new ConnectionComplete( - peerService, - controlPoint, - connectionInfo.getPeerConnectionID() - ) { - - @Override - public void success(ActionInvocation invocation) { - removeConnection(connectionInfo.getConnectionID()); - } - - @Override - public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) { - AbstractPeeringConnectionManagerService.this.peerFailure( - invocation, operation, defaultMsg - ); - } - }.run(); // Synchronous execution! - } - - protected abstract ConnectionInfo createConnection(int connectionID, - int peerConnectionId, ServiceReference peerConnectionManager, - ConnectionInfo.Direction direction, ProtocolInfo protocolInfo) throws ActionException; - - protected abstract void closeConnection(ConnectionInfo connectionInfo); - - /** - * Called when connection creation or closing with a peer failed. - *

- * This is the failure result of an action invocation on the peer's connection - * management service. The execution of the {@link #createConnectionWithPeer(org.fourthline.cling.model.ServiceReference, org.fourthline.cling.controlpoint.ControlPoint, org.fourthline.cling.model.meta.Service, org.fourthline.cling.support.model.ProtocolInfo , org.fourthline.cling.support.model.ConnectionInfo.Direction)} - * and {@link #closeConnectionWithPeer(org.fourthline.cling.controlpoint.ControlPoint, org.fourthline.cling.model.meta.Service, org.fourthline.cling.support.model.ConnectionInfo)} - * methods will block until this method completes handling any failure. - *

- * - * @param invocation The underlying action invocation of the remote connection manager service. - * @param operation The network message response if there was a response, or null. - * @param defaultFailureMessage A user-friendly error message generated from the invocation exception and response. - */ - protected abstract void peerFailure(ActionInvocation invocation, UpnpResponse operation, String defaultFailureMessage); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerErrorCode.java b/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerErrorCode.java deleted file mode 100644 index 199b89a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerErrorCode.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.connectionmanager; - -/** - * - */ -public enum ConnectionManagerErrorCode { - - INCOMPATIBLE_PROTOCOL_INFO(701, "The connection cannot be established because the protocol info parameter is incompatible"), - INCOMPATIBLE_DIRECTIONS(702, "The connection cannot be established because the directions of the involved ConnectionManagers (source/sink) are incompatible"), - INSUFFICIENT_NETWORK_RESOURCES(703, "The connection cannot be established because there are insufficient network resources"), - LOCAL_RESTRICTIONS(704, "The connection cannot be established because of local restrictions in the device"), - ACCESS_DENIED(705, "The connection cannot be established because the client is not permitted."), - INVALID_CONNECTION_REFERENCE(706, "Not a valid connection established by this service"), - NOT_IN_NETWORK(707, "The connection cannot be established because the ConnectionManagers are not part of the same physical network."); - - private int code; - private String description; - - ConnectionManagerErrorCode(int code, String description) { - this.code = code; - this.description = description; - } - - public int getCode() { - return code; - } - - public String getDescription() { - return description; - } - - public static ConnectionManagerErrorCode getByCode(int code) { - for (ConnectionManagerErrorCode errorCode : ConnectionManagerErrorCode.values()) { - if (errorCode.getCode() == code) - return errorCode; - } - return null; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerException.java b/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerException.java deleted file mode 100644 index 0d9887f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.connectionmanager; - -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.types.ErrorCode; - -/** - * - */ -public class ConnectionManagerException extends ActionException { - - public ConnectionManagerException(int errorCode, String message) { - super(errorCode, message); - } - - public ConnectionManagerException(int errorCode, String message, Throwable cause) { - super(errorCode, message, cause); - } - - public ConnectionManagerException(ErrorCode errorCode, String message) { - super(errorCode, message); - } - - public ConnectionManagerException(ErrorCode errorCode) { - super(errorCode); - } - - public ConnectionManagerException(ConnectionManagerErrorCode errorCode, String message) { - super(errorCode.getCode(), errorCode.getDescription() + ". " + message + "."); - } - - public ConnectionManagerException(ConnectionManagerErrorCode errorCode) { - super(errorCode.getCode(), errorCode.getDescription()); - } -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerService.java b/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerService.java deleted file mode 100644 index a99d17a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/ConnectionManagerService.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.connectionmanager; - -import org.fourthline.cling.binding.annotations.UpnpAction; -import org.fourthline.cling.binding.annotations.UpnpInputArgument; -import org.fourthline.cling.binding.annotations.UpnpOutputArgument; -import org.fourthline.cling.binding.annotations.UpnpService; -import org.fourthline.cling.binding.annotations.UpnpServiceId; -import org.fourthline.cling.binding.annotations.UpnpServiceType; -import org.fourthline.cling.binding.annotations.UpnpStateVariable; -import org.fourthline.cling.binding.annotations.UpnpStateVariables; -import org.fourthline.cling.model.ServiceReference; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.model.types.csv.CSV; -import org.fourthline.cling.model.types.csv.CSVUnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.ConnectionInfo; -import org.fourthline.cling.support.model.ProtocolInfo; -import org.fourthline.cling.support.model.ProtocolInfos; - -import java.beans.PropertyChangeSupport; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; - -/** - * Base for connection management, implements the connection ID "0" behavior. - * - * @author Christian Bauer - * @author Alessio Gaeta - */ -@UpnpService( - serviceId = @UpnpServiceId("ConnectionManager"), - serviceType = @UpnpServiceType(value = "ConnectionManager", version = 1), - stringConvertibleTypes = {ProtocolInfo.class, ProtocolInfos.class, ServiceReference.class} -) -@UpnpStateVariables({ - @UpnpStateVariable(name = "SourceProtocolInfo", datatype = "string"), - @UpnpStateVariable(name = "SinkProtocolInfo", datatype = "string"), - @UpnpStateVariable(name = "CurrentConnectionIDs", datatype = "string"), - @UpnpStateVariable(name = "A_ARG_TYPE_ConnectionStatus", allowedValuesEnum = ConnectionInfo.Status.class, sendEvents = false), - @UpnpStateVariable(name = "A_ARG_TYPE_ConnectionManager", datatype = "string", sendEvents = false), - @UpnpStateVariable(name = "A_ARG_TYPE_Direction", allowedValuesEnum = ConnectionInfo.Direction.class, sendEvents = false), - @UpnpStateVariable(name = "A_ARG_TYPE_ProtocolInfo", datatype = "string", sendEvents = false), - @UpnpStateVariable(name = "A_ARG_TYPE_ConnectionID", datatype = "i4", sendEvents = false), - @UpnpStateVariable(name = "A_ARG_TYPE_AVTransportID", datatype = "i4", sendEvents = false), - @UpnpStateVariable(name = "A_ARG_TYPE_RcsID", datatype = "i4", sendEvents = false) -}) -public class ConnectionManagerService { - - final private static Logger log = Logger.getLogger(ConnectionManagerService.class.getName()); - - final protected PropertyChangeSupport propertyChangeSupport; - final protected Map activeConnections = new ConcurrentHashMap(); - final protected ProtocolInfos sourceProtocolInfo; - final protected ProtocolInfos sinkProtocolInfo; - - /** - * Creates a default "active" connection with identifier "0". - */ - public ConnectionManagerService() { - this(new ConnectionInfo()); - } - - /** - * Creates a default "active" connection with identifier "0". - */ - public ConnectionManagerService(ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo) { - this(sourceProtocolInfo, sinkProtocolInfo, new ConnectionInfo()); - } - - public ConnectionManagerService(ConnectionInfo... activeConnections) { - this(null, new ProtocolInfos(), new ProtocolInfos(), activeConnections); - } - - public ConnectionManagerService(ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo, ConnectionInfo... activeConnections) { - this(null, sourceProtocolInfo, sinkProtocolInfo, activeConnections); - } - - public ConnectionManagerService(PropertyChangeSupport propertyChangeSupport, - ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo, - ConnectionInfo... activeConnections) { - this.propertyChangeSupport = - propertyChangeSupport == null - ? new PropertyChangeSupport(this) : propertyChangeSupport; - - this.sourceProtocolInfo = sourceProtocolInfo; - this.sinkProtocolInfo = sinkProtocolInfo; - - for (ConnectionInfo activeConnection : activeConnections) { - this.activeConnections.put(activeConnection.getConnectionID(), activeConnection); - } - } - - public PropertyChangeSupport getPropertyChangeSupport() { - return propertyChangeSupport; - } - - @UpnpAction(out = { - @UpnpOutputArgument(name = "RcsID", getterName = "getRcsID"), - @UpnpOutputArgument(name = "AVTransportID", getterName = "getAvTransportID"), - @UpnpOutputArgument(name = "ProtocolInfo", getterName = "getProtocolInfo"), - @UpnpOutputArgument(name = "PeerConnectionManager", stateVariable = "A_ARG_TYPE_ConnectionManager", getterName = "getPeerConnectionManager"), - @UpnpOutputArgument(name = "PeerConnectionID", stateVariable = "A_ARG_TYPE_ConnectionID", getterName = "getPeerConnectionID"), - @UpnpOutputArgument(name = "Direction", getterName = "getDirection"), - @UpnpOutputArgument(name = "Status", stateVariable = "A_ARG_TYPE_ConnectionStatus", getterName = "getConnectionStatus") - }) - synchronized public ConnectionInfo getCurrentConnectionInfo(@UpnpInputArgument(name = "ConnectionID") int connectionId) - throws ActionException { - log.fine("Getting connection information of connection ID: " + connectionId); - ConnectionInfo info; - if ((info = activeConnections.get(connectionId)) == null) { - throw new ConnectionManagerException( - ConnectionManagerErrorCode.INVALID_CONNECTION_REFERENCE, - "Non-active connection ID: " + connectionId - ); - } - return info; - } - - @UpnpAction(out = { - @UpnpOutputArgument(name = "ConnectionIDs") - }) - synchronized public CSV getCurrentConnectionIDs() { - CSV csv = new CSVUnsignedIntegerFourBytes(); - for (Integer connectionID : activeConnections.keySet()) { - csv.add(new UnsignedIntegerFourBytes(connectionID)); - } - log.fine("Returning current connection IDs: " + csv.size()); - return csv; - } - - @UpnpAction(out = { - @UpnpOutputArgument(name = "Source", stateVariable = "SourceProtocolInfo", getterName = "getSourceProtocolInfo"), - @UpnpOutputArgument(name = "Sink", stateVariable = "SinkProtocolInfo", getterName = "getSinkProtocolInfo") - }) - synchronized public void getProtocolInfo() throws ActionException { - // NOOP - } - - synchronized public ProtocolInfos getSourceProtocolInfo() { - return sourceProtocolInfo; - } - - synchronized public ProtocolInfos getSinkProtocolInfo() { - return sinkProtocolInfo; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/ConnectionComplete.java b/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/ConnectionComplete.java deleted file mode 100644 index d4f812a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/ConnectionComplete.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.connectionmanager.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; - -/** - * @author Christian Bauer - */ -public abstract class ConnectionComplete extends ActionCallback { - - public ConnectionComplete(Service service, int connectionID) { - this(service, null, connectionID); - } - - protected ConnectionComplete(Service service, ControlPoint controlPoint, int connectionID) { - super(new ActionInvocation(service.getAction("ConnectionComplete")), controlPoint); - getActionInvocation().setInput("ConnectionID", connectionID); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/GetCurrentConnectionInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/GetCurrentConnectionInfo.java deleted file mode 100644 index 3624165..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/GetCurrentConnectionInfo.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.connectionmanager.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.ServiceReference; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.support.model.ConnectionInfo; -import org.fourthline.cling.support.model.ProtocolInfo; - -/** - * @author Alessio Gaeta - * @author Christian Bauer - */ -public abstract class GetCurrentConnectionInfo extends ActionCallback { - - public GetCurrentConnectionInfo(Service service, int connectionID) { - this(service, null, connectionID); - } - - protected GetCurrentConnectionInfo(Service service, ControlPoint controlPoint, int connectionID) { - super(new ActionInvocation(service.getAction("GetCurrentConnectionInfo")), controlPoint); - getActionInvocation().setInput("ConnectionID", connectionID); - } - - @Override - public void success(ActionInvocation invocation) { - - try { - ConnectionInfo info = new ConnectionInfo( - (Integer)invocation.getInput("ConnectionID").getValue(), - (Integer)invocation.getOutput("RcsID").getValue(), - (Integer)invocation.getOutput("AVTransportID").getValue(), - new ProtocolInfo(invocation.getOutput("ProtocolInfo").toString()), - new ServiceReference(invocation.getOutput("PeerConnectionManager").toString()), - (Integer)invocation.getOutput("PeerConnectionID").getValue(), - ConnectionInfo.Direction.valueOf(invocation.getOutput("Direction").toString()), - ConnectionInfo.Status.valueOf(invocation.getOutput("Status").toString()) - ); - - received(invocation, info); - - } catch (Exception ex) { - invocation.setFailure( - new ActionException(ErrorCode.ACTION_FAILED, "Can't parse ConnectionInfo response: " + ex, ex) - ); - failure(invocation, null); - } - } - - public abstract void received(ActionInvocation invocation, ConnectionInfo connectionInfo); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/GetProtocolInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/GetProtocolInfo.java deleted file mode 100644 index 940ca86..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/GetProtocolInfo.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.connectionmanager.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.action.ActionArgumentValue; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.support.model.ProtocolInfos; - -/** - * @author Christian Bauer - */ -public abstract class GetProtocolInfo extends ActionCallback { - - public GetProtocolInfo(Service service) { - this(service, null); - } - - protected GetProtocolInfo(Service service, ControlPoint controlPoint) { - super(new ActionInvocation(service.getAction("GetProtocolInfo")), controlPoint); - } - - @Override - public void success(ActionInvocation invocation) { - try { - ActionArgumentValue sink = invocation.getOutput("Sink"); - ActionArgumentValue source = invocation.getOutput("Source"); - - received( - invocation, - sink != null ? new ProtocolInfos(sink.toString()) : null, - source != null ? new ProtocolInfos(source.toString()) : null - ); - - } catch (Exception ex) { - invocation.setFailure( - new ActionException(ErrorCode.ACTION_FAILED, "Can't parse ProtocolInfo response: " + ex, ex) - ); - failure(invocation, null); - } - } - - public abstract void received(ActionInvocation actionInvocation, ProtocolInfos sinkProtocolInfos, ProtocolInfos sourceProtocolInfos); - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/PrepareForConnection.java b/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/PrepareForConnection.java deleted file mode 100644 index f5ae7ac..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/connectionmanager/callback/PrepareForConnection.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.connectionmanager.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.ServiceReference; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.support.model.ConnectionInfo; -import org.fourthline.cling.support.model.ProtocolInfo; - -/** - * @author Alessio Gaeta - * @author Christian Bauer - */ -public abstract class PrepareForConnection extends ActionCallback { - - public PrepareForConnection(Service service, - ProtocolInfo remoteProtocolInfo, ServiceReference peerConnectionManager, - int peerConnectionID, ConnectionInfo.Direction direction) { - this(service, null, remoteProtocolInfo, peerConnectionManager, peerConnectionID, direction); - } - - public PrepareForConnection(Service service, ControlPoint controlPoint, - ProtocolInfo remoteProtocolInfo, ServiceReference peerConnectionManager, - int peerConnectionID, ConnectionInfo.Direction direction) { - super(new ActionInvocation(service.getAction("PrepareForConnection")), controlPoint); - - getActionInvocation().setInput("RemoteProtocolInfo", remoteProtocolInfo.toString()); - getActionInvocation().setInput("PeerConnectionManager", peerConnectionManager.toString()); - getActionInvocation().setInput("PeerConnectionID", peerConnectionID); - getActionInvocation().setInput("Direction", direction.toString()); - } - - @Override - public void success(ActionInvocation invocation) { - received( - invocation, - (Integer)invocation.getOutput("ConnectionID").getValue(), - (Integer)invocation.getOutput("RcsID").getValue(), - (Integer)invocation.getOutput("AVTransportID").getValue() - ); - } - - public abstract void received(ActionInvocation invocation, int connectionID, int rcsID, int avTransportID); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/AbstractContentDirectoryService.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/AbstractContentDirectoryService.java deleted file mode 100644 index 57b41d5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/AbstractContentDirectoryService.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.contentdirectory; - -import org.fourthline.cling.binding.annotations.UpnpAction; -import org.fourthline.cling.binding.annotations.UpnpInputArgument; -import org.fourthline.cling.binding.annotations.UpnpOutputArgument; -import org.fourthline.cling.binding.annotations.UpnpService; -import org.fourthline.cling.binding.annotations.UpnpServiceId; -import org.fourthline.cling.binding.annotations.UpnpServiceType; -import org.fourthline.cling.binding.annotations.UpnpStateVariable; -import org.fourthline.cling.binding.annotations.UpnpStateVariables; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.model.types.csv.CSV; -import org.fourthline.cling.model.types.csv.CSVString; -import org.fourthline.cling.support.model.BrowseFlag; -import org.fourthline.cling.support.model.BrowseResult; -import org.fourthline.cling.support.model.DIDLContent; -import org.fourthline.cling.support.model.SortCriterion; - -import java.beans.PropertyChangeSupport; -import java.util.ArrayList; -import java.util.List; - -/** - * Simple ContentDirectory service skeleton. - *

- * Only state variables and actions required by ContentDirectory:1 - * (not the optional ones) are implemented. - *

- * - * @author Alessio Gaeta - * @author Christian Bauer - */ - -@UpnpService( - serviceId = @UpnpServiceId("ContentDirectory"), - serviceType = @UpnpServiceType(value = "ContentDirectory", version = 1) -) - -@UpnpStateVariables({ - @UpnpStateVariable( - name = "A_ARG_TYPE_ObjectID", - sendEvents = false, - datatype = "string"), - @UpnpStateVariable( - name = "A_ARG_TYPE_Result", - sendEvents = false, - datatype = "string"), - @UpnpStateVariable( - name = "A_ARG_TYPE_BrowseFlag", - sendEvents = false, - datatype = "string", - allowedValuesEnum = BrowseFlag.class), - @UpnpStateVariable( - name = "A_ARG_TYPE_Filter", - sendEvents = false, - datatype = "string"), - @UpnpStateVariable( - name = "A_ARG_TYPE_SortCriteria", - sendEvents = false, - datatype = "string"), - @UpnpStateVariable( - name = "A_ARG_TYPE_Index", - sendEvents = false, - datatype = "ui4"), - @UpnpStateVariable( - name = "A_ARG_TYPE_Count", - sendEvents = false, - datatype = "ui4"), - @UpnpStateVariable( - name = "A_ARG_TYPE_UpdateID", - sendEvents = false, - datatype = "ui4"), - @UpnpStateVariable( - name = "A_ARG_TYPE_URI", - sendEvents = false, - datatype = "uri"), - @UpnpStateVariable( - name = "A_ARG_TYPE_SearchCriteria", - sendEvents = false, - datatype = "string") - }) -public abstract class AbstractContentDirectoryService { - - public static final String CAPS_WILDCARD = "*"; - - @UpnpStateVariable(sendEvents = false) - final private CSV searchCapabilities; - - @UpnpStateVariable(sendEvents = false) - final private CSV sortCapabilities; - - @UpnpStateVariable( - sendEvents = true, - defaultValue = "0", - eventMaximumRateMilliseconds = 200 - ) - private UnsignedIntegerFourBytes systemUpdateID = new UnsignedIntegerFourBytes(0); - - final protected PropertyChangeSupport propertyChangeSupport; - - protected AbstractContentDirectoryService() { - this(new ArrayList(), new ArrayList(), null); - } - - protected AbstractContentDirectoryService(List searchCapabilities, List sortCapabilities) { - this(searchCapabilities, sortCapabilities, null); - } - - protected AbstractContentDirectoryService(List searchCapabilities, List sortCapabilities, - PropertyChangeSupport propertyChangeSupport) { - this.propertyChangeSupport = propertyChangeSupport != null ? propertyChangeSupport : new PropertyChangeSupport(this); - this.searchCapabilities = new CSVString(); - this.searchCapabilities.addAll(searchCapabilities); - this.sortCapabilities = new CSVString(); - this.sortCapabilities.addAll(sortCapabilities); - } - - @UpnpAction(out = @UpnpOutputArgument(name = "SearchCaps")) - public CSV getSearchCapabilities() { - return searchCapabilities; - } - - @UpnpAction(out = @UpnpOutputArgument(name = "SortCaps")) - public CSV getSortCapabilities() { - return sortCapabilities; - } - - @UpnpAction(out = @UpnpOutputArgument(name = "Id")) - synchronized public UnsignedIntegerFourBytes getSystemUpdateID() { - return systemUpdateID; - } - - public PropertyChangeSupport getPropertyChangeSupport() { - return propertyChangeSupport; - } - - /** - * Call this method after making changes to your content directory. - *

- * This will notify clients that their view of the content directory is potentially - * outdated and has to be refreshed. - *

- */ - synchronized protected void changeSystemUpdateID() { - Long oldUpdateID = getSystemUpdateID().getValue(); - systemUpdateID.increment(true); - getPropertyChangeSupport().firePropertyChange( - "SystemUpdateID", - oldUpdateID, - getSystemUpdateID().getValue() - ); - } - - @UpnpAction(out = { - @UpnpOutputArgument(name = "Result", - stateVariable = "A_ARG_TYPE_Result", - getterName = "getResult"), - @UpnpOutputArgument(name = "NumberReturned", - stateVariable = "A_ARG_TYPE_Count", - getterName = "getCount"), - @UpnpOutputArgument(name = "TotalMatches", - stateVariable = "A_ARG_TYPE_Count", - getterName = "getTotalMatches"), - @UpnpOutputArgument(name = "UpdateID", - stateVariable = "A_ARG_TYPE_UpdateID", - getterName = "getContainerUpdateID") - }) - public BrowseResult browse( - @UpnpInputArgument(name = "ObjectID", aliases = "ContainerID") String objectId, - @UpnpInputArgument(name = "BrowseFlag") String browseFlag, - @UpnpInputArgument(name = "Filter") String filter, - @UpnpInputArgument(name = "StartingIndex", stateVariable = "A_ARG_TYPE_Index") UnsignedIntegerFourBytes firstResult, - @UpnpInputArgument(name = "RequestedCount", stateVariable = "A_ARG_TYPE_Count") UnsignedIntegerFourBytes maxResults, - @UpnpInputArgument(name = "SortCriteria") String orderBy) - throws ContentDirectoryException { - - SortCriterion[] orderByCriteria; - try { - orderByCriteria = SortCriterion.valueOf(orderBy); - } catch (Exception ex) { - throw new ContentDirectoryException(ContentDirectoryErrorCode.UNSUPPORTED_SORT_CRITERIA, ex.toString()); - } - - try { - return browse( - objectId, - BrowseFlag.valueOrNullOf(browseFlag), - filter, - firstResult.getValue(), maxResults.getValue(), - orderByCriteria - ); - } catch (ContentDirectoryException ex) { - throw ex; - } catch (Exception ex) { - throw new ContentDirectoryException(ErrorCode.ACTION_FAILED, ex.toString()); - } - } - - /** - * Implement this method to implement browsing of your content. - *

- * This is a required action defined by ContentDirectory:1. - *

- *

- * You should wrap any exception into a {@link ContentDirectoryException}, so a propery - * error message can be returned to control points. - *

- */ - public abstract BrowseResult browse(String objectID, BrowseFlag browseFlag, - String filter, - long firstResult, long maxResults, - SortCriterion[] orderby) throws ContentDirectoryException; - - - @UpnpAction(out = { - @UpnpOutputArgument(name = "Result", - stateVariable = "A_ARG_TYPE_Result", - getterName = "getResult"), - @UpnpOutputArgument(name = "NumberReturned", - stateVariable = "A_ARG_TYPE_Count", - getterName = "getCount"), - @UpnpOutputArgument(name = "TotalMatches", - stateVariable = "A_ARG_TYPE_Count", - getterName = "getTotalMatches"), - @UpnpOutputArgument(name = "UpdateID", - stateVariable = "A_ARG_TYPE_UpdateID", - getterName = "getContainerUpdateID") - }) - public BrowseResult search( - @UpnpInputArgument(name = "ContainerID", stateVariable = "A_ARG_TYPE_ObjectID") String containerId, - @UpnpInputArgument(name = "SearchCriteria") String searchCriteria, - @UpnpInputArgument(name = "Filter") String filter, - @UpnpInputArgument(name = "StartingIndex", stateVariable = "A_ARG_TYPE_Index") UnsignedIntegerFourBytes firstResult, - @UpnpInputArgument(name = "RequestedCount", stateVariable = "A_ARG_TYPE_Count") UnsignedIntegerFourBytes maxResults, - @UpnpInputArgument(name = "SortCriteria") String orderBy) - throws ContentDirectoryException { - - SortCriterion[] orderByCriteria; - try { - orderByCriteria = SortCriterion.valueOf(orderBy); - } catch (Exception ex) { - throw new ContentDirectoryException(ContentDirectoryErrorCode.UNSUPPORTED_SORT_CRITERIA, ex.toString()); - } - - try { - return search( - containerId, - searchCriteria, - filter, - firstResult.getValue(), maxResults.getValue(), - orderByCriteria - ); - } catch (ContentDirectoryException ex) { - throw ex; - } catch (Exception ex) { - throw new ContentDirectoryException(ErrorCode.ACTION_FAILED, ex.toString()); - } - } - - /** - * Override this method to implement searching of your content. - *

- * The default implementation returns an empty result. - *

- */ - public BrowseResult search(String containerId, String searchCriteria, String filter, - long firstResult, long maxResults, SortCriterion[] orderBy) throws ContentDirectoryException { - - try { - return new BrowseResult(new DIDLParser().generate(new DIDLContent()), 0, 0); - } catch (Exception ex) { - throw new ContentDirectoryException(ErrorCode.ACTION_FAILED, ex.toString()); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ContentDirectoryErrorCode.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ContentDirectoryErrorCode.java deleted file mode 100644 index f48e00b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ContentDirectoryErrorCode.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory; - -/** - * @author Alessio Gaeta - */ -public enum ContentDirectoryErrorCode { - - NO_SUCH_OBJECT(701, "The specified ObjectID is invalid"), - UNSUPPORTED_SORT_CRITERIA(709, "Unsupported or invalid sort criteria"), - CANNOT_PROCESS(720, "Cannot process the request"); - - private int code; - private String description; - - ContentDirectoryErrorCode(int code, String description) { - this.code = code; - this.description = description; - } - - public int getCode() { - return code; - } - - public String getDescription() { - return description; - } - - public static ContentDirectoryErrorCode getByCode(int code) { - for (ContentDirectoryErrorCode errorCode : values()) { - if (errorCode.getCode() == code) - return errorCode; - } - return null; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ContentDirectoryException.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ContentDirectoryException.java deleted file mode 100644 index 785fb20..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ContentDirectoryException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory; - -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.types.ErrorCode; - -/** - * @author Alessio Gaeta - */ -public class ContentDirectoryException extends ActionException { - - public ContentDirectoryException(int errorCode, String message) { - super(errorCode, message); - } - - public ContentDirectoryException(int errorCode, String message, - Throwable cause) { - super(errorCode, message, cause); - } - - public ContentDirectoryException(ErrorCode errorCode, String message) { - super(errorCode, message); - } - - public ContentDirectoryException(ErrorCode errorCode) { - super(errorCode); - } - - public ContentDirectoryException(ContentDirectoryErrorCode errorCode, String message) { - super(errorCode.getCode(), errorCode.getDescription() + ". " + message + "."); - } - - public ContentDirectoryException(ContentDirectoryErrorCode errorCode) { - super(errorCode.getCode(), errorCode.getDescription()); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/DIDLParser.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/DIDLParser.java deleted file mode 100644 index 83c7876..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/DIDLParser.java +++ /dev/null @@ -1,1082 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory; - -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.support.model.DIDLAttribute; -import org.fourthline.cling.support.model.DIDLContent; -import org.fourthline.cling.support.model.DIDLObject; -import org.fourthline.cling.support.model.DescMeta; -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.PersonWithRole; -import org.fourthline.cling.support.model.ProtocolInfo; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.model.WriteStatus; -import org.fourthline.cling.support.model.container.Container; -import org.fourthline.cling.support.model.item.Item; -import org.seamless.util.io.IO; -import org.seamless.util.Exceptions; -import org.seamless.xml.SAXParser; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import java.io.InputStream; -import java.io.StringReader; -import java.io.StringWriter; -import java.net.URI; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static org.fourthline.cling.model.XMLUtil.appendNewElement; -import static org.fourthline.cling.model.XMLUtil.appendNewElementIfNotNull; - -/** - * DIDL parser based on SAX for reading and DOM for writing. - *

- * This parser requires Android platform level 8 (2.2). - *

- *

- * Override the {@link #createDescMetaHandler(org.fourthline.cling.support.model.DescMeta, org.seamless.xml.SAXParser.Handler)} - * method to read vendor extension content of {@code } elements. You then should also override the - * {@link #populateDescMetadata(org.w3c.dom.Element, org.fourthline.cling.support.model.DescMeta)} method for writing. - *

- *

- * Override the {@link #createItemHandler(org.fourthline.cling.support.model.item.Item, org.seamless.xml.SAXParser.Handler)} - * etc. methods to register custom handlers for vendor-specific elements and attributes within items, containers, - * and so on. - *

- * - * @author Christian Bauer - * @author Mario Franco - */ -public class DIDLParser extends SAXParser { - - final private static Logger log = Logger.getLogger(DIDLParser.class.getName()); - - public static final String UNKNOWN_TITLE = "Unknown Title"; - - /** - * Uses the current thread's context classloader to read and unmarshall the given resource. - * - * @param resource The resource on the classpath. - * @return The unmarshalled DIDL content model. - * @throws Exception - */ - public DIDLContent parseResource(String resource) throws Exception { - InputStream is = null; - try { - is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource); - return parse(IO.readLines(is)); - } finally { - if (is != null) is.close(); - } - } - - /** - * Reads and unmarshalls an XML representation into a DIDL content model. - * - * @param xml The XML representation. - * @return A DIDL content model. - * @throws Exception - */ - public DIDLContent parse(String xml) throws Exception { - - if (xml == null || xml.length() == 0) { - throw new RuntimeException("Null or empty XML"); - } - - DIDLContent content = new DIDLContent(); - createRootHandler(content, this); - - log.fine("Parsing DIDL XML content"); - parse(new InputSource(new StringReader(xml))); - return content; - } - - protected RootHandler createRootHandler(DIDLContent instance, SAXParser parser) { - return new RootHandler(instance, parser); - } - - protected ContainerHandler createContainerHandler(Container instance, Handler parent) { - return new ContainerHandler(instance, parent); - } - - protected ItemHandler createItemHandler(Item instance, Handler parent) { - return new ItemHandler(instance, parent); - } - - protected ResHandler createResHandler(Res instance, Handler parent) { - return new ResHandler(instance, parent); - } - - protected DescMetaHandler createDescMetaHandler(DescMeta instance, Handler parent) { - return new DescMetaHandler(instance, parent); - } - - - protected Container createContainer(Attributes attributes) { - Container container = new Container(); - - container.setId(attributes.getValue("id")); - container.setParentID(attributes.getValue("parentID")); - - if ((attributes.getValue("childCount") != null)) - container.setChildCount(Integer.valueOf(attributes.getValue("childCount"))); - - try { - Boolean value = (Boolean) Datatype.Builtin.BOOLEAN.getDatatype().valueOf( - attributes.getValue("restricted") - ); - if (value != null) - container.setRestricted(value); - - value = (Boolean) Datatype.Builtin.BOOLEAN.getDatatype().valueOf( - attributes.getValue("searchable") - ); - if (value != null) - container.setSearchable(value); - } catch (Exception ex) { - // Ignore - } - - return container; - } - - protected Item createItem(Attributes attributes) { - Item item = new Item(); - - item.setId(attributes.getValue("id")); - item.setParentID(attributes.getValue("parentID")); - - try { - Boolean value = (Boolean)Datatype.Builtin.BOOLEAN.getDatatype().valueOf( - attributes.getValue("restricted") - ); - if (value != null) - item.setRestricted(value); - - } catch (Exception ex) { - // Ignore - } - - if ((attributes.getValue("refID") != null)) - item.setRefID(attributes.getValue("refID")); - - return item; - } - - protected Res createResource(Attributes attributes) { - Res res = new Res(); - - if (attributes.getValue("importUri") != null) - res.setImportUri(URI.create(attributes.getValue("importUri"))); - - try { - res.setProtocolInfo( - new ProtocolInfo(attributes.getValue("protocolInfo")) - ); - } catch (InvalidValueException ex) { - log.warning("In DIDL content, invalid resource protocol info: " + Exceptions.unwrap(ex)); - return null; - } - - if (attributes.getValue("size") != null) - res.setSize(toLongOrNull(attributes.getValue("size"))); - - if (attributes.getValue("duration") != null) - res.setDuration(attributes.getValue("duration")); - - if (attributes.getValue("bitrate") != null) - res.setBitrate(toLongOrNull(attributes.getValue("bitrate"))); - - if (attributes.getValue("sampleFrequency") != null) - res.setSampleFrequency(toLongOrNull(attributes.getValue("sampleFrequency"))); - - if (attributes.getValue("bitsPerSample") != null) - res.setBitsPerSample(toLongOrNull(attributes.getValue("bitsPerSample"))); - - if (attributes.getValue("nrAudioChannels") != null) - res.setNrAudioChannels(toLongOrNull(attributes.getValue("nrAudioChannels"))); - - if (attributes.getValue("colorDepth") != null) - res.setColorDepth(toLongOrNull(attributes.getValue("colorDepth"))); - - if (attributes.getValue("protection") != null) - res.setProtection(attributes.getValue("protection")); - - if (attributes.getValue("resolution") != null) - res.setResolution(attributes.getValue("resolution")); - - return res; - } - - private Long toLongOrNull(String value) { - try { - return Long.valueOf(value); - } catch (NumberFormatException x) { - return null; - } - } - - protected DescMeta createDescMeta(Attributes attributes) { - DescMeta desc = new DescMeta(); - - desc.setId(attributes.getValue("id")); - - if ((attributes.getValue("type") != null)) - desc.setType(attributes.getValue("type")); - - if ((attributes.getValue("nameSpace") != null)) - desc.setNameSpace(URI.create(attributes.getValue("nameSpace"))); - - return desc; - } - - - /* ############################################################################################# */ - - - /** - * Generates a XML representation of the content model. - *

- * Items inside a container will not be represented in the XML, the containers - * will be rendered flat without children. - *

- * - * @param content The content model. - * @return An XML representation. - * @throws Exception - */ - public String generate(DIDLContent content) throws Exception { - return generate(content, false); - } - - /** - * Generates an XML representation of the content model. - *

- * Optionally, items inside a container will be represented in the XML, - * the container elements then have nested item elements. Although this - * parser can read such a structure, it is unclear whether other DIDL - * parsers should and actually do support this XML. - *

- * - * @param content The content model. - * @param nestedItems true if nested item elements should be rendered for containers. - * @return An XML representation. - * @throws Exception - */ - public String generate(DIDLContent content, boolean nestedItems) throws Exception { - return documentToString(buildDOM(content, nestedItems), true); - } - - // TODO: Yes, this only runs on Android 2.2 - - protected String documentToString(Document document, boolean omitProlog) throws Exception { - TransformerFactory transFactory = TransformerFactory.newInstance(); - - // Indentation not supported on Android 2.2 - //transFactory.setAttribute("indent-number", 4); - - Transformer transformer = transFactory.newTransformer(); - - if (omitProlog) { - // TODO: UPNP VIOLATION: Terratec Noxon Webradio fails when DIDL content has a prolog - // No XML prolog! This is allowed because it is UTF-8 encoded and required - // because broken devices will stumble on SOAP messages that contain (even - // encoded) XML prologs within a message body. - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - } - - // Again, Android 2.2 fails hard if you try this. - //transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - - StringWriter out = new StringWriter(); - transformer.transform(new DOMSource(document), new StreamResult(out)); - return out.toString(); - } - - protected Document buildDOM(DIDLContent content, boolean nestedItems) throws Exception { - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - - Document d = factory.newDocumentBuilder().newDocument(); - - generateRoot(content, d, nestedItems); - - return d; - } - - protected void generateRoot(DIDLContent content, Document descriptor, boolean nestedItems) { - Element rootElement = descriptor.createElementNS(DIDLContent.NAMESPACE_URI, "DIDL-Lite"); - descriptor.appendChild(rootElement); - - // rootElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:didl", DIDLContent.NAMESPACE_URI); - rootElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:upnp", DIDLObject.Property.UPNP.NAMESPACE.URI); - rootElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:dc", DIDLObject.Property.DC.NAMESPACE.URI); - rootElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:sec", DIDLObject.Property.SEC.NAMESPACE.URI); - - for (Container container : content.getContainers()) { - if (container == null) continue; - generateContainer(container, descriptor, rootElement, nestedItems); - } - - for (Item item : content.getItems()) { - if (item == null) continue; - generateItem(item, descriptor, rootElement); - } - - for (DescMeta descMeta : content.getDescMetadata()) { - if (descMeta == null) continue; - generateDescMetadata(descMeta, descriptor, rootElement); - } - } - - protected void generateContainer(Container container, Document descriptor, Element parent, boolean nestedItems) { - - if (container.getClazz() == null) { - throw new RuntimeException("Missing 'upnp:class' element for container: " + container.getId()); - } - - Element containerElement = appendNewElement(descriptor, parent, "container"); - - if (container.getId() == null) - throw new NullPointerException("Missing id on container: " + container); - containerElement.setAttribute("id", container.getId()); - - if (container.getParentID() == null) - throw new NullPointerException("Missing parent id on container: " + container); - containerElement.setAttribute("parentID", container.getParentID()); - - if (container.getChildCount() != null) { - containerElement.setAttribute("childCount", Integer.toString(container.getChildCount())); - } - - containerElement.setAttribute("restricted", booleanToInt(container.isRestricted())); - containerElement.setAttribute("searchable", booleanToInt(container.isSearchable())); - - String title = container.getTitle(); - if (title == null) { - log.warning("Missing 'dc:title' element for container: " + container.getId()); - title = UNKNOWN_TITLE; - } - - appendNewElementIfNotNull( - descriptor, - containerElement, - "dc:title", - title, - DIDLObject.Property.DC.NAMESPACE.URI - ); - - appendNewElementIfNotNull( - descriptor, - containerElement, - "dc:creator", - container.getCreator(), - DIDLObject.Property.DC.NAMESPACE.URI - ); - - appendNewElementIfNotNull( - descriptor, - containerElement, - "upnp:writeStatus", - container.getWriteStatus(), - DIDLObject.Property.UPNP.NAMESPACE.URI - ); - - appendClass(descriptor, containerElement, container.getClazz(), "upnp:class", false); - - for (DIDLObject.Class searchClass : container.getSearchClasses()) { - appendClass(descriptor, containerElement, searchClass, "upnp:searchClass", true); - } - - for (DIDLObject.Class createClass : container.getCreateClasses()) { - appendClass(descriptor, containerElement, createClass, "upnp:createClass", true); - } - - appendProperties(descriptor, containerElement, container, "upnp", DIDLObject.Property.UPNP.NAMESPACE.class, DIDLObject.Property.UPNP.NAMESPACE.URI); - appendProperties(descriptor, containerElement, container, "dc", DIDLObject.Property.DC.NAMESPACE.class, DIDLObject.Property.DC.NAMESPACE.URI); - - if (nestedItems) { - for (Item item : container.getItems()) { - if (item == null) continue; - generateItem(item, descriptor, containerElement); - } - } - - for (Res resource : container.getResources()) { - if (resource == null) continue; - generateResource(resource, descriptor, containerElement); - } - - for (DescMeta descMeta : container.getDescMetadata()) { - if (descMeta == null) continue; - generateDescMetadata(descMeta, descriptor, containerElement); - } - } - - protected void generateItem(Item item, Document descriptor, Element parent) { - - if (item.getClazz() == null) { - throw new RuntimeException("Missing 'upnp:class' element for item: " + item.getId()); - } - - Element itemElement = appendNewElement(descriptor, parent, "item"); - - if (item.getId() == null) - throw new NullPointerException("Missing id on item: " + item); - itemElement.setAttribute("id", item.getId()); - - if (item.getParentID() == null) - throw new NullPointerException("Missing parent id on item: " + item); - itemElement.setAttribute("parentID", item.getParentID()); - - if (item.getRefID() != null) - itemElement.setAttribute("refID", item.getRefID()); - itemElement.setAttribute("restricted", booleanToInt(item.isRestricted())); - - String title = item.getTitle(); - if (title == null) { - log.warning("Missing 'dc:title' element for item: " + item.getId()); - title = UNKNOWN_TITLE; - } - - appendNewElementIfNotNull( - descriptor, - itemElement, - "dc:title", - title, - DIDLObject.Property.DC.NAMESPACE.URI - ); - - appendNewElementIfNotNull( - descriptor, - itemElement, - "dc:creator", - item.getCreator(), - DIDLObject.Property.DC.NAMESPACE.URI - ); - - appendNewElementIfNotNull( - descriptor, - itemElement, - "upnp:writeStatus", - item.getWriteStatus(), - DIDLObject.Property.UPNP.NAMESPACE.URI - ); - - appendClass(descriptor, itemElement, item.getClazz(), "upnp:class", false); - - appendProperties(descriptor, itemElement, item, "upnp", DIDLObject.Property.UPNP.NAMESPACE.class, DIDLObject.Property.UPNP.NAMESPACE.URI); - appendProperties(descriptor, itemElement, item, "dc", DIDLObject.Property.DC.NAMESPACE.class, DIDLObject.Property.DC.NAMESPACE.URI); - appendProperties(descriptor, itemElement, item, "sec", DIDLObject.Property.SEC.NAMESPACE.class, DIDLObject.Property.SEC.NAMESPACE.URI); - - for (Res resource : item.getResources()) { - if (resource == null) continue; - generateResource(resource, descriptor, itemElement); - } - - for (DescMeta descMeta : item.getDescMetadata()) { - if (descMeta == null) continue; - generateDescMetadata(descMeta, descriptor, itemElement); - } - } - - protected void generateResource(Res resource, Document descriptor, Element parent) { - - if (resource.getValue() == null) { - throw new RuntimeException("Missing resource URI value" + resource); - } - if (resource.getProtocolInfo() == null) { - throw new RuntimeException("Missing resource protocol info: " + resource); - } - - Element resourceElement = appendNewElement(descriptor, parent, "res", resource.getValue()); - resourceElement.setAttribute("protocolInfo", resource.getProtocolInfo().toString()); - if (resource.getImportUri() != null) - resourceElement.setAttribute("importUri", resource.getImportUri().toString()); - if (resource.getSize() != null) - resourceElement.setAttribute("size", resource.getSize().toString()); - if (resource.getDuration() != null) - resourceElement.setAttribute("duration", resource.getDuration()); - if (resource.getBitrate() != null) - resourceElement.setAttribute("bitrate", resource.getBitrate().toString()); - if (resource.getSampleFrequency() != null) - resourceElement.setAttribute("sampleFrequency", resource.getSampleFrequency().toString()); - if (resource.getBitsPerSample() != null) - resourceElement.setAttribute("bitsPerSample", resource.getBitsPerSample().toString()); - if (resource.getNrAudioChannels() != null) - resourceElement.setAttribute("nrAudioChannels", resource.getNrAudioChannels().toString()); - if (resource.getColorDepth() != null) - resourceElement.setAttribute("colorDepth", resource.getColorDepth().toString()); - if (resource.getProtection() != null) - resourceElement.setAttribute("protection", resource.getProtection()); - if (resource.getResolution() != null) - resourceElement.setAttribute("resolution", resource.getResolution()); - } - - protected void generateDescMetadata(DescMeta descMeta, Document descriptor, Element parent) { - - if (descMeta.getId() == null) { - throw new RuntimeException("Missing id of description metadata: " + descMeta); - } - if (descMeta.getNameSpace() == null) { - throw new RuntimeException("Missing namespace of description metadata: " + descMeta); - } - - Element descElement = appendNewElement(descriptor, parent, "desc"); - descElement.setAttribute("id", descMeta.getId()); - descElement.setAttribute("nameSpace", descMeta.getNameSpace().toString()); - if (descMeta.getType() != null) - descElement.setAttribute("type", descMeta.getType()); - populateDescMetadata(descElement, descMeta); - } - - /** - * Expects an org.w3c.Document as metadata, copies nodes of the document into the DIDL content. - *

- * This method will ignore the content and log a warning if it's of the wrong type. If you override - * {@link #createDescMetaHandler(org.fourthline.cling.support.model.DescMeta, org.seamless.xml.SAXParser.Handler)}, - * you most likely also want to override this method. - *

- * - * @param descElement The DIDL content {@code } element wrapping the final metadata. - * @param descMeta The metadata with a org.w3c.Document payload. - */ - protected void populateDescMetadata(Element descElement, DescMeta descMeta) { - if (descMeta.getMetadata() instanceof Document) { - Document doc = (Document) descMeta.getMetadata(); - - NodeList nl = doc.getDocumentElement().getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) { - Node n = nl.item(i); - if (n.getNodeType() != Node.ELEMENT_NODE) - continue; - - Node clone = descElement.getOwnerDocument().importNode(n, true); - descElement.appendChild(clone); - } - - } else { - log.warning("Unknown desc metadata content, please override populateDescMetadata(): " + descMeta.getMetadata()); - } - } - - protected void appendProperties(Document descriptor, Element parent, DIDLObject object, String prefix, - Class namespace, - String namespaceURI) { - for (DIDLObject.Property property : object.getPropertiesByNamespace(namespace)) { - Element el = descriptor.createElementNS(namespaceURI, prefix + ":" + property.getDescriptorName()); - parent.appendChild(el); - property.setOnElement(el); - } - } - - protected void appendClass(Document descriptor, Element parent, DIDLObject.Class clazz, String element, boolean appendDerivation) { - Element classElement = appendNewElementIfNotNull( - descriptor, - parent, - element, - clazz.getValue(), - DIDLObject.Property.UPNP.NAMESPACE.URI - ); - if (clazz.getFriendlyName() != null && clazz.getFriendlyName().length() > 0) - classElement.setAttribute("name", clazz.getFriendlyName()); - if (appendDerivation) - classElement.setAttribute("includeDerived", Boolean.toString(clazz.isIncludeDerived())); - } - - protected String booleanToInt(boolean b) { - return b ? "1" : "0"; - } - - /** - * Sends the given string to the log with Level.FINE, if that log level is enabled. - * - * @param s The string to send to the log. - */ - public void debugXML(String s) { - if (log.isLoggable(Level.FINE)) { - log.fine("-------------------------------------------------------------------------------------"); - log.fine("\n" + s); - log.fine("-------------------------------------------------------------------------------------"); - } - } - - - /* ############################################################################################# */ - - - public abstract class DIDLObjectHandler extends Handler { - - protected DIDLObjectHandler(I instance, Handler parent) { - super(instance, parent); - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - super.endElement(uri, localName, qName); - - if (DIDLObject.Property.DC.NAMESPACE.URI.equals(uri)) { - - if ("title".equals(localName)) { - getInstance().setTitle(getCharacters()); - } else if ("creator".equals(localName)) { - getInstance().setCreator(getCharacters()); - } else if ("description".equals(localName)) { - getInstance().addProperty(new DIDLObject.Property.DC.DESCRIPTION(getCharacters())); - } else if ("publisher".equals(localName)) { - getInstance().addProperty(new DIDLObject.Property.DC.PUBLISHER(new Person(getCharacters()))); - } else if ("contributor".equals(localName)) { - getInstance().addProperty(new DIDLObject.Property.DC.CONTRIBUTOR(new Person(getCharacters()))); - } else if ("date".equals(localName)) { - getInstance().addProperty(new DIDLObject.Property.DC.DATE(getCharacters())); - } else if ("language".equals(localName)) { - getInstance().addProperty(new DIDLObject.Property.DC.LANGUAGE(getCharacters())); - } else if ("rights".equals(localName)) { - getInstance().addProperty(new DIDLObject.Property.DC.RIGHTS(getCharacters())); - } else if ("relation".equals(localName)) { - getInstance().addProperty(new DIDLObject.Property.DC.RELATION(URI.create(getCharacters()))); - } - - } else if (DIDLObject.Property.UPNP.NAMESPACE.URI.equals(uri)) { - - if ("writeStatus".equals(localName)) { - try { - getInstance().setWriteStatus( - WriteStatus.valueOf(getCharacters()) - ); - } catch (Exception ex) { - log.info("Ignoring invalid writeStatus value: " + getCharacters()); - } - } else if ("class".equals(localName)) { - getInstance().setClazz( - new DIDLObject.Class( - getCharacters(), - getAttributes().getValue("name") - ) - ); - } else if ("artist".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.ARTIST( - new PersonWithRole(getCharacters(), getAttributes().getValue("role")) - ) - ); - } else if ("actor".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.ACTOR( - new PersonWithRole(getCharacters(), getAttributes().getValue("role")) - ) - ); - } else if ("author".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.AUTHOR( - new PersonWithRole(getCharacters(), getAttributes().getValue("role")) - ) - ); - } else if ("producer".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.PRODUCER(new Person(getCharacters())) - ); - } else if ("director".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.DIRECTOR(new Person(getCharacters())) - ); - } else if ("longDescription".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.LONG_DESCRIPTION(getCharacters()) - ); - } else if ("storageUsed".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.STORAGE_USED(Long.valueOf(getCharacters())) - ); - } else if ("storageTotal".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.STORAGE_TOTAL(Long.valueOf(getCharacters())) - ); - } else if ("storageFree".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.STORAGE_FREE(Long.valueOf(getCharacters())) - ); - } else if ("storageMaxPartition".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.STORAGE_MAX_PARTITION(Long.valueOf(getCharacters())) - ); - } else if ("storageMedium".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.STORAGE_MEDIUM(StorageMedium.valueOrVendorSpecificOf(getCharacters())) - ); - } else if ("genre".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.GENRE(getCharacters()) - ); - } else if ("album".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.ALBUM(getCharacters()) - ); - } else if ("playlist".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.PLAYLIST(getCharacters()) - ); - } else if ("region".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.REGION(getCharacters()) - ); - } else if ("rating".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.RATING(getCharacters()) - ); - } else if ("toc".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.TOC(getCharacters()) - ); - } else if ("albumArtURI".equals(localName)) { - DIDLObject.Property albumArtURI = new DIDLObject.Property.UPNP.ALBUM_ART_URI(URI.create(getCharacters())); - - Attributes albumArtURIAttributes = getAttributes(); - for (int i = 0; i < albumArtURIAttributes.getLength(); i++) { - if ("profileID".equals(albumArtURIAttributes.getLocalName(i))) { - albumArtURI.addAttribute( - new DIDLObject.Property.DLNA.PROFILE_ID( - new DIDLAttribute( - DIDLObject.Property.DLNA.NAMESPACE.URI, - "dlna", - albumArtURIAttributes.getValue(i)) - )); - } - } - - getInstance().addProperty(albumArtURI); - } else if ("artistDiscographyURI".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.ARTIST_DISCO_URI(URI.create(getCharacters())) - ); - } else if ("lyricsURI".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.LYRICS_URI(URI.create(getCharacters())) - ); - } else if ("icon".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.ICON(URI.create(getCharacters())) - ); - } else if ("radioCallSign".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.RADIO_CALL_SIGN(getCharacters()) - ); - } else if ("radioStationID".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.RADIO_STATION_ID(getCharacters()) - ); - } else if ("radioBand".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.RADIO_BAND(getCharacters()) - ); - } else if ("channelNr".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.CHANNEL_NR(Integer.valueOf(getCharacters())) - ); - } else if ("channelName".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.CHANNEL_NAME(getCharacters()) - ); - } else if ("scheduledStartTime".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.SCHEDULED_START_TIME(getCharacters()) - ); - } else if ("scheduledEndTime".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.SCHEDULED_END_TIME(getCharacters()) - ); - } else if ("DVDRegionCode".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.DVD_REGION_CODE(Integer.valueOf(getCharacters())) - ); - } else if ("originalTrackNumber".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.ORIGINAL_TRACK_NUMBER(Integer.valueOf(getCharacters())) - ); - } else if ("userAnnotation".equals(localName)) { - getInstance().addProperty( - new DIDLObject.Property.UPNP.USER_ANNOTATION(getCharacters()) - ); - } - } - } - } - - public class RootHandler extends Handler { - - RootHandler(DIDLContent instance, SAXParser parser) { - super(instance, parser); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - super.startElement(uri, localName, qName, attributes); - - if (!DIDLContent.NAMESPACE_URI.equals(uri)) return; - - if (localName.equals("container")) { - - Container container = createContainer(attributes); - getInstance().addContainer(container); - createContainerHandler(container, this); - - } else if (localName.equals("item")) { - - Item item = createItem(attributes); - getInstance().addItem(item); - createItemHandler(item, this); - - } else if (localName.equals("desc")) { - - DescMeta desc = createDescMeta(attributes); - getInstance().addDescMetadata(desc); - createDescMetaHandler(desc, this); - - } - } - - @Override - protected boolean isLastElement(String uri, String localName, String qName) { - if (DIDLContent.NAMESPACE_URI.equals(uri) && "DIDL-Lite".equals(localName)) { - - // Now transform all the generically typed Container and Item instances into - // more specific Album, MusicTrack, etc. instances - getInstance().replaceGenericContainerAndItems(); - - return true; - } - return false; - } - } - - public class ContainerHandler extends DIDLObjectHandler { - public ContainerHandler(Container instance, Handler parent) { - super(instance, parent); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - super.startElement(uri, localName, qName, attributes); - - if (!DIDLContent.NAMESPACE_URI.equals(uri)) return; - - if (localName.equals("item")) { - - Item item = createItem(attributes); - getInstance().addItem(item); - createItemHandler(item, this); - - } else if (localName.equals("desc")) { - - DescMeta desc = createDescMeta(attributes); - getInstance().addDescMetadata(desc); - createDescMetaHandler(desc, this); - - } else if (localName.equals("res")) { - - Res res = createResource(attributes); - if (res != null) { - getInstance().addResource(res); - createResHandler(res, this); - } - - } - - // We do NOT support recursive container embedded in container! The schema allows it - // but the spec doesn't: - // - // Section 2.8.3: Incremental navigation i.e. the full hierarchy is never returned - // in one call since this is likely to flood the resources available to the control - // point (memory, network bandwidth, etc.). - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - super.endElement(uri, localName, qName); - - if (DIDLObject.Property.UPNP.NAMESPACE.URI.equals(uri)) { - - if ("searchClass".equals(localName)) { - getInstance().getSearchClasses().add( - new DIDLObject.Class( - getCharacters(), - getAttributes().getValue("name"), - "true".equals(getAttributes().getValue("includeDerived")) - ) - ); - } else if ("createClass".equals(localName)) { - getInstance().getCreateClasses().add( - new DIDLObject.Class( - getCharacters(), - getAttributes().getValue("name"), - "true".equals(getAttributes().getValue("includeDerived")) - ) - ); - } - } - } - - @Override - protected boolean isLastElement(String uri, String localName, String qName) { - if (DIDLContent.NAMESPACE_URI.equals(uri) && "container".equals(localName)) { - if (getInstance().getTitle() == null) { - log.warning("In DIDL content, missing 'dc:title' element for container: " + getInstance().getId()); - } - if (getInstance().getClazz() == null) { - log.warning("In DIDL content, missing 'upnp:class' element for container: " + getInstance().getId()); - } - return true; - } - return false; - } - } - - public class ItemHandler extends DIDLObjectHandler { - public ItemHandler(Item instance, Handler parent) { - super(instance, parent); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - super.startElement(uri, localName, qName, attributes); - - if (!DIDLContent.NAMESPACE_URI.equals(uri)) return; - - if (localName.equals("res")) { - - Res res = createResource(attributes); - if (res != null) { - getInstance().addResource(res); - createResHandler(res, this); - } - - } else if (localName.equals("desc")) { - - DescMeta desc = createDescMeta(attributes); - getInstance().addDescMetadata(desc); - createDescMetaHandler(desc, this); - - } - } - - @Override - protected boolean isLastElement(String uri, String localName, String qName) { - if (DIDLContent.NAMESPACE_URI.equals(uri) && "item".equals(localName)) { - if (getInstance().getTitle() == null) { - log.warning("In DIDL content, missing 'dc:title' element for item: " + getInstance().getId()); - } - if (getInstance().getClazz() == null) { - log.warning("In DIDL content, missing 'upnp:class' element for item: " + getInstance().getId()); - } - return true; - } - return false; - } - } - - protected class ResHandler extends Handler { - public ResHandler(Res instance, Handler parent) { - super(instance, parent); - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - super.endElement(uri, localName, qName); - getInstance().setValue(getCharacters()); - } - - @Override - protected boolean isLastElement(String uri, String localName, String qName) { - return DIDLContent.NAMESPACE_URI.equals(uri) && "res".equals(localName); - } - } - - /** - * Extracts an org.w3c.Document from the nested elements in the {@code } element. - *

- * The root element of this document is a wrapper in the namespace - * {@link org.fourthline.cling.support.model.DIDLContent#DESC_WRAPPER_NAMESPACE_URI}. - *

- */ - public class DescMetaHandler extends Handler { - - protected Element current; - - public DescMetaHandler(DescMeta instance, Handler parent) { - super(instance, parent); - instance.setMetadata(instance.createMetadataDocument()); - current = getInstance().getMetadata().getDocumentElement(); - } - - @Override - public DescMeta getInstance() { - return super.getInstance(); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - super.startElement(uri, localName, qName, attributes); - - Element newEl = getInstance().getMetadata().createElementNS(uri, qName); - for (int i = 0; i < attributes.getLength(); i++) { - newEl.setAttributeNS( - attributes.getURI(i), - attributes.getQName(i), - attributes.getValue(i) - ); - } - current.appendChild(newEl); - current = newEl; - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - super.endElement(uri, localName, qName); - if (isLastElement(uri, localName, qName)) return; - - // Ignore whitespace - if (getCharacters().length() > 0 && !getCharacters().matches("[\\t\\n\\x0B\\f\\r\\s]+")) - current.appendChild(getInstance().getMetadata().createTextNode(getCharacters())); - - current = (Element) current.getParentNode(); - - // Reset this so we can continue parsing child nodes with this handler - characters = new StringBuilder(); - attributes = null; - } - - @Override - protected boolean isLastElement(String uri, String localName, String qName) { - return DIDLContent.NAMESPACE_URI.equals(uri) && "desc".equals(localName); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/Browse.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/Browse.java deleted file mode 100644 index 60f1507..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/Browse.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.contentdirectory.DIDLParser; -import org.fourthline.cling.support.model.BrowseFlag; -import org.fourthline.cling.support.model.BrowseResult; -import org.fourthline.cling.support.model.DIDLContent; -import org.fourthline.cling.support.model.SortCriterion; - -import java.util.logging.Logger; - -/** - * Invokes a "Browse" action, parses the result. - * - * @author Christian Bauer - */ -public abstract class Browse extends ActionCallback { - - public static final String CAPS_WILDCARD = "*"; - - public enum Status { - NO_CONTENT("No Content"), - LOADING("Loading..."), - OK("OK"); - - private String defaultMessage; - - Status(String defaultMessage) { - this.defaultMessage = defaultMessage; - } - - public String getDefaultMessage() { - return defaultMessage; - } - } - - private static Logger log = Logger.getLogger(Browse.class.getName()); - - /** - * Browse with first result 0 and {@link #getDefaultMaxResults()}, filters with {@link #CAPS_WILDCARD}. - */ - public Browse(Service service, String containerId, BrowseFlag flag) { - this(service, containerId, flag, CAPS_WILDCARD, 0, null); - } - - /** - * @param maxResults Can be null, then {@link #getDefaultMaxResults()} is used. - */ - public Browse(Service service, String objectID, BrowseFlag flag, - String filter, long firstResult, Long maxResults, SortCriterion... orderBy) { - - super(new ActionInvocation(service.getAction("Browse"))); - - log.fine("Creating browse action for object ID: " + objectID); - - getActionInvocation().setInput("ObjectID", objectID); - getActionInvocation().setInput("BrowseFlag", flag.toString()); - getActionInvocation().setInput("Filter", filter); - getActionInvocation().setInput("StartingIndex", new UnsignedIntegerFourBytes(firstResult)); - getActionInvocation().setInput("RequestedCount", - new UnsignedIntegerFourBytes(maxResults == null ? getDefaultMaxResults() : maxResults) - ); - getActionInvocation().setInput("SortCriteria", SortCriterion.toString(orderBy)); - } - - @Override - public void run() { - updateStatus(Status.LOADING); - super.run(); - } - - public void success(ActionInvocation invocation) { - log.fine("Successful browse action, reading output argument values"); - - BrowseResult result = new BrowseResult( - invocation.getOutput("Result").getValue().toString(), - (UnsignedIntegerFourBytes) invocation.getOutput("NumberReturned").getValue(), - (UnsignedIntegerFourBytes) invocation.getOutput("TotalMatches").getValue(), - (UnsignedIntegerFourBytes) invocation.getOutput("UpdateID").getValue() - ); - - boolean proceed = receivedRaw(invocation, result); - - if (proceed && result.getCountLong() > 0 && result.getResult().length() > 0) { - - try { - - DIDLParser didlParser = new DIDLParser(); - DIDLContent didl = didlParser.parse(result.getResult()); - received(invocation, didl); - updateStatus(Status.OK); - - } catch (Exception ex) { - invocation.setFailure( - new ActionException(ErrorCode.ACTION_FAILED, "Can't parse DIDL XML response: " + ex, ex) - ); - failure(invocation, null); - } - - } else { - received(invocation, new DIDLContent()); - updateStatus(Status.NO_CONTENT); - } - } - - /** - * Some media servers will crash if there is no limit on the maximum number of results. - * - * @return The default limit, 999. - */ - public long getDefaultMaxResults() { - return 999; - } - - public boolean receivedRaw(ActionInvocation actionInvocation, BrowseResult browseResult) { - /* - if (log.isLoggable(Level.FINER)) { - log.finer("-------------------------------------------------------------------------------------"); - log.finer("\n" + XML.pretty(browseResult.getDidl())); - log.finer("-------------------------------------------------------------------------------------"); - } - */ - return true; - } - - public abstract void received(ActionInvocation actionInvocation, DIDLContent didl); - public abstract void updateStatus(Status status); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/GetSystemUpdateID.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/GetSystemUpdateID.java deleted file mode 100644 index 71584b7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/GetSystemUpdateID.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.types.ErrorCode; - -/** - * - * @author Christian Bauer - */ -public abstract class GetSystemUpdateID extends ActionCallback { - - public GetSystemUpdateID(org.fourthline.cling.model.meta.Service service) { - super(new ActionInvocation(service.getAction("GetSystemUpdateID"))); - } - - public void success(ActionInvocation invocation) { - boolean ok = true; - long id = 0; - try { - id = Long.valueOf(invocation.getOutput("Id").getValue().toString()); // UnsignedIntegerFourBytes... - } catch (Exception ex) { - invocation.setFailure(new ActionException(ErrorCode.ACTION_FAILED, "Can't parse GetSystemUpdateID response: " + ex, ex)); - failure(invocation, null); - ok = false; - } - if (ok) received(invocation, id); - } - - public abstract void received(ActionInvocation invocation, long systemUpdateID); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/Search.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/Search.java deleted file mode 100644 index 819044f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/callback/Search.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.contentdirectory.DIDLParser; -import org.fourthline.cling.support.model.DIDLContent; -import org.fourthline.cling.support.model.SearchResult; -import org.fourthline.cling.support.model.SortCriterion; - -import java.util.logging.Logger; - -/** - * Invokes a "Search" action, parses the result. - * - * @author TK Kocheran <rfkrocktk@gmail.com> - */ -public abstract class Search extends ActionCallback { - - public static final String CAPS_WILDCARD = "*"; - - public enum Status { - NO_CONTENT("No Content"), - LOADING("Loading..."), - OK("OK"); - - private String defaultMessage; - - Status(String defaultMessage) { - this.defaultMessage = defaultMessage; - } - - public String getDefaultMessage() { - return this.defaultMessage; - } - } - - private static Logger log = Logger.getLogger(Search.class.getName()); - - /** - * Search with first result 0 and {@link #getDefaultMaxResults()}, filters with {@link #CAPS_WILDCARD}. - */ - public Search(Service service, String containerId, String searchCriteria) { - this(service, containerId, searchCriteria, CAPS_WILDCARD, 0, null); - } - - /** - * @param maxResults Can be null, then {@link #getDefaultMaxResults()} is used. - */ - public Search(Service service, String containerId, String searchCriteria, String filter, - long firstResult, Long maxResults, SortCriterion... orderBy) { - super(new ActionInvocation(service.getAction("Search"))); - - log.fine("Creating browse action for container ID: " + containerId); - - getActionInvocation().setInput("ContainerID", containerId); - getActionInvocation().setInput("SearchCriteria", searchCriteria); - getActionInvocation().setInput("Filter", filter); - getActionInvocation().setInput("StartingIndex", new UnsignedIntegerFourBytes(firstResult)); - getActionInvocation().setInput( - "RequestedCount", - new UnsignedIntegerFourBytes(maxResults == null ? getDefaultMaxResults() : maxResults) - ); - getActionInvocation().setInput("SortCriteria", SortCriterion.toString(orderBy)); - } - - @Override - public void run() { - updateStatus(Status.LOADING); - super.run(); - } - - @Override - public void success(ActionInvocation actionInvocation) { - log.fine("Successful search action, reading output argument values"); - - SearchResult result = new SearchResult( - actionInvocation.getOutput("Result").getValue().toString(), - (UnsignedIntegerFourBytes) actionInvocation.getOutput("NumberReturned").getValue(), - (UnsignedIntegerFourBytes) actionInvocation.getOutput("TotalMatches").getValue(), - (UnsignedIntegerFourBytes) actionInvocation.getOutput("UpdateID").getValue()); - - boolean proceed = receivedRaw(actionInvocation, result); - - if (proceed && result.getCountLong() > 0 && result.getResult().length() > 0) { - try { - DIDLParser didlParser = new DIDLParser(); - DIDLContent didl = didlParser.parse(result.getResult()); - received(actionInvocation, didl); - updateStatus(Status.OK); - } catch (Exception ex) { - actionInvocation.setFailure( - new ActionException(ErrorCode.ACTION_FAILED, "Can't parse DIDL XML response: " + ex, ex) - ); - failure(actionInvocation, null); - } - } else { - received(actionInvocation, new DIDLContent()); - updateStatus(Status.NO_CONTENT); - } - } - - /** - * Some media servers will crash if there is no limit on the maximum number of results. - * - * @return The default limit, 999. - */ - public Long getDefaultMaxResults() { - return 999L; - } - - public boolean receivedRaw(ActionInvocation actionInvocation, SearchResult searchResult) { - return true; - } - - public abstract void received(ActionInvocation actionInvocation, DIDLContent didl); - - public abstract void updateStatus(Status status); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentBrowseActionCallback.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentBrowseActionCallback.java deleted file mode 100644 index 2a5dac2..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentBrowseActionCallback.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory.ui; - -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.support.model.BrowseFlag; -import org.fourthline.cling.support.model.DIDLContent; -import org.fourthline.cling.support.model.SortCriterion; -import org.fourthline.cling.support.contentdirectory.callback.Browse; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.support.model.container.Container; -import org.fourthline.cling.support.model.item.Item; - -import java.util.logging.Logger; - -import javax.swing.tree.MutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.SwingUtilities; -import java.util.ArrayList; -import java.util.List; - -/** - * Updates a tree model after querying a backend ContentDirectory service. - * - * @author Christian Bauer - */ -public abstract class ContentBrowseActionCallback extends Browse { - - private static Logger log = Logger.getLogger(ContentBrowseActionCallback.class.getName()); - - final protected DefaultTreeModel treeModel; - final protected DefaultMutableTreeNode treeNode; - - public ContentBrowseActionCallback(Service service, DefaultTreeModel treeModel, DefaultMutableTreeNode treeNode) { - super(service, ((Container) treeNode.getUserObject()).getId(), BrowseFlag.DIRECT_CHILDREN, "*", 0, null, new SortCriterion(true, "dc:title")); - this.treeModel = treeModel; - this.treeNode = treeNode; - } - - public ContentBrowseActionCallback(Service service, DefaultTreeModel treeModel, DefaultMutableTreeNode treeNode, - String filter, long firstResult, long maxResults, SortCriterion... orderBy) { - super(service, ((Container) treeNode.getUserObject()).getId(), BrowseFlag.DIRECT_CHILDREN, filter, firstResult, maxResults, orderBy); - this.treeModel = treeModel; - this.treeNode = treeNode; - } - - public DefaultTreeModel getTreeModel() { - return treeModel; - } - - public DefaultMutableTreeNode getTreeNode() { - return treeNode; - } - - public void received(final ActionInvocation actionInvocation, DIDLContent didl) { - log.fine("Received browse action DIDL descriptor, creating tree nodes"); - final List childNodes = new ArrayList<>(); - - try { - - // Containers first - for (Container childContainer : didl.getContainers()) { - DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(childContainer) { - @Override - public boolean isLeaf() { - return false; - /* TODO: UPNP VIOLATION: We can't trust the childcount attribute at all, some - servers return 0 even if there are children. - - // The 'childCount' is optional, so we always have to assume that unless - // there is a non-zero child count, there are children and we don't know - // anything about them - Container container = ((Container) getUserObject()); - Integer childCount = container.getChildCount(); - return childCount != null && childCount <= 0; - */ - } - }; - childNodes.add(childNode); - } - - // Now items - for (Item childItem : didl.getItems()) { - DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(childItem) { - @Override - public boolean isLeaf() { - return true; - } - }; - childNodes.add(childNode); - } - - } catch (Exception ex) { - log.fine("Creating DIDL tree nodes failed: " + ex); - actionInvocation.setFailure( - new ActionException(ErrorCode.ACTION_FAILED, "Can't create tree child nodes: " + ex, ex) - ); - failure(actionInvocation, null); - } - - SwingUtilities.invokeLater(new Runnable() { - public void run() { - updateTreeModel(childNodes); - } - }); - } - - public void updateStatus(final Status status) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - updateStatusUI(status, treeNode, treeModel); - } - }); - } - - @Override - public void failure(ActionInvocation invocation, UpnpResponse operation, final String defaultMsg) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - failureUI(defaultMsg); - } - }); - } - - protected void updateTreeModel(final List childNodes) { - log.fine("Adding nodes to tree: " + childNodes.size()); - // Remove all "old" children such as the loading/progress messages - removeChildren(); - - // Insert new children - for (DefaultMutableTreeNode childNode : childNodes) { - insertChild(childNode); - } - } - - protected void removeChildren() { - treeNode.removeAllChildren(); - treeModel.nodeStructureChanged(treeNode); - } - - protected void insertChild(MutableTreeNode childNode) { - int index = treeNode.getChildCount() <= 0 ? 0 : treeNode.getChildCount(); - treeModel.insertNodeInto(childNode, treeNode, index); - } - - public abstract void updateStatusUI(Status status, DefaultMutableTreeNode treeNode, DefaultTreeModel treeModel); - - public abstract void failureUI(String failureMessage); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentBrowseActionCallbackCreator.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentBrowseActionCallbackCreator.java deleted file mode 100644 index b3bd073..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentBrowseActionCallbackCreator.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory.ui; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.meta.Service; - -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.DefaultMutableTreeNode; - -/** - * @author Christian Bauer - */ -public interface ContentBrowseActionCallbackCreator { - - public ActionCallback createContentBrowseActionCallback(Service service, - DefaultTreeModel treeModel, - DefaultMutableTreeNode treeNode); - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTree.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTree.java deleted file mode 100644 index 40e7c83..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTree.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory.ui; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.support.model.container.Container; - -import javax.swing.JTree; -import javax.swing.event.TreeWillExpandListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeSelectionModel; - -/** - * Ready-to-use JTree with interactive browsing of a backend ContentDirectory service. - *

- * Shows the loading status as icon + text informational node directly in the tree. - *

- * - * @author Christian Bauer - */ -public abstract class ContentTree extends JTree implements ContentBrowseActionCallbackCreator { - - protected Container rootContainer; - protected DefaultMutableTreeNode rootNode; - - protected ContentTree() { - } - - public ContentTree(ControlPoint controlPoint, Service service) { - init(controlPoint, service); - } - - public void init(ControlPoint controlPoint, Service service) { - rootContainer = createRootContainer(service); - rootNode = new DefaultMutableTreeNode(rootContainer) { - @Override - public boolean isLeaf() { - return false; - } - }; - - DefaultTreeModel treeModel = new DefaultTreeModel(rootNode); - setModel(treeModel); - - getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - addTreeWillExpandListener(createContainerTreeExpandListener(controlPoint, service, treeModel)); - setCellRenderer(createContainerTreeCellRenderer()); - - controlPoint.execute(createContentBrowseActionCallback(service, treeModel, getRootNode())); - } - - public Container getRootContainer() { - return rootContainer; - } - - public DefaultMutableTreeNode getRootNode() { - return rootNode; - } - - public DefaultMutableTreeNode getSelectedNode() { - return (DefaultMutableTreeNode) getLastSelectedPathComponent(); - } - - protected Container createRootContainer(Service service) { - Container rootContainer = new Container(); - rootContainer.setId("0"); - rootContainer.setTitle("Content Directory on " + service.getDevice().getDisplayString()); - return rootContainer; - } - - protected TreeWillExpandListener createContainerTreeExpandListener(ControlPoint controlPoint, - Service service, - DefaultTreeModel treeModel) { - return new ContentTreeExpandListener(controlPoint, service, treeModel, this); - } - - protected DefaultTreeCellRenderer createContainerTreeCellRenderer() { - return new ContentTreeCellRenderer(); - } - - public ActionCallback createContentBrowseActionCallback(Service service, - DefaultTreeModel treeModel, - DefaultMutableTreeNode treeNode) { - - return new ContentBrowseActionCallback(service, treeModel, treeNode) { - public void updateStatusUI(Status status, DefaultMutableTreeNode treeNode, DefaultTreeModel treeModel) { - ContentTree.this.updateStatus(status, treeNode, treeModel); - } - public void failureUI(String failureMessage) { - ContentTree.this.failure(failureMessage); - } - }; - } - - // Show some of the status messages _inside_ the tree as a special node - public void updateStatus(ContentBrowseActionCallback.Status status, DefaultMutableTreeNode treeNode, DefaultTreeModel treeModel) { - switch(status) { - case LOADING: - case NO_CONTENT: - treeNode.removeAllChildren(); - int index = treeNode.getChildCount() <= 0 ? 0 : treeNode.getChildCount(); - treeModel.insertNodeInto(new DefaultMutableTreeNode(status.getDefaultMessage()), treeNode, index); - treeModel.nodeStructureChanged(treeNode); - break; - } - } - - public abstract void failure(String message); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTreeCellRenderer.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTreeCellRenderer.java deleted file mode 100644 index 1c90ead..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTreeCellRenderer.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory.ui; - -import org.fourthline.cling.support.model.DIDLObject; -import org.fourthline.cling.support.model.container.Container; -import org.fourthline.cling.support.model.item.Item; - -import javax.swing.Icon; -import javax.swing.JTree; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import java.awt.Component; - -/** - * @author Christian Bauer - */ -public class ContentTreeCellRenderer extends DefaultTreeCellRenderer { - - public Component getTreeCellRendererComponent( - JTree tree, - Object value, - boolean sel, - boolean expanded, - boolean leaf, - int row, - boolean hasFocus) { - - super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - - DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; - - if (node.getUserObject() instanceof Container) { - - Container container = (Container) node.getUserObject(); - setText(container.getTitle()); - setIcon(expanded ? getContainerOpenIcon() : getContainerClosedIcon()); - - } else if (node.getUserObject() instanceof Item) { - - Item item = (Item) node.getUserObject(); - setText(item.getTitle()); - - DIDLObject.Class upnpClass = item.getClazz(); - setIcon(getItemIcon(item, upnpClass != null ? upnpClass.getValue() : null)); - - } else if (node.getUserObject() instanceof String) { - setIcon(getInfoIcon()); - } - - onCreate(); - return this; - } - - protected void onCreate() { - - } - - protected Icon getContainerOpenIcon() { - return null; - } - - protected Icon getContainerClosedIcon() { - return null; - } - - protected Icon getItemIcon(Item item, String upnpClass) { - return null; - } - - protected Icon getInfoIcon() { - return null; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTreeExpandListener.java b/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTreeExpandListener.java deleted file mode 100644 index 46c3f04..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/contentdirectory/ui/ContentTreeExpandListener.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.contentdirectory.ui; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.meta.Service; - -import javax.swing.event.TreeExpansionEvent; -import javax.swing.event.TreeWillExpandListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.ExpandVetoException; - -/** - * @author Christian Bauer - */ -public class ContentTreeExpandListener implements TreeWillExpandListener { - - final protected ControlPoint controlPoint; - final protected Service service; - final protected DefaultTreeModel treeModel; - final protected ContentBrowseActionCallbackCreator actionCreator; - - public ContentTreeExpandListener(ControlPoint controlPoint, - Service service, - DefaultTreeModel treeModel, - ContentBrowseActionCallbackCreator actionCreator) { - this.controlPoint = controlPoint; - this.service = service; - this.treeModel = treeModel; - this.actionCreator = actionCreator; - } - - public void treeWillExpand(final TreeExpansionEvent e) throws ExpandVetoException { - final DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) e.getPath().getLastPathComponent(); - - // Remove all "old" children such as the loading/progress messages - treeNode.removeAllChildren(); - treeModel.nodeStructureChanged(treeNode); - - // Perform the loading in a background thread - ActionCallback callback = - actionCreator.createContentBrowseActionCallback( - service, treeModel, treeNode - ); - controlPoint.execute(callback); - } - - public void treeWillCollapse(TreeExpansionEvent e) throws ExpandVetoException { - - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/PortMappingListener.java b/clinglibrary/src/main/java/org/fourthline/cling/support/igd/PortMappingListener.java deleted file mode 100644 index 40e87b5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/PortMappingListener.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.igd; - -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.meta.Device; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.DeviceType; -import org.fourthline.cling.model.types.ServiceType; -import org.fourthline.cling.model.types.UDADeviceType; -import org.fourthline.cling.model.types.UDAServiceType; -import org.fourthline.cling.registry.DefaultRegistryListener; -import org.fourthline.cling.registry.Registry; -import org.fourthline.cling.support.igd.callback.PortMappingAdd; -import org.fourthline.cling.support.igd.callback.PortMappingDelete; -import org.fourthline.cling.support.model.PortMapping; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -/** - * Maintains UPnP port mappings on an InternetGatewayDevice automatically. - *

- * This listener will wait for discovered devices which support either - * {@code WANIPConnection} or the {@code WANPPPConnection} service. As soon as any such - * service is discovered, the desired port mapping will be created. When the UPnP service - * is shutting down, all previously established port mappings with all services will - * be deleted. - *

- *

- * The following listener maps external WAN TCP port 8123 to internal host 10.0.0.2: - *

- *
{@code
- * upnpService.getRegistry().addListener(
- *newPortMappingListener(newPortMapping(8123, "10.0.0.2",PortMapping.Protocol.TCP))
- * );}
- *

- * If all you need from the Cling UPnP stack is NAT port mapping, use the following idiom: - *

- *
{@code
- * UpnpService upnpService = new UpnpServiceImpl(
- *     new PortMappingListener(new PortMapping(8123, "10.0.0.2", PortMapping.Protocol.TCP))
- * );
- * 

- * upnpService.getControlPoint().search(new STAllHeader()); // Search for all devices - *

- * upnpService.shutdown(); // When you no longer need the port mapping - * }

- * - * @author Christian Bauer - */ -public class PortMappingListener extends DefaultRegistryListener { - - private static final Logger log = Logger.getLogger(PortMappingListener.class.getName()); - - public static final DeviceType IGD_DEVICE_TYPE = new UDADeviceType("InternetGatewayDevice", 1); - public static final DeviceType CONNECTION_DEVICE_TYPE = new UDADeviceType("WANConnectionDevice", 1); - - public static final ServiceType IP_SERVICE_TYPE = new UDAServiceType("WANIPConnection", 1); - public static final ServiceType PPP_SERVICE_TYPE = new UDAServiceType("WANPPPConnection", 1); - - protected PortMapping[] portMappings; - - // The key of the map is Service and equality is object identity, this is by-design - protected Map> activePortMappings = new HashMap<>(); - - public PortMappingListener(PortMapping portMapping) { - this(new PortMapping[]{portMapping}); - } - - public PortMappingListener(PortMapping[] portMappings) { - this.portMappings = portMappings; - } - - @Override - synchronized public void deviceAdded(Registry registry, Device device) { - - Service connectionService; - if ((connectionService = discoverConnectionService(device)) == null) return; - - log.fine("Activating port mappings on: " + connectionService); - - final List activeForService = new ArrayList<>(); - for (final PortMapping pm : portMappings) { - new PortMappingAdd(connectionService, registry.getUpnpService().getControlPoint(), pm) { - - @Override - public void success(ActionInvocation invocation) { - log.fine("Port mapping added: " + pm); - activeForService.add(pm); - } - - @Override - public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) { - handleFailureMessage("Failed to add port mapping: " + pm); - handleFailureMessage("Reason: " + defaultMsg); - } - }.run(); // Synchronous! - } - - activePortMappings.put(connectionService, activeForService); - } - - @Override - synchronized public void deviceRemoved(Registry registry, Device device) { - for (Service service : device.findServices()) { - Iterator>> it = activePortMappings.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry> activeEntry = it.next(); - if (!activeEntry.getKey().equals(service)) continue; - - if (activeEntry.getValue().size() > 0) - handleFailureMessage("Device disappeared, couldn't delete port mappings: " + activeEntry.getValue().size()); - - it.remove(); - } - } - } - - @Override - synchronized public void beforeShutdown(Registry registry) { - for (Map.Entry> activeEntry : activePortMappings.entrySet()) { - - final Iterator it = activeEntry.getValue().iterator(); - while (it.hasNext()) { - final PortMapping pm = it.next(); - log.fine("Trying to delete port mapping on IGD: " + pm); - new PortMappingDelete(activeEntry.getKey(), registry.getUpnpService().getControlPoint(), pm) { - - @Override - public void success(ActionInvocation invocation) { - log.fine("Port mapping deleted: " + pm); - it.remove(); - } - - @Override - public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) { - handleFailureMessage("Failed to delete port mapping: " + pm); - handleFailureMessage("Reason: " + defaultMsg); - } - - }.run(); // Synchronous! - } - } - } - - protected Service discoverConnectionService(Device device) { - if (!device.getType().equals(IGD_DEVICE_TYPE)) { - return null; - } - - Device[] connectionDevices = device.findDevices(CONNECTION_DEVICE_TYPE); - if (connectionDevices.length == 0) { - log.fine("IGD doesn't support '" + CONNECTION_DEVICE_TYPE + "': " + device); - return null; - } - - Device connectionDevice = connectionDevices[0]; - log.fine("Using first discovered WAN connection device: " + connectionDevice); - - Service ipConnectionService = connectionDevice.findService(IP_SERVICE_TYPE); - Service pppConnectionService = connectionDevice.findService(PPP_SERVICE_TYPE); - - if (ipConnectionService == null && pppConnectionService == null) { - log.fine("IGD doesn't support IP or PPP WAN connection service: " + device); - } - - return ipConnectionService != null ? ipConnectionService : pppConnectionService; - } - - protected void handleFailureMessage(String s) { - log.warning(s); - } - -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/GetExternalIP.java b/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/GetExternalIP.java deleted file mode 100644 index 08df5c5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/GetExternalIP.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.igd.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; - -/** - * @author Christian Bauer - */ -public abstract class GetExternalIP extends ActionCallback { - - public GetExternalIP(Service service) { - super(new ActionInvocation(service.getAction("GetExternalIPAddress"))); - } - - @Override - public void success(ActionInvocation invocation) { - success((String)invocation.getOutput("NewExternalIPAddress").getValue()); - } - - protected abstract void success(String externalIPAddress); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/GetStatusInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/GetStatusInfo.java deleted file mode 100644 index 3a497a7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/GetStatusInfo.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.igd.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.Connection; - -/** - * @author Christian Bauer - */ -public abstract class GetStatusInfo extends ActionCallback { - - public GetStatusInfo(Service service) { - super(new ActionInvocation(service.getAction("GetStatusInfo"))); - } - - @Override - public void success(ActionInvocation invocation) { - - try { - Connection.Status status = - Connection.Status.valueOf(invocation.getOutput("NewConnectionStatus").getValue().toString()); - - Connection.Error lastError = - Connection.Error.valueOf(invocation.getOutput("NewLastConnectionError").getValue().toString()); - - success(new Connection.StatusInfo(status, (UnsignedIntegerFourBytes) invocation.getOutput("NewUptime").getValue(), lastError)); - - } catch (Exception ex) { - invocation.setFailure( - new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, - "Invalid status or last error string: " + ex, - ex - ) - ); - failure(invocation, null); - } - } - - protected abstract void success(Connection.StatusInfo statusInfo); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingAdd.java b/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingAdd.java deleted file mode 100644 index d61ccca..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingAdd.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.igd.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.support.model.PortMapping; - -/** - * @author Christian Bauer - */ -public abstract class PortMappingAdd extends ActionCallback { - - final protected PortMapping portMapping; - - public PortMappingAdd(Service service, PortMapping portMapping) { - this(service, null, portMapping); - } - - protected PortMappingAdd(Service service, ControlPoint controlPoint, PortMapping portMapping) { - super(new ActionInvocation(service.getAction("AddPortMapping")), controlPoint); - - this.portMapping = portMapping; - - getActionInvocation().setInput("NewExternalPort", portMapping.getExternalPort()); - getActionInvocation().setInput("NewProtocol", portMapping.getProtocol()); - getActionInvocation().setInput("NewInternalClient", portMapping.getInternalClient()); - getActionInvocation().setInput("NewInternalPort", portMapping.getInternalPort()); - getActionInvocation().setInput("NewLeaseDuration", portMapping.getLeaseDurationSeconds()); - getActionInvocation().setInput("NewEnabled", portMapping.isEnabled()); - if (portMapping.hasRemoteHost()) - getActionInvocation().setInput("NewRemoteHost", portMapping.getRemoteHost()); - if (portMapping.hasDescription()) - getActionInvocation().setInput("NewPortMappingDescription", portMapping.getDescription()); - - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingDelete.java b/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingDelete.java deleted file mode 100644 index d6cc73c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingDelete.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.igd.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.support.model.PortMapping; - -/** - * @author Christian Bauer - */ -public abstract class PortMappingDelete extends ActionCallback { - - final protected PortMapping portMapping; - - public PortMappingDelete(Service service, PortMapping portMapping) { - this(service, null, portMapping); - } - - protected PortMappingDelete(Service service, ControlPoint controlPoint, PortMapping portMapping) { - super(new ActionInvocation(service.getAction("DeletePortMapping")), controlPoint); - - this.portMapping = portMapping; - - getActionInvocation().setInput("NewExternalPort", portMapping.getExternalPort()); - getActionInvocation().setInput("NewProtocol", portMapping.getProtocol()); - if (portMapping.hasRemoteHost()) - getActionInvocation().setInput("NewRemoteHost", portMapping.getRemoteHost()); - - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingEntryGet.java b/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingEntryGet.java deleted file mode 100644 index 82ca2e9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/igd/callback/PortMappingEntryGet.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.fourthline.cling.support.igd.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.controlpoint.ControlPoint; -import org.fourthline.cling.model.action.ActionArgumentValue; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes; -import org.fourthline.cling.support.model.PortMapping; - -import java.util.Map; - -public abstract class PortMappingEntryGet extends ActionCallback { - - public PortMappingEntryGet(Service service, long index) { - this(service, null, index); - } - - protected PortMappingEntryGet(Service service, ControlPoint controlPoint, long index) { - super(new ActionInvocation(service.getAction("GetGenericPortMappingEntry")), controlPoint); - - getActionInvocation().setInput("NewPortMappingIndex", new UnsignedIntegerTwoBytes(index)); - } - - @Override - public void success(ActionInvocation invocation) { - - Map> outputMap = invocation.getOutputMap(); - success(new PortMapping(outputMap)); - } - - protected abstract void success(PortMapping portMapping); -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/Event.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/Event.java deleted file mode 100644 index 5cc5d27..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/Event.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class Event { - - protected List instanceIDs = new ArrayList<>(); - - public Event() { - } - - public Event(List instanceIDs) { - this.instanceIDs = instanceIDs; - } - - public List getInstanceIDs() { - return instanceIDs; - } - - public InstanceID getInstanceID(UnsignedIntegerFourBytes id) { - for (InstanceID instanceID : instanceIDs) { - if (instanceID.getId().equals(id)) return instanceID; - } - return null; - } - - public void clear() { - instanceIDs = new ArrayList<>(); - } - - public void setEventedValue(UnsignedIntegerFourBytes id, EventedValue ev) { - InstanceID instanceID = null; - for (InstanceID i : getInstanceIDs()) { - if (i.getId().equals(id)) { - instanceID = i; - } - } - if (instanceID == null) { - instanceID = new InstanceID(id); - getInstanceIDs().add(instanceID); - } - - Iterator it = instanceID.getValues().iterator(); - while (it.hasNext()) { - EventedValue existingEv = it.next(); - if (existingEv.getClass().equals(ev.getClass())) { - it.remove(); - } - } - instanceID.getValues().add(ev); - } - - public EV getEventedValue(UnsignedIntegerFourBytes id, Class type) { - for (InstanceID instanceID : getInstanceIDs()) { - if (instanceID.getId().equals(id)) { - for (EventedValue eventedValue : instanceID.getValues()) { - if (eventedValue.getClass().equals(type)) - return (EV) eventedValue; - } - } - } - return null; - } - - public boolean hasChanges() { - for (InstanceID instanceID : instanceIDs) { - if (instanceID.getValues().size() > 0) return true; - } - return false; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValue.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValue.java deleted file mode 100644 index b21e192..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValue.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.support.shared.AbstractMap; - -import java.util.Map; - -public abstract class EventedValue { - - final protected V value; - - public EventedValue(V value) { - this.value = value; - } - - public EventedValue(Map.Entry[] attributes) { - try { - this.value = valueOf(attributes); - } catch (InvalidValueException ex) { - throw new RuntimeException(ex); - } - } - - public String getName() { - return getClass().getSimpleName(); - } - - public V getValue() { - return value; - } - - public Map.Entry[] getAttributes() { - return new Map.Entry[] { - new AbstractMap.SimpleEntry<>("val", toString()) - }; - } - - protected V valueOf(Map.Entry[] attributes) throws InvalidValueException { - V v = null; - for (Map.Entry attribute : attributes) { - if (attribute.getKey().equals("val")) v = valueOf(attribute.getValue()); - } - return v; - } - - protected V valueOf(String s) throws InvalidValueException { - return (V)getDatatype().valueOf(s); - } - - @Override - public String toString() { - return getDatatype().getString(getValue()); - } - - abstract protected Datatype getDatatype(); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueEnum.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueEnum.java deleted file mode 100644 index 0fccb65..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueEnum.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public abstract class EventedValueEnum extends EventedValue { - - public EventedValueEnum(E e) { - super(e); - } - - public EventedValueEnum(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected E valueOf(String s) throws InvalidValueException { - return enumValueOf(s); - } - - protected abstract E enumValueOf(String s); - - @Override - public String toString() { - return getValue().name(); - } - - @Override - protected Datatype getDatatype() { - return null; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueEnumArray.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueEnumArray.java deleted file mode 100644 index e9e16fe..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueEnumArray.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public abstract class EventedValueEnumArray extends EventedValue { - - public EventedValueEnumArray(E[] e) { - super(e); - } - - public EventedValueEnumArray(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected E[] valueOf(String s) throws InvalidValueException { - return enumValueOf(ModelUtil.fromCommaSeparatedList(s)); - } - - protected abstract E[] enumValueOf(String[] names); - - @Override - public String toString() { - return ModelUtil.toCommaSeparatedList(getValue()); - } - - @Override - protected Datatype getDatatype() { - return null; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueShort.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueShort.java deleted file mode 100644 index 59347a8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueShort.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.Datatype; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class EventedValueShort extends EventedValue { - - public EventedValueShort(Short value) { - super(value); - } - - public EventedValueShort(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected Datatype getDatatype() { - return Datatype.Builtin.I2_SHORT.getDatatype(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueString.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueString.java deleted file mode 100644 index 08b3bcf..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueString.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.Datatype; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class EventedValueString extends EventedValue { - - public EventedValueString(String value) { - super(value); - } - - public EventedValueString(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected Datatype getDatatype() { - return Datatype.Builtin.STRING.getDatatype(); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueURI.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueURI.java deleted file mode 100644 index 16b0b9f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueURI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; -import org.seamless.util.Exceptions; - -import java.net.URI; -import java.util.Map; -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public class EventedValueURI extends EventedValue { - - final private static Logger log = Logger.getLogger(EventedValueURI.class.getName()); - - public EventedValueURI(URI value) { - super(value); - } - - public EventedValueURI(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected URI valueOf(String s) throws InvalidValueException { - try { - // These URIs are really defined as 'string' datatype in AVTransport1.0.pdf, but we can try - // to parse whatever devices give us, like the Roku which sends "unknown url". - return super.valueOf(s); - } catch (InvalidValueException ex) { - log.info("Ignoring invalid URI in evented value '" + s +"': " + Exceptions.unwrap(ex)); - return null; - } - } - - @Override - protected Datatype getDatatype() { - return Datatype.Builtin.URI.getDatatype(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueUnsignedIntegerFourBytes.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueUnsignedIntegerFourBytes.java deleted file mode 100644 index c7d53a4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueUnsignedIntegerFourBytes.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class EventedValueUnsignedIntegerFourBytes extends EventedValue { - - public EventedValueUnsignedIntegerFourBytes(UnsignedIntegerFourBytes value) { - super(value); - } - - public EventedValueUnsignedIntegerFourBytes(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected Datatype getDatatype() { - return Datatype.Builtin.UI4.getDatatype(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueUnsignedIntegerTwoBytes.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueUnsignedIntegerTwoBytes.java deleted file mode 100644 index faac490..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/EventedValueUnsignedIntegerTwoBytes.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class EventedValueUnsignedIntegerTwoBytes extends EventedValue { - - public EventedValueUnsignedIntegerTwoBytes(UnsignedIntegerTwoBytes value) { - super(value); - } - - public EventedValueUnsignedIntegerTwoBytes(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected Datatype getDatatype() { - return Datatype.Builtin.UI2.getDatatype(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/InstanceID.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/InstanceID.java deleted file mode 100644 index b6592dc..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/InstanceID.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class InstanceID { - - protected UnsignedIntegerFourBytes id; - protected List values = new ArrayList<>(); - - public InstanceID(UnsignedIntegerFourBytes id) { - this(id, new ArrayList()); - } - - public InstanceID(UnsignedIntegerFourBytes id, List values) { - this.id = id; - this.values = values; - } - - public UnsignedIntegerFourBytes getId() { - return id; - } - - public List getValues() { - return values; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChange.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChange.java deleted file mode 100644 index 1fb5f2b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChange.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.beans.PropertyChangeSupport; -import java.util.ArrayList; -import java.util.List; - -/** - * Collects all state changes per logical instance. - *

- * This class is supposed to be used on a UPnP state variable field, - * on a RenderingControl or AVTransport service. The service then - * sets evented values whenever its state changes, and periodically - * (e.g. in a background loop) fires the "LastChange" XML content - * through its PropertyChangeSupport. (Where the ServiceManager picks - * it up and sends it to all subscribers.) - *

- *

- * The event subscriber can use this class to marshall the "LastChange" - * content, when the event XML is received. - *

- *

- * This class is thread-safe. - *

- * - * @author Christian Bauer - */ -public class LastChange { - - final private Event event; - final private LastChangeParser parser; - private String previousValue; - - public LastChange(String s) { - throw new UnsupportedOperationException("This constructor is only for service binding detection"); - } - - public LastChange(LastChangeParser parser, Event event) { - this.parser = parser; - this.event = event; - } - - public LastChange(LastChangeParser parser) { - this(parser, new Event()); - } - - public LastChange(LastChangeParser parser, String xml) throws Exception { - if (xml != null && xml.length() > 0) { - this.event = parser.parse(xml); - } else { - this.event = new Event(); - } - this.parser = parser; - } - - synchronized public void reset() { - previousValue = toString(); - event.clear(); - } - - synchronized public void setEventedValue(int instanceID, EventedValue... ev) { - setEventedValue(new UnsignedIntegerFourBytes(instanceID), ev); - } - - synchronized public void setEventedValue(UnsignedIntegerFourBytes instanceID, EventedValue... ev) { - for (EventedValue eventedValue : ev) { - if (eventedValue != null) - event.setEventedValue(instanceID, eventedValue); - - } - } - - synchronized public UnsignedIntegerFourBytes[] getInstanceIDs() { - List list = new ArrayList<>(); - for (InstanceID instanceID : event.getInstanceIDs()) { - list.add(instanceID.getId()); - } - return list.toArray(new UnsignedIntegerFourBytes[list.size()]); - } - - synchronized EventedValue[] getEventedValues(UnsignedIntegerFourBytes instanceID) { - InstanceID inst = event.getInstanceID(instanceID); - return inst != null ? inst.getValues().toArray(new EventedValue[inst.getValues().size()]) : null; - } - - synchronized public EV getEventedValue(int instanceID, Class type) { - return getEventedValue(new UnsignedIntegerFourBytes(instanceID), type); - } - - synchronized public EV getEventedValue(UnsignedIntegerFourBytes id, Class type) { - return event.getEventedValue(id, type); - } - - synchronized public void fire(PropertyChangeSupport propertyChangeSupport) { - String lastChanges = toString(); - if (lastChanges != null && lastChanges.length() > 0) { - propertyChangeSupport.firePropertyChange("LastChange", previousValue, lastChanges); - reset(); - } - } - - @Override - synchronized public String toString() { - if (!event.hasChanges()) return ""; - try { - return parser.generate(event); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeAwareServiceManager.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeAwareServiceManager.java deleted file mode 100644 index a699252..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeAwareServiceManager.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.DefaultServiceManager; -import org.fourthline.cling.model.meta.LocalService; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.state.StateVariableValue; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * Handles the "initial" event state for GENA subscriptions to services using LastChange. - *

- * When a GENA subscription is made on your AVTransport/RenderingControl service, you have to - * read the initial state of the service. Ususally Cling would do this for you and simply - * access all the state variables of your service behind the scenes. But the - * AVTransport/RenderingControl service doesn't use regular UPnP state variable eventing - * internally, they rely on the awful "LastChange" mechanism for their "logical" instances. - *

- *

- * Use this {@link org.fourthline.cling.model.ServiceManager} instead of the default one for - * these services. - *

- * - * @author Christian Bauer - */ -public class LastChangeAwareServiceManager extends DefaultServiceManager { - - final protected LastChangeParser lastChangeParser; - - public LastChangeAwareServiceManager(LocalService localService, - LastChangeParser lastChangeParser) { - this(localService, null, lastChangeParser); - } - - public LastChangeAwareServiceManager(LocalService localService, - Class serviceClass, - LastChangeParser lastChangeParser) { - super(localService, serviceClass); - this.lastChangeParser = lastChangeParser; - } - - protected LastChangeParser getLastChangeParser() { - return lastChangeParser; - } - - /** - * Call this method to propagate all accumulated "LastChange" values to GENA subscribers. - */ - public void fireLastChange() { - - // We need to obtain locks in the right order to avoid deadlocks: - // 1. The lock() of the DefaultServiceManager - // 2. The monitor/synchronized of the LastChange.fire() method - - lock(); - try { - getImplementation().getLastChange().fire(getPropertyChangeSupport()); - } finally { - unlock(); - } - } - - @Override - protected Collection readInitialEventedStateVariableValues() throws Exception { - - // We don't use the service's internal LastChange but a fresh new one just for - // this initial event. Modifying the internal one would trigger event notification's - // to other subscribers! - LastChange lc = new LastChange(getLastChangeParser()); - - // Get the current "logical" instances of the service - UnsignedIntegerFourBytes[] ids = getImplementation().getCurrentInstanceIds(); - if (ids.length > 0) { - for (UnsignedIntegerFourBytes instanceId : ids) { - // Iterate through all "logical" instances and ask them what their state is - getImplementation().appendCurrentState(lc, instanceId); - } - } else { - // Use the default "logical" instance with ID 0 - getImplementation().appendCurrentState(lc, new UnsignedIntegerFourBytes(0)); - } - - // Sum it all up and return it in the initial event to the GENA subscriber - StateVariable variable = getService().getStateVariable("LastChange"); - Collection values = new ArrayList<>(); - values.add(new StateVariableValue(variable, lc.toString())); - return values; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeDelegator.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeDelegator.java deleted file mode 100644 index 8503c34..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeDelegator.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -/** - * Any service implementation using the "LastChange" mechanism. - *

- * Required by the {@link LastChangeAwareServiceManager} to handle state readouts - * of "LastChange"-using services for initial events GENA subscriptions. If you - * want a specification compliant AVTransport or RenderingControl - * UPnP service, your service implementation should implement this interface as well. - *

- * - * @author Christian Bauer - */ -public interface LastChangeDelegator { - - public LastChange getLastChange(); - - public void appendCurrentState(LastChange lc, UnsignedIntegerFourBytes instanceId) throws Exception; - - public abstract UnsignedIntegerFourBytes[] getCurrentInstanceIds(); - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeParser.java b/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeParser.java deleted file mode 100644 index a62e2fd..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/lastchange/LastChangeParser.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.lastchange; - -import static org.fourthline.cling.model.XMLUtil.appendNewElement; - -import java.io.InputStream; -import java.io.StringReader; -import java.lang.reflect.Constructor; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.xml.parsers.DocumentBuilderFactory; - -import org.fourthline.cling.model.XMLUtil; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.shared.AbstractMap; -import org.seamless.util.io.IO; -import org.seamless.util.Exceptions; -import org.seamless.xml.DOMParser; -import org.seamless.xml.SAXParser; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -/** - * Reads and writes the "LastChange" XML content. - *

- * Validates against a schema if the {@link #getSchemaSources()} method - * doesn't return null. - *

- *

- * Note: This is broken on most devices and with most services out in the wild. In fact, - * you might want to use polling the service with actions, to get its status, instead of - * GENA. Polling can be expensive on low-power control points, however. - *

- * - * @author Christian Bauer - */ -public abstract class LastChangeParser extends SAXParser { - - final private static Logger log = Logger.getLogger(LastChangeParser.class.getName()); - - public enum CONSTANTS { - Event, - InstanceID, - val; - - public boolean equals(String s) { - return this.name().equals(s); - } - } - - abstract protected String getNamespace(); - - protected Set> getEventedVariables() { - return Collections.EMPTY_SET; - } - - protected EventedValue createValue(String name, Map.Entry[] attributes) throws Exception { - for (Class evType : getEventedVariables()) { - if (evType.getSimpleName().equals(name)) { - Constructor ctor = evType.getConstructor(Map.Entry[].class); - return ctor.newInstance(new Object[]{attributes}); - } - } - return null; - } - - /** - * Uses the current thread's context classloader to read and unmarshall the given resource. - * - * @param resource The resource on the classpath. - * @return The unmarshalled Event model. - * @throws Exception - */ - public Event parseResource(String resource) throws Exception { - InputStream is = null; - try { - is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource); - return parse(IO.readLines(is)); - } finally { - if (is != null) is.close(); - } - } - - public Event parse(String xml) throws Exception { - - if (xml == null || xml.length() == 0) { - throw new RuntimeException("Null or empty XML"); - } - - Event event = new Event(); - new RootHandler(event, this); - - if (log.isLoggable(Level.FINE)) { - log.fine("Parsing 'LastChange' event XML content"); - log.fine("===================================== 'LastChange' BEGIN ============================================"); - log.fine(xml); - log.fine("====================================== 'LastChange' END ============================================"); - } - parse(new InputSource(new StringReader(xml))); - - log.fine("Parsed event with instances IDs: " + event.getInstanceIDs().size()); - if (log.isLoggable(Level.FINEST)) { - for (InstanceID instanceID : event.getInstanceIDs()) { - log.finest("InstanceID '" + instanceID.getId() + "' has values: " + instanceID.getValues().size()); - for (EventedValue eventedValue : instanceID.getValues()) { - log.finest(eventedValue.getName() + " => " + eventedValue.getValue()); - } - } - } - - return event; - } - - class RootHandler extends SAXParser.Handler { - - RootHandler(Event instance, SAXParser parser) { - super(instance, parser); - } - - RootHandler(Event instance) { - super(instance); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - super.startElement(uri, localName, qName, attributes); - if (CONSTANTS.InstanceID.equals(localName)) { - String valAttr = attributes.getValue(CONSTANTS.val.name()); - if (valAttr != null) { - InstanceID instanceID = new InstanceID(new UnsignedIntegerFourBytes(valAttr)); - getInstance().getInstanceIDs().add(instanceID); - new InstanceIDHandler(instanceID, this); - } - } - } - } - - class InstanceIDHandler extends SAXParser.Handler { - - InstanceIDHandler(InstanceID instance, SAXParser.Handler parent) { - super(instance, parent); - } - - @Override - public void startElement(String uri, String localName, String qName, final Attributes attributes) throws SAXException { - super.startElement(uri, localName, qName, attributes); - Map.Entry[] attributeMap = new Map.Entry[attributes.getLength()]; - for (int i = 0; i < attributeMap.length; i++) { - attributeMap[i] = - new AbstractMap.SimpleEntry<>( - attributes.getLocalName(i), - attributes.getValue(i) - ); - } - try { - EventedValue esv = createValue(localName, attributeMap); - if (esv != null) - getInstance().getValues().add(esv); - } catch (Exception ex) { - // Don't exit, just log a warning - log.warning("Error reading event XML, ignoring value: " + Exceptions.unwrap(ex)); - } - } - - @Override - protected boolean isLastElement(String uri, String localName, String qName) { - return CONSTANTS.InstanceID.equals(localName); - } - } - - public String generate(Event event) throws Exception { - return XMLUtil.documentToFragmentString(buildDOM(event)); - } - - protected Document buildDOM(Event event) throws Exception { - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - - Document d = factory.newDocumentBuilder().newDocument(); - generateRoot(event, d); - - return d; - } - - protected void generateRoot(Event event, Document descriptor) { - Element eventElement = descriptor.createElementNS(getNamespace(), CONSTANTS.Event.name()); - descriptor.appendChild(eventElement); - generateInstanceIDs(event, descriptor, eventElement); - } - - protected void generateInstanceIDs(Event event, Document descriptor, Element rootElement) { - for (InstanceID instanceID : event.getInstanceIDs()) { - if (instanceID.getId() == null) continue; - Element instanceIDElement = appendNewElement(descriptor, rootElement, CONSTANTS.InstanceID.name()); - instanceIDElement.setAttribute(CONSTANTS.val.name(), instanceID.getId().toString()); - - for (EventedValue eventedValue : instanceID.getValues()) { - generateEventedValue(eventedValue, descriptor, instanceIDElement); - } - } - } - - protected void generateEventedValue(EventedValue eventedValue, Document descriptor, Element parentElement) { - String name = eventedValue.getName(); - Map.Entry[] attributes = eventedValue.getAttributes(); - if (attributes != null && attributes.length > 0) { - Element evElement = appendNewElement(descriptor, parentElement, name); - for (Map.Entry attr : attributes) { - evElement.setAttribute(attr.getKey(), DOMParser.escape(attr.getValue())); - } - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/AddMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/AddMessage.java deleted file mode 100644 index 4d5d45f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/AddMessage.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.support.messagebox.model.Message; -import org.seamless.util.MimeType; - -/** - * @author Christian Bauer - */ -public abstract class AddMessage extends ActionCallback { - - final protected MimeType mimeType = MimeType.valueOf("text/xml;charset=\"utf-8\""); - - public AddMessage(Service service, Message message) { - super(new ActionInvocation(service.getAction("AddMessage"))); - - getActionInvocation().setInput("MessageID", Integer.toString(message.getId())); - getActionInvocation().setInput("MessageType", mimeType.toString()); - getActionInvocation().setInput("Message", message.toString()); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/RemoveMessage.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/RemoveMessage.java deleted file mode 100644 index b94661a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/RemoveMessage.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.support.messagebox.model.Message; - -/** - * ATTENTION: My Samsung TV does not implement this! - * - * @author Christian Bauer - */ -public abstract class RemoveMessage extends ActionCallback { - - public RemoveMessage(Service service, Message message) { - this(service, message.getId()); - } - - public RemoveMessage(Service service, int id) { - super(new ActionInvocation(service.getAction("RemoveMessage"))); - getActionInvocation().setInput("MessageID", id); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/DateTime.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/DateTime.java deleted file mode 100644 index 0780178..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/DateTime.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox.model; - -import org.fourthline.cling.support.messagebox.parser.MessageElement; - -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * @author Christian Bauer - */ -public class DateTime implements ElementAppender { - - final private String date; - final private String time; - - public DateTime() { - this(getCurrentDate(), getCurrentTime()); - } - - public DateTime(String date, String time) { - this.date = date; - this.time = time; - } - - public String getDate() { - return date; - } - - public String getTime() { - return time; - } - - public void appendMessageElements(MessageElement parent) { - parent.createChild("Date").setContent(getDate()); - parent.createChild("Time").setContent(getTime()); - } - - public static String getCurrentDate() { - SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd"); - return fmt.format(new Date()); - } - - public static String getCurrentTime() { - SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss"); - return fmt.format(new Date()); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/ElementAppender.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/ElementAppender.java deleted file mode 100644 index 9f5d63b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/ElementAppender.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox.model; - -import org.fourthline.cling.support.messagebox.parser.MessageElement; - -/** - * @author Christian Bauer - */ -public interface ElementAppender { - - public void appendMessageElements(MessageElement parent); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/Message.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/Message.java deleted file mode 100644 index 1bc6335..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/Message.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox.model; - -import org.fourthline.cling.support.messagebox.parser.MessageDOM; -import org.fourthline.cling.support.messagebox.parser.MessageDOMParser; -import org.fourthline.cling.support.messagebox.parser.MessageElement; -import org.seamless.xml.ParserException; - -import java.util.Random; - -/** - * https://sourceforge.net/apps/mediawiki/samygo/index.php?title=MessageBoxService_request_format - * - * @author Christian Bauer - */ -public abstract class Message implements ElementAppender { - - final protected Random randomGenerator = new Random(); - - public enum Category { - SMS("SMS"), - INCOMING_CALL("Incoming Call"), - SCHEDULE_REMINDER("Schedule Reminder"); - - public String text; - - Category(String text) { - this.text = text; - } - } - - public enum DisplayType { - - MINIMUM("Minimum"), - MAXIMUM("Maximum"); - - public String text; - - DisplayType(String text) { - this.text = text; - } - } - - private final int id; - private final Category category; - private DisplayType displayType; - - public Message(Category category, DisplayType displayType) { - this(0, category, displayType); - } - - public Message(int id, Category category, DisplayType displayType) { - if (id == 0) id = randomGenerator.nextInt(Integer.MAX_VALUE); - this.id = id; - this.category = category; - this.displayType = displayType; - } - - public int getId() { - return id; - } - - public Category getCategory() { - return category; - } - - public DisplayType getDisplayType() { - return displayType; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Message message = (Message) o; - - if (id != message.id) return false; - - return true; - } - - @Override - public int hashCode() { - return id; - } - - @Override - public String toString() { - try { - MessageDOMParser mp = new MessageDOMParser(); - MessageDOM dom = mp.createDocument(); - - MessageElement root = dom.createRoot(mp.createXPath(), "Message"); - root.createChild("Category").setContent(getCategory().text); - root.createChild("DisplayType").setContent(getDisplayType().text); - appendMessageElements(root); - - String s = mp.print(dom, 0, false); - - // Cut the root element, what we send to the TV is not really XML, just - // random element soup which I'm sure the Samsung guys think is XML... - return s.replaceAll("", "") - .replaceAll("", ""); - - - } catch (ParserException ex) { - throw new RuntimeException(ex); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageIncomingCall.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageIncomingCall.java deleted file mode 100644 index 59e3b3d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageIncomingCall.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox.model; - -import org.fourthline.cling.support.messagebox.parser.MessageElement; - -/** - * @author Christian Bauer - */ -public class MessageIncomingCall extends Message { - - final private DateTime callTime; - final private NumberName callee; - final private NumberName caller; - - public MessageIncomingCall(NumberName callee, NumberName caller) { - this(new DateTime(), callee, caller); - } - - public MessageIncomingCall(DateTime callTime, NumberName callee, NumberName caller) { - this(DisplayType.MAXIMUM, callTime, callee, caller); - } - - public MessageIncomingCall(DisplayType displayType, DateTime callTime, NumberName callee, NumberName caller) { - super(Category.INCOMING_CALL, displayType); - this.callTime = callTime; - this.callee = callee; - this.caller = caller; - } - - public DateTime getCallTime() { - return callTime; - } - - public NumberName getCallee() { - return callee; - } - - public NumberName getCaller() { - return caller; - } - - public void appendMessageElements(MessageElement parent) { - getCallTime().appendMessageElements(parent.createChild("CallTime")); - getCallee().appendMessageElements(parent.createChild("Callee")); - getCaller().appendMessageElements(parent.createChild("Caller")); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageSMS.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageSMS.java deleted file mode 100644 index 1a6cea0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageSMS.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox.model; - -import org.fourthline.cling.support.messagebox.parser.MessageElement; - -/** - * Sender and body will only be displayed if display type is set to "Maximum". - * - * @author Christian Bauer - */ -public class MessageSMS extends Message { - - final private DateTime receiveTime; - final private NumberName receiver; - final private NumberName sender; - final private String body; - - public MessageSMS(NumberName receiver, NumberName sender, String body) { - this(new DateTime(), receiver, sender, body); - } - - public MessageSMS(DateTime receiveTime, NumberName receiver, NumberName sender, String body) { - this(Message.DisplayType.MAXIMUM, receiveTime, receiver, sender, body); - } - - public MessageSMS(DisplayType displayType, DateTime receiveTime, NumberName receiver, NumberName sender, String body) { - super(Message.Category.SMS, displayType); - this.receiveTime = receiveTime; - this.receiver = receiver; - this.sender = sender; - this.body = body; - } - - public DateTime getReceiveTime() { - return receiveTime; - } - - public NumberName getReceiver() { - return receiver; - } - - public NumberName getSender() { - return sender; - } - - public String getBody() { - return body; - } - - public void appendMessageElements(MessageElement parent) { - getReceiveTime().appendMessageElements(parent.createChild("ReceiveTime")); - getReceiver().appendMessageElements(parent.createChild("Receiver")); - getSender().appendMessageElements(parent.createChild("Sender")); - parent.createChild("Body").setContent(getBody()); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageScheduleReminder.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageScheduleReminder.java deleted file mode 100644 index 6af2c14..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/MessageScheduleReminder.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox.model; - -import org.fourthline.cling.support.messagebox.parser.MessageElement; - -/** - * @author Christian Bauer - */ -public class MessageScheduleReminder extends Message { - - final private DateTime startTime; - final private NumberName owner; - final private String subject; - final private DateTime endTime; - final private String location; - final private String body; - - public MessageScheduleReminder(DateTime startTime, NumberName owner, String subject, - DateTime endTime, String location, String body) { - this(DisplayType.MAXIMUM, startTime, owner, subject, endTime, location, body); - } - - public MessageScheduleReminder(DisplayType displayType, DateTime startTime, NumberName owner, String subject, - DateTime endTime, String location, String body) { - super(Category.SCHEDULE_REMINDER, displayType); - this.startTime = startTime; - this.owner = owner; - this.subject = subject; - this.endTime = endTime; - this.location = location; - this.body = body; - } - - public DateTime getStartTime() { - return startTime; - } - - public NumberName getOwner() { - return owner; - } - - public String getSubject() { - return subject; - } - - public DateTime getEndTime() { - return endTime; - } - - public String getLocation() { - return location; - } - - public String getBody() { - return body; - } - - public void appendMessageElements(MessageElement parent) { - getStartTime().appendMessageElements(parent.createChild("StartTime")); - getOwner().appendMessageElements(parent.createChild("Owner")); - parent.createChild("Subject").setContent(getSubject()); - getEndTime().appendMessageElements(parent.createChild("EndTime")); - parent.createChild("Location").setContent(getLocation()); - parent.createChild("Body").setContent(getBody()); - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/NumberName.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/NumberName.java deleted file mode 100644 index f7d6edb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/model/NumberName.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox.model; - -import org.fourthline.cling.support.messagebox.parser.MessageElement; - -/** - * @author Christian Bauer - */ -public class NumberName implements ElementAppender { - - private String number; - private String name; - - public NumberName(String number, String name) { - this.number = number; - this.name = name; - } - - public String getNumber() { - return number; - } - - public String getName() { - return name; - } - - public void appendMessageElements(MessageElement parent) { - parent.createChild("Number").setContent(getNumber()); - parent.createChild("Name").setContent(getName()); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageDOM.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageDOM.java deleted file mode 100644 index d2319e2..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageDOM.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox.parser; - -import org.seamless.xml.DOM; -import org.w3c.dom.Document; - -import javax.xml.xpath.XPath; - -/** - * @author Christian Bauer - */ -public class MessageDOM extends DOM { - - public static final String NAMESPACE_URI = "urn:samsung-com:messagebox-1-0"; - - public MessageDOM(Document dom) { - super(dom); - } - - @Override - public String getRootElementNamespace() { - return NAMESPACE_URI; - } - - @Override - public MessageElement getRoot(XPath xPath) { - return new MessageElement(xPath, getW3CDocument().getDocumentElement()); - } - - @Override - public MessageDOM copy() { - return new MessageDOM((Document) getW3CDocument().cloneNode(true)); - } - - public MessageElement createRoot(XPath xpath, String element) { - super.createRoot(element); - return getRoot(xpath); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageDOMParser.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageDOMParser.java deleted file mode 100644 index 3a316f3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageDOMParser.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox.parser; - -import org.seamless.xml.DOMParser; -import org.seamless.xml.NamespaceContextMap; -import org.w3c.dom.Document; - -import javax.xml.xpath.XPath; - -/** - * @author Christian Bauer - */ -public class MessageDOMParser extends DOMParser { - - @Override - protected MessageDOM createDOM(Document document) { - return new MessageDOM(document); - } - - public NamespaceContextMap createDefaultNamespaceContext(String... optionalPrefixes) { - NamespaceContextMap ctx = new NamespaceContextMap() { - @Override - protected String getDefaultNamespaceURI() { - return MessageDOM.NAMESPACE_URI; - } - }; - for (String optionalPrefix : optionalPrefixes) { - ctx.put(optionalPrefix, MessageDOM.NAMESPACE_URI); - } - return ctx; - } - - public XPath createXPath() { - return super.createXPath(createDefaultNamespaceContext(MessageElement.XPATH_PREFIX)); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageElement.java b/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageElement.java deleted file mode 100644 index 95ef11a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/messagebox/parser/MessageElement.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.messagebox.parser; - -import org.seamless.xml.DOMElement; -import org.w3c.dom.Element; - -import javax.xml.xpath.XPath; - -/** - * @author Christian Bauer - */ -public class MessageElement extends DOMElement { - - public static final String XPATH_PREFIX = "m"; - - public MessageElement(XPath xpath, Element element) { - super(xpath, element); - } - - @Override - protected String prefix(String localName) { - return XPATH_PREFIX + ":" + localName; - } - - @Override - protected Builder createParentBuilder(DOMElement el) { - return new Builder(el) { - @Override - public MessageElement build(Element element) { - return new MessageElement(getXpath(), element); - } - }; - } - - @Override - protected ArrayBuilder createChildBuilder(DOMElement el) { - return new ArrayBuilder(el) { - @Override - public MessageElement[] newChildrenArray(int length) { - return new MessageElement[length]; - } - - @Override - public MessageElement build(Element element) { - return new MessageElement(getXpath(), element); - } - }; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/AVTransport.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/AVTransport.java deleted file mode 100644 index e3e953c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/AVTransport.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.lastchange.LastChange; - -/** - * State of one logical instance of the AV Transport service. - * - * @author Christian Bauer - */ -public class AVTransport { - - final protected UnsignedIntegerFourBytes instanceID; - final protected LastChange lastChange; - protected MediaInfo mediaInfo; - protected TransportInfo transportInfo; - protected PositionInfo positionInfo; - protected DeviceCapabilities deviceCapabilities; - protected TransportSettings transportSettings; - - public AVTransport(UnsignedIntegerFourBytes instanceID, LastChange lastChange, StorageMedium possiblePlayMedium) { - this(instanceID, lastChange, new StorageMedium[]{possiblePlayMedium}); - } - - public AVTransport(UnsignedIntegerFourBytes instanceID, LastChange lastChange, StorageMedium[] possiblePlayMedia) { - this.instanceID = instanceID; - this.lastChange = lastChange; - setDeviceCapabilities(new DeviceCapabilities(possiblePlayMedia)); - setMediaInfo(new MediaInfo()); - setTransportInfo(new TransportInfo()); - setPositionInfo(new PositionInfo()); - setTransportSettings(new TransportSettings()); - } - - public UnsignedIntegerFourBytes getInstanceId() { - return instanceID; - } - - public LastChange getLastChange() { - return lastChange; - } - - public MediaInfo getMediaInfo() { - return mediaInfo; - } - - public void setMediaInfo(MediaInfo mediaInfo) { - this.mediaInfo = mediaInfo; - } - - public TransportInfo getTransportInfo() { - return transportInfo; - } - - public void setTransportInfo(TransportInfo transportInfo) { - this.transportInfo = transportInfo; - } - - public PositionInfo getPositionInfo() { - return positionInfo; - } - - public void setPositionInfo(PositionInfo positionInfo) { - this.positionInfo = positionInfo; - } - - public DeviceCapabilities getDeviceCapabilities() { - return deviceCapabilities; - } - - public void setDeviceCapabilities(DeviceCapabilities deviceCapabilities) { - this.deviceCapabilities = deviceCapabilities; - } - - public TransportSettings getTransportSettings() { - return transportSettings; - } - - public void setTransportSettings(TransportSettings transportSettings) { - this.transportSettings = transportSettings; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/BrowseFlag.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/BrowseFlag.java deleted file mode 100644 index 631306f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/BrowseFlag.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * @author Alessio Gaeta - * @author Christian Bauer - */ -public enum BrowseFlag { - - METADATA("BrowseMetadata"), - DIRECT_CHILDREN("BrowseDirectChildren"); - - private String protocolString; - - BrowseFlag(String protocolString) { - this.protocolString = protocolString; - } - - @Override - public String toString() { - return protocolString; - } - - public static BrowseFlag valueOrNullOf(String s) { - for (BrowseFlag browseFlag : values()) { - if (browseFlag.toString().equals(s)) - return browseFlag; - } - return null; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/BrowseResult.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/BrowseResult.java deleted file mode 100644 index 825fcce..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/BrowseResult.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -/** - * @author Alessio Gaeta - * @author Christian Bauer - */ -public class BrowseResult { - - protected String result; - protected UnsignedIntegerFourBytes count; - protected UnsignedIntegerFourBytes totalMatches; - protected UnsignedIntegerFourBytes containerUpdateID; - - public BrowseResult(String result, UnsignedIntegerFourBytes count, - UnsignedIntegerFourBytes totalMatches, - UnsignedIntegerFourBytes containerUpdateID) { - this.result = result; - this.count = count; - this.totalMatches = totalMatches; - this.containerUpdateID = containerUpdateID; - } - - public BrowseResult(String result, long count, long totalMatches) { - this(result, count, totalMatches, 0); - } - - public BrowseResult(String result, long count, long totalMatches, long updatedId) { - this( - result, - new UnsignedIntegerFourBytes(count), - new UnsignedIntegerFourBytes(totalMatches), - new UnsignedIntegerFourBytes(updatedId) - ); - } - - public String getResult() { - return result; - } - - public UnsignedIntegerFourBytes getCount() { - return count; - } - - public long getCountLong() { - return count.getValue(); - } - - public UnsignedIntegerFourBytes getTotalMatches() { - return totalMatches; - } - - public long getTotalMatchesLong() { - return totalMatches.getValue(); - } - - public UnsignedIntegerFourBytes getContainerUpdateID() { - return containerUpdateID; - } - - public long getContainerUpdateIDLong() { - return containerUpdateID.getValue(); - } - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/Channel.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/Channel.java deleted file mode 100644 index ec71615..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/Channel.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * - */ -public enum Channel { - Master, - LF, - RF, - CF, - LFE, - LS, - RS, - LFC, - RFC, - SD, - SL, - SR, - T -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/Connection.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/Connection.java deleted file mode 100644 index 3f7cc7a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/Connection.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -/** - * @author Christian Bauer - */ -public class Connection { - - static public class StatusInfo { - - private Status status; - private long uptimeSeconds; - private Error lastError; - - public StatusInfo(Status status, UnsignedIntegerFourBytes uptime, Error lastError) { - this(status, uptime.getValue(), lastError); - } - - public StatusInfo(Status status, long uptimeSeconds, Error lastError) { - this.status = status; - this.uptimeSeconds = uptimeSeconds; - this.lastError = lastError; - } - - public Status getStatus() { - return status; - } - - public long getUptimeSeconds() { - return uptimeSeconds; - } - - public UnsignedIntegerFourBytes getUptime() { - return new UnsignedIntegerFourBytes(getUptimeSeconds()); - } - - public Error getLastError() { - return lastError; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - StatusInfo that = (StatusInfo) o; - - if (uptimeSeconds != that.uptimeSeconds) return false; - if (lastError != that.lastError) return false; - if (status != that.status) return false; - - return true; - } - - @Override - public int hashCode() { - int result = status.hashCode(); - result = 31 * result + (int) (uptimeSeconds ^ (uptimeSeconds >>> 32)); - result = 31 * result + lastError.hashCode(); - return result; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") " + getStatus(); - } - } - - public enum Type { - /** - * Valid connection types cannot be identified. - */ - Unconfigured, - - /** - * The Internet Gateway is an IP router between the LAN and the WAN connection. - */ - IP_Routed, - - /** - * The Internet Gateway is an Ethernet bridge between the LAN and the WAN connection. - */ - IP_Bridged - } - - public enum Status { - /** - * This value indicates that other variables in the service table are - * uninitialized or in an invalid state. - */ - Unconfigured, - - /** - * The WANConnectionDevice is in the process of initiating a connection - * for the first time after the connection became disconnected. - */ - Connecting, - - /** - * At least one client has successfully - * initiated an Internet connection using this instance. - */ - Connected, - - /** - * The connection is active (packets are allowed to flow - * through), but will transition to Disconnecting state after a certain period. - */ - PendingDisconnect, - - /** - * The WANConnectionDevice is in the process of terminating a connection. - * On successful termination, ConnectionStatus transitions to Disconnected. - */ - Disconnecting, - - /** - * No ISP connection is active (or being activated) from this connection - * instance. No packets are transiting the gateway. - */ - Disconnected - } - - public enum Error { - ERROR_NONE, - ERROR_COMMAND_ABORTED, - ERROR_NOT_ENABLED_FOR_INTERNET, - ERROR_USER_DISCONNECT, - ERROR_ISP_DISCONNECT, - ERROR_IDLE_DISCONNECT, - ERROR_FORCED_DISCONNECT, - ERROR_NO_CARRIER, - ERROR_IP_CONFIGURATION, - ERROR_UNKNOWN - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/ConnectionInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/ConnectionInfo.java deleted file mode 100644 index fd0b9fb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/ConnectionInfo.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.ServiceReference; - -/** - * Immutable type encapsulating the state of a single connection. - * - * @author Alessio Gaeta - * @author Christian Bauer - */ -public class ConnectionInfo { - - public enum Status { - OK, - ContentFormatMismatch, - InsufficientBandwidth, - UnreliableChannel, - Unknown - } - - public enum Direction { - Output, - Input; - - public Direction getOpposite() { - return this.equals(Output) ? Input : Output; - } - - } - - final protected int connectionID; - - final protected int rcsID; - final protected int avTransportID; - - final protected ProtocolInfo protocolInfo; - - final protected ServiceReference peerConnectionManager; - final protected int peerConnectionID; - - final protected Direction direction; - protected Status connectionStatus = Status.Unknown; - - /** - * Creates a default instance with values expected for the default connection ID "0". - *

- * The ConnectionManager 1.0 specification says: - *

- *

- * If optional action PrepareForConnection is not implemented then (limited) connection - * information can be retrieved for ConnectionID 0. The device should return all known - * information: - *

- *
    - *
  • RcsID should be 0 or -1
  • - *
  • AVTransportID should be 0 or -1
  • - *
  • ProtocolInfo should contain accurate information if it is known, otherwhise - * it should be NULL (empty string)
  • - *
  • PeerConnectionManager should be NULL (empty string)
  • - *
  • PeerConnectionID should be -1
  • - *
  • Direction should be Input or Output
  • - *
  • Status should be OK or Unknown
  • - *
- */ - public ConnectionInfo() { - this(0, 0, 0, null, null, -1, Direction.Input, Status.Unknown); - } - - - public ConnectionInfo(int connectionID, - int rcsID, int avTransportID, - ProtocolInfo protocolInfo, - ServiceReference peerConnectionManager, int peerConnectionID, - Direction direction, Status connectionStatus) { - this.connectionID = connectionID; - this.rcsID = rcsID; - this.avTransportID = avTransportID; - this.protocolInfo = protocolInfo; - this.peerConnectionManager = peerConnectionManager; - this.peerConnectionID = peerConnectionID; - this.direction = direction; - this.connectionStatus = connectionStatus; - } - - public int getConnectionID() { - return connectionID; - } - - public int getRcsID() { - return rcsID; - } - - public int getAvTransportID() { - return avTransportID; - } - - public ProtocolInfo getProtocolInfo() { - return protocolInfo; - } - - public ServiceReference getPeerConnectionManager() { - return peerConnectionManager; - } - - public int getPeerConnectionID() { - return peerConnectionID; - } - - public Direction getDirection() { - return direction; - } - - synchronized public Status getConnectionStatus() { - return connectionStatus; - } - - synchronized public void setConnectionStatus(Status connectionStatus) { - this.connectionStatus = connectionStatus; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ConnectionInfo that = (ConnectionInfo) o; - - if (avTransportID != that.avTransportID) return false; - if (connectionID != that.connectionID) return false; - if (peerConnectionID != that.peerConnectionID) return false; - if (rcsID != that.rcsID) return false; - if (connectionStatus != that.connectionStatus) return false; - if (direction != that.direction) return false; - if (peerConnectionManager != null ? !peerConnectionManager.equals(that.peerConnectionManager) : that.peerConnectionManager != null) - return false; - if (protocolInfo != null ? !protocolInfo.equals(that.protocolInfo) : that.protocolInfo != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = connectionID; - result = 31 * result + rcsID; - result = 31 * result + avTransportID; - result = 31 * result + (protocolInfo != null ? protocolInfo.hashCode() : 0); - result = 31 * result + (peerConnectionManager != null ? peerConnectionManager.hashCode() : 0); - result = 31 * result + peerConnectionID; - result = 31 * result + direction.hashCode(); - result = 31 * result + connectionStatus.hashCode(); - return result; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") ID: " + getConnectionID() + ", Status: " + getConnectionStatus(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLAttribute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLAttribute.java deleted file mode 100644 index 1116907..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLAttribute.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * - * @author Christian Bauer - * @author Mario Franco - */ -public class DIDLAttribute { - - private String namespaceURI; - private String prefix; - private String value; - - public DIDLAttribute(String namespaceURI, String prefix, String value) { - this.namespaceURI = namespaceURI; - this.prefix = prefix; - this.value = value; - } - /** - * @return the namespaceURI - */ - public String getNamespaceURI() { - return namespaceURI; - } - - /** - * @return the prefix - */ - public String getPrefix() { - return prefix; - } - - /** - * @return the value - */ - public String getValue() { - return value; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLContent.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLContent.java deleted file mode 100644 index 7885bab..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLContent.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.support.model.container.Album; -import org.fourthline.cling.support.model.container.Container; -import org.fourthline.cling.support.model.container.GenreContainer; -import org.fourthline.cling.support.model.container.MovieGenre; -import org.fourthline.cling.support.model.container.MusicAlbum; -import org.fourthline.cling.support.model.container.MusicArtist; -import org.fourthline.cling.support.model.container.MusicGenre; -import org.fourthline.cling.support.model.container.PersonContainer; -import org.fourthline.cling.support.model.container.PhotoAlbum; -import org.fourthline.cling.support.model.container.PlaylistContainer; -import org.fourthline.cling.support.model.container.StorageFolder; -import org.fourthline.cling.support.model.container.StorageSystem; -import org.fourthline.cling.support.model.container.StorageVolume; -import org.fourthline.cling.support.model.item.AudioBook; -import org.fourthline.cling.support.model.item.AudioBroadcast; -import org.fourthline.cling.support.model.item.AudioItem; -import org.fourthline.cling.support.model.item.ImageItem; -import org.fourthline.cling.support.model.item.Item; -import org.fourthline.cling.support.model.item.Movie; -import org.fourthline.cling.support.model.item.MusicTrack; -import org.fourthline.cling.support.model.item.MusicVideoClip; -import org.fourthline.cling.support.model.item.Photo; -import org.fourthline.cling.support.model.item.PlaylistItem; -import org.fourthline.cling.support.model.item.TextItem; -import org.fourthline.cling.support.model.item.VideoBroadcast; -import org.fourthline.cling.support.model.item.VideoItem; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class DIDLContent { - - public static final String NAMESPACE_URI = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"; - public static final String DESC_WRAPPER_NAMESPACE_URI = "urn:fourthline-org:cling:support:content-directory-desc-1-0"; - - protected List containers = new ArrayList<>(); - protected List items = new ArrayList<>(); - protected List descMetadata = new ArrayList<>(); - - public Container getFirstContainer() { - return getContainers().get(0); - } - - public DIDLContent addContainer(Container container) { - getContainers().add(container); - return this; - } - - public List getContainers() { - return containers; - } - - public void setContainers(List containers) { - this.containers = containers; - } - - /** - * Adds {@link Item} or {@link Container} typed instances, ignores everything else. - */ - public DIDLContent addObject(Object object) { - if(object instanceof Item) { - addItem((Item)object); - } else if(object instanceof Container) { - addContainer((Container)object); - } - return this; - } - - public DIDLContent addItem(Item item) { - getItems().add(item); - return this; - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } - - public DIDLContent addDescMetadata(DescMeta descMetadata) { - getDescMetadata().add(descMetadata); - return this; - } - - public List getDescMetadata() { - return descMetadata; - } - - public void setDescMetadata(List descMetadata) { - this.descMetadata = descMetadata; - } - - public void replaceGenericContainerAndItems() { - setItems(replaceGenericItems(getItems())); - setContainers(replaceGenericContainers(getContainers())); - } - - protected List replaceGenericItems(List genericItems) { - List specificItems = new ArrayList<>(); - - for (Item genericItem : genericItems) { - String genericType = genericItem.getClazz().getValue(); - - if (AudioItem.CLASS.getValue().equals(genericType)) { - specificItems.add(new AudioItem(genericItem)); - } else if (MusicTrack.CLASS.getValue().equals(genericType)) { - specificItems.add(new MusicTrack(genericItem)); - } else if (AudioBook.CLASS.getValue().equals(genericType)) { - specificItems.add(new AudioBook(genericItem)); - } else if (AudioBroadcast.CLASS.getValue().equals(genericType)) { - specificItems.add(new AudioBroadcast(genericItem)); - - } else if (VideoItem.CLASS.getValue().equals(genericType)) { - specificItems.add(new VideoItem(genericItem)); - } else if (Movie.CLASS.getValue().equals(genericType)) { - specificItems.add(new Movie(genericItem)); - } else if (VideoBroadcast.CLASS.getValue().equals(genericType)) { - specificItems.add(new VideoBroadcast(genericItem)); - } else if (MusicVideoClip.CLASS.getValue().equals(genericType)) { - specificItems.add(new MusicVideoClip(genericItem)); - - } else if (ImageItem.CLASS.getValue().equals(genericType)) { - specificItems.add(new ImageItem(genericItem)); - } else if (Photo.CLASS.getValue().equals(genericType)) { - specificItems.add(new Photo(genericItem)); - - } else if (PlaylistItem.CLASS.getValue().equals(genericType)) { - specificItems.add(new PlaylistItem(genericItem)); - - } else if (TextItem.CLASS.getValue().equals(genericType)) { - specificItems.add(new TextItem(genericItem)); - - } else { - specificItems.add(genericItem); - } - } - - return specificItems; - } - - protected List replaceGenericContainers(List genericContainers) { - List specificContainers = new ArrayList<>(); - - for (Container genericContainer : genericContainers) { - String genericType = genericContainer.getClazz().getValue(); - - Container specific; - - if (Album.CLASS.getValue().equals(genericType)) { - specific = new Album(genericContainer); - - } else if (MusicAlbum.CLASS.getValue().equals(genericType)) { - specific = new MusicAlbum(genericContainer); - - } else if (PhotoAlbum.CLASS.getValue().equals(genericType)) { - specific = new PhotoAlbum(genericContainer); - - } else if (GenreContainer.CLASS.getValue().equals(genericType)) { - specific = new GenreContainer(genericContainer); - - } else if (MusicGenre.CLASS.getValue().equals(genericType)) { - specific = new MusicGenre(genericContainer); - - } else if (MovieGenre.CLASS.getValue().equals(genericType)) { - specific = new MovieGenre(genericContainer); - - } else if (PlaylistContainer.CLASS.getValue().equals(genericType)) { - specific = new PlaylistContainer(genericContainer); - - } else if (PersonContainer.CLASS.getValue().equals(genericType)) { - specific = new PersonContainer(genericContainer); - - } else if (MusicArtist.CLASS.getValue().equals(genericType)) { - specific = new MusicArtist(genericContainer); - - } else if (StorageSystem.CLASS.getValue().equals(genericType)) { - specific = new StorageSystem(genericContainer); - - } else if (StorageVolume.CLASS.getValue().equals(genericType)) { - specific = new StorageVolume(genericContainer); - - } else if (StorageFolder.CLASS.getValue().equals(genericType)) { - specific = new StorageFolder(genericContainer); - - } else { - specific = genericContainer; - } - - specific.setItems(replaceGenericItems(genericContainer.getItems())); - specificContainers.add(specific); - } - - return specificContainers; - } - - public long getCount() { - return items.size() + containers.size(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLObject.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLObject.java deleted file mode 100644 index 188e383..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/DIDLObject.java +++ /dev/null @@ -1,898 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.w3c.dom.Element; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; - -/** - * @author Christian Bauer - * @author Mario Franco - */ -public abstract class DIDLObject { - - static public abstract class Property { - - public interface NAMESPACE { - } - - private V value; - final private String descriptorName; - final private List> attributes = new ArrayList<>(); - - protected Property() { - this(null, null); - } - - protected Property(String descriptorName) { - this(null, descriptorName); - } - - protected Property(V value, String descriptorName) { - this.value = value; - // TODO Not sure this is a good fix for https://github.com/4thline/cling/issues/62 - this.descriptorName = descriptorName == null - ? getClass().getSimpleName().toLowerCase(Locale.ROOT).replace("didlobject$property$upnp$", "") - : descriptorName; - } - - protected Property(V value, String descriptorName, List> attributes) { - this.value = value; - // TODO Not sure this is a good fix for https://github.com/4thline/cling/issues/62 - this.descriptorName = descriptorName == null - ? getClass().getSimpleName().toLowerCase(Locale.ROOT).replace("didlobject$property$upnp$", "") - : descriptorName; - this.attributes.addAll(attributes); - } - - public V getValue() { - return value; - } - - public void setValue(V value) { - this.value = value; - } - - public String getDescriptorName() { - return descriptorName; - } - - public void setOnElement(Element element) { - element.setTextContent(toString()); - for (Property attr : attributes) { - element.setAttributeNS( - attr.getValue().getNamespaceURI(), - attr.getValue().getPrefix() + ':' + attr.getDescriptorName(), - attr.getValue().getValue()); - } - } - - public void addAttribute(Property attr) { - this.attributes.add(attr); - } - - public void removeAttribute(Property attr) { - this.attributes.remove(attr); - } - - public void removeAttribute(String descriptorName) { - for (Property attr : attributes) { - if (attr.getDescriptorName().equals(descriptorName)) { - this.removeAttribute(attr); - break; - } - } - } - - public Property getAttribute(String descriptorName) { - for (Property attr : attributes) { - if (attr.getDescriptorName().equals(descriptorName)) { - return attr; - } - } - return null; - } - - @Override - public String toString() { - return getValue() != null ? getValue().toString() : ""; - } - - static public class PropertyPersonWithRole extends Property { - - public PropertyPersonWithRole() { - } - - public PropertyPersonWithRole(String descriptorName) { - super(descriptorName); - } - - public PropertyPersonWithRole(PersonWithRole value, String descriptorName) { - super(value, descriptorName); - } - - @Override - public void setOnElement(Element element) { - if (getValue() != null) - getValue().setOnElement(element); - } - } - - static public class DC { - - public interface NAMESPACE extends Property.NAMESPACE { - public static final String URI = "http://purl.org/dc/elements/1.1/"; - } - - static public class DESCRIPTION extends Property implements NAMESPACE { - public DESCRIPTION() { - } - - public DESCRIPTION(String value) { - super(value, null); - } - } - - static public class PUBLISHER extends Property implements NAMESPACE { - public PUBLISHER() { - } - - public PUBLISHER(Person value) { - super(value, null); - } - } - - static public class CONTRIBUTOR extends Property implements NAMESPACE { - public CONTRIBUTOR() { - } - - public CONTRIBUTOR(Person value) { - super(value, null); - } - } - - static public class DATE extends Property implements NAMESPACE { - public DATE() { - } - - public DATE(String value) { - super(value, null); - } - } - - static public class LANGUAGE extends Property implements NAMESPACE { - public LANGUAGE() { - } - - public LANGUAGE(String value) { - super(value, null); - } - } - - static public class RELATION extends Property implements NAMESPACE { - public RELATION() { - } - - public RELATION(URI value) { - super(value, null); - } - } - - static public class RIGHTS extends Property implements NAMESPACE { - public RIGHTS() { - } - - public RIGHTS(String value) { - super(value, null); - } - } - } - - static public abstract class SEC { - - public interface NAMESPACE extends Property.NAMESPACE { - public static final String URI = "http://www.sec.co.kr/"; - } - - static public class CAPTIONINFOEX extends Property implements NAMESPACE { - public CAPTIONINFOEX() { - this(null); - } - - public CAPTIONINFOEX(URI value) { - super(value, "CaptionInfoEx"); - } - - public CAPTIONINFOEX(URI value, List> attributes) { - super(value, "CaptionInfoEx", attributes); - } - } - - static public class CAPTIONINFO extends Property implements NAMESPACE { - public CAPTIONINFO() { - this(null); - } - - public CAPTIONINFO(URI value) { - super(value, "CaptionInfo"); - } - - public CAPTIONINFO(URI value, List> attributes) { - super(value, "CaptionInfo", attributes); - } - } - - static public class TYPE extends Property implements NAMESPACE { - public TYPE() { - this(null); - } - - public TYPE(DIDLAttribute value) { - super(value, "type"); - } - } - - - } - - static public abstract class UPNP { - - public interface NAMESPACE extends Property.NAMESPACE { - public static final String URI = "urn:schemas-upnp-org:metadata-1-0/upnp/"; - } - - static public class ARTIST extends PropertyPersonWithRole implements NAMESPACE { - public ARTIST() { - } - - public ARTIST(PersonWithRole value) { - super(value, null); - } - } - - static public class ACTOR extends PropertyPersonWithRole implements NAMESPACE { - public ACTOR() { - } - - public ACTOR(PersonWithRole value) { - super(value, null); - } - } - - static public class AUTHOR extends PropertyPersonWithRole implements NAMESPACE { - public AUTHOR() { - } - - public AUTHOR(PersonWithRole value) { - super(value, null); - } - } - - static public class PRODUCER extends Property implements NAMESPACE { - public PRODUCER() { - } - - public PRODUCER(Person value) { - super(value, null); - } - } - - static public class DIRECTOR extends Property implements NAMESPACE { - public DIRECTOR() { - } - - public DIRECTOR(Person value) { - super(value, null); - } - } - - static public class GENRE extends Property implements NAMESPACE { - public GENRE() { - } - - public GENRE(String value) { - super(value, null); - } - } - - static public class ALBUM extends Property implements NAMESPACE { - public ALBUM() { - } - - public ALBUM(String value) { - super(value, null); - } - } - - static public class PLAYLIST extends Property implements NAMESPACE { - public PLAYLIST() { - } - - public PLAYLIST(String value) { - super(value, null); - } - } - - static public class REGION extends Property implements NAMESPACE { - public REGION() { - } - - public REGION(String value) { - super(value, null); - } - } - - static public class RATING extends Property implements NAMESPACE { - public RATING() { - } - - public RATING(String value) { - super(value, null); - } - } - - static public class TOC extends Property implements NAMESPACE { - public TOC() { - } - - public TOC(String value) { - super(value, null); - } - } - - static public class ALBUM_ART_URI extends Property implements NAMESPACE { - public ALBUM_ART_URI() { - this(null); - } - - public ALBUM_ART_URI(URI value) { - super(value, "albumArtURI"); - } - - public ALBUM_ART_URI(URI value, List> attributes) { - super(value, "albumArtURI", attributes); - } - } - - static public class ARTIST_DISCO_URI extends Property implements NAMESPACE { - public ARTIST_DISCO_URI() { - this(null); - } - - public ARTIST_DISCO_URI(URI value) { - super(value, "artistDiscographyURI"); - } - } - - static public class LYRICS_URI extends Property implements NAMESPACE { - public LYRICS_URI() { - this(null); - } - - public LYRICS_URI(URI value) { - super(value, "lyricsURI"); - } - } - - static public class STORAGE_TOTAL extends Property implements NAMESPACE { - public STORAGE_TOTAL() { - this(null); - } - - public STORAGE_TOTAL(Long value) { - super(value, "storageTotal"); - } - } - - static public class STORAGE_USED extends Property implements NAMESPACE { - public STORAGE_USED() { - this(null); - } - - public STORAGE_USED(Long value) { - super(value, "storageUsed"); - } - } - - static public class STORAGE_FREE extends Property implements NAMESPACE { - public STORAGE_FREE() { - this(null); - } - - public STORAGE_FREE(Long value) { - super(value, "storageFree"); - } - } - - static public class STORAGE_MAX_PARTITION extends Property implements NAMESPACE { - public STORAGE_MAX_PARTITION() { - this(null); - } - - public STORAGE_MAX_PARTITION(Long value) { - super(value, "storageMaxPartition"); - } - } - - static public class STORAGE_MEDIUM extends Property implements NAMESPACE { - public STORAGE_MEDIUM() { - this(null); - } - - public STORAGE_MEDIUM(StorageMedium value) { - super(value, "storageMedium"); - } - } - - static public class LONG_DESCRIPTION extends Property implements NAMESPACE { - public LONG_DESCRIPTION() { - this(null); - } - - public LONG_DESCRIPTION(String value) { - super(value, "longDescription"); - } - } - - static public class ICON extends Property implements NAMESPACE { - public ICON() { - this(null); - } - - public ICON(URI value) { - super(value, "icon"); - } - } - - static public class RADIO_CALL_SIGN extends Property implements NAMESPACE { - public RADIO_CALL_SIGN() { - this(null); - } - - public RADIO_CALL_SIGN(String value) { - super(value, "radioCallSign"); - } - } - - static public class RADIO_STATION_ID extends Property implements NAMESPACE { - public RADIO_STATION_ID() { - this(null); - } - - public RADIO_STATION_ID(String value) { - super(value, "radioStationID"); - } - } - - static public class RADIO_BAND extends Property implements NAMESPACE { - public RADIO_BAND() { - this(null); - } - - public RADIO_BAND(String value) { - super(value, "radioBand"); - } - } - - static public class CHANNEL_NR extends Property implements NAMESPACE { - public CHANNEL_NR() { - this(null); - } - - public CHANNEL_NR(Integer value) { - super(value, "channelNr"); - } - } - - static public class CHANNEL_NAME extends Property implements NAMESPACE { - public CHANNEL_NAME() { - this(null); - } - - public CHANNEL_NAME(String value) { - super(value, "channelName"); - } - } - - static public class SCHEDULED_START_TIME extends Property implements NAMESPACE { - public SCHEDULED_START_TIME() { - this(null); - } - - public SCHEDULED_START_TIME(String value) { - super(value, "scheduledStartTime"); - } - } - - static public class SCHEDULED_END_TIME extends Property implements NAMESPACE { - public SCHEDULED_END_TIME() { - this(null); - } - - public SCHEDULED_END_TIME(String value) { - super(value, "scheduledEndTime"); - } - } - - static public class DVD_REGION_CODE extends Property implements NAMESPACE { - public DVD_REGION_CODE() { - this(null); - } - - public DVD_REGION_CODE(Integer value) { - super(value, "DVDRegionCode"); - } - } - - static public class ORIGINAL_TRACK_NUMBER extends Property implements NAMESPACE { - public ORIGINAL_TRACK_NUMBER() { - this(null); - } - - public ORIGINAL_TRACK_NUMBER(Integer value) { - super(value, "originalTrackNumber"); - } - } - - - static public class USER_ANNOTATION extends Property implements NAMESPACE { - public USER_ANNOTATION() { - this(null); - } - - public USER_ANNOTATION(String value) { - super(value, "userAnnotation"); - } - } - } - - static public abstract class DLNA { - - public interface NAMESPACE extends Property.NAMESPACE { - public static final String URI = "urn:schemas-dlna-org:metadata-1-0/"; - } - - static public class PROFILE_ID extends Property implements NAMESPACE { - public PROFILE_ID() { - this(null); - } - - public PROFILE_ID(DIDLAttribute value) { - super(value, "profileID"); - } - } - } - } - - public static class Class { - - protected String value; - protected String friendlyName; - protected boolean includeDerived; - - public Class() { - } - - public Class(String value) { - this.value = value; - } - - public Class(String value, String friendlyName) { - this.value = value; - this.friendlyName = friendlyName; - } - - public Class(String value, String friendlyName, boolean includeDerived) { - this.value = value; - this.friendlyName = friendlyName; - this.includeDerived = includeDerived; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getFriendlyName() { - return friendlyName; - } - - public void setFriendlyName(String friendlyName) { - this.friendlyName = friendlyName; - } - - public boolean isIncludeDerived() { - return includeDerived; - } - - public void setIncludeDerived(boolean includeDerived) { - this.includeDerived = includeDerived; - } - - public boolean equals(DIDLObject instance) { - return getValue().equals(instance.getClazz().getValue()); - - } - } - - protected String id; - protected String parentID; - - protected String title; // DC - protected String creator; // DC - - protected boolean restricted = true; // Let's just assume read-only is default - protected WriteStatus writeStatus; // UPNP - protected Class clazz; // UPNP - - protected List resources = new ArrayList<>(); - protected List properties = new ArrayList<>(); - - protected List descMetadata = new ArrayList<>(); - - protected DIDLObject() { - } - - protected DIDLObject(DIDLObject other) { - this(other.getId(), - other.getParentID(), - other.getTitle(), - other.getCreator(), - other.isRestricted(), - other.getWriteStatus(), - other.getClazz(), - other.getResources(), - other.getProperties(), - other.getDescMetadata() - ); - } - - protected DIDLObject(String id, String parentID, String title, String creator, boolean restricted, WriteStatus writeStatus, Class clazz, List resources, List properties, List descMetadata) { - this.id = id; - this.parentID = parentID; - this.title = title; - this.creator = creator; - this.restricted = restricted; - this.writeStatus = writeStatus; - this.clazz = clazz; - this.resources = resources; - this.properties = properties; - this.descMetadata = descMetadata; - } - - public String getId() { - return id; - } - - public DIDLObject setId(String id) { - this.id = id; - return this; - } - - public String getParentID() { - return parentID; - } - - public DIDLObject setParentID(String parentID) { - this.parentID = parentID; - return this; - } - - public String getTitle() { - return title; - } - - public DIDLObject setTitle(String title) { - this.title = title; - return this; - } - - public String getCreator() { - return creator; - } - - public DIDLObject setCreator(String creator) { - this.creator = creator; - return this; - } - - public boolean isRestricted() { - return restricted; - } - - public DIDLObject setRestricted(boolean restricted) { - this.restricted = restricted; - return this; - } - - public WriteStatus getWriteStatus() { - return writeStatus; - } - - public DIDLObject setWriteStatus(WriteStatus writeStatus) { - this.writeStatus = writeStatus; - return this; - } - - public Res getFirstResource() { - return getResources().size() > 0 ? getResources().get(0) : null; - } - - public List getResources() { - return resources; - } - - public DIDLObject setResources(List resources) { - this.resources = resources; - return this; - } - - public DIDLObject addResource(Res resource) { - getResources().add(resource); - return this; - } - - public Class getClazz() { - return clazz; - } - - public DIDLObject setClazz(Class clazz) { - this.clazz = clazz; - return this; - } - - public List getProperties() { - return properties; - } - - public DIDLObject setProperties(List properties) { - this.properties = properties; - return this; - } - - public DIDLObject addProperty(Property property) { - if (property == null) return this; - getProperties().add(property); - return this; - } - - public DIDLObject replaceFirstProperty(Property property) { - if (property == null) return this; - Iterator it = getProperties().iterator(); - while (it.hasNext()) { - Property p = it.next(); - if (p.getClass().isAssignableFrom(property.getClass())) - it.remove(); - } - addProperty(property); - return this; - } - - public DIDLObject replaceProperties(java.lang.Class propertyClass, Property[] properties) { - if (properties.length == 0) return this; - removeProperties(propertyClass); - return addProperties(properties); - } - - public DIDLObject addProperties(Property[] properties) { - if (properties == null) return this; - for (Property property : properties) { - addProperty(property); - } - return this; - } - - public DIDLObject removeProperties(java.lang.Class propertyClass) { - Iterator it = getProperties().iterator(); - while (it.hasNext()) { - Property property = it.next(); - if (propertyClass.isInstance(property)) - it.remove(); - } - return this; - } - - public boolean hasProperty(java.lang.Class propertyClass) { - for (Property property : getProperties()) { - if (propertyClass.isInstance(property)) return true; - } - return false; - } - - public Property getFirstProperty(java.lang.Class> propertyClass) { - for (Property property : getProperties()) { - if (propertyClass.isInstance(property)) return property; - } - return null; - } - - public Property getLastProperty(java.lang.Class> propertyClass) { - Property found = null; - for (Property property : getProperties()) { - if (propertyClass.isInstance(property)) found = property; - } - return found; - } - - public Property[] getProperties(java.lang.Class> propertyClass) { - List> list = new ArrayList<>(); - for (Property property : getProperties()) { - if (propertyClass.isInstance(property)) - list.add(property); - } - return list.toArray(new Property[list.size()]); - } - - public Property[] getPropertiesByNamespace(java.lang.Class namespace) { - List> list = new ArrayList<>(); - for (Property property : getProperties()) { - if (namespace.isInstance(property)) - list.add(property); - } - return list.toArray(new Property[list.size()]); - } - - public V getFirstPropertyValue(java.lang.Class> propertyClass) { - Property prop = getFirstProperty(propertyClass); - return prop == null ? null : prop.getValue(); - } - - public List getPropertyValues(java.lang.Class> propertyClass) { - List list = new ArrayList<>(); - for (Property property : getProperties(propertyClass)) { - list.add((V) property.getValue()); - } - return list; - } - - public List getDescMetadata() { - return descMetadata; - } - - public void setDescMetadata(List descMetadata) { - this.descMetadata = descMetadata; - } - - public DIDLObject addDescMetadata(DescMeta descMetadata) { - getDescMetadata().add(descMetadata); - return this; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - DIDLObject that = (DIDLObject) o; - - if (!id.equals(that.id)) return false; - - return true; - } - - @Override - public int hashCode() { - return id.hashCode(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/DescMeta.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/DescMeta.java deleted file mode 100644 index 3355c4d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/DescMeta.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import javax.xml.parsers.DocumentBuilderFactory; -import java.net.URI; - - -/** - * Descriptor metadata about an item/resource. - * - *
- * <complexType>
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <any namespace='##other'/>
- *       </sequence>
- *       <attribute name="id" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       <attribute name="type" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       <attribute name="nameSpace" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -public class DescMeta { - - protected String id; - protected String type; - protected URI nameSpace; - protected M metadata; - - public DescMeta() { - } - - public DescMeta(String id, String type, URI nameSpace, M metadata) { - this.id = id; - this.type = type; - this.nameSpace = nameSpace; - this.metadata = metadata; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public URI getNameSpace() { - return nameSpace; - } - - public void setNameSpace(URI nameSpace) { - this.nameSpace = nameSpace; - } - - public M getMetadata() { - return metadata; - } - - public void setMetadata(M metadata) { - this.metadata = metadata; - } - - public Document createMetadataDocument() { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - Document d = factory.newDocumentBuilder().newDocument(); - Element rootElement = d.createElementNS(DIDLContent.DESC_WRAPPER_NAMESPACE_URI, "desc-wrapper"); - d.appendChild(rootElement); - return d; - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/DeviceCapabilities.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/DeviceCapabilities.java deleted file mode 100644 index d0e88d0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/DeviceCapabilities.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.action.ActionArgumentValue; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class DeviceCapabilities { - - private StorageMedium[] playMedia; - private StorageMedium[] recMedia = new StorageMedium[] {StorageMedium.NOT_IMPLEMENTED}; - private RecordQualityMode[] recQualityModes = new RecordQualityMode[] {RecordQualityMode.NOT_IMPLEMENTED}; - - public DeviceCapabilities(Map args) { - this( - StorageMedium.valueOfCommaSeparatedList((String) args.get("PlayMedia").getValue()), - StorageMedium.valueOfCommaSeparatedList((String) args.get("RecMedia").getValue()), - RecordQualityMode.valueOfCommaSeparatedList((String) args.get("RecQualityModes").getValue()) - ); - } - - public DeviceCapabilities(StorageMedium[] playMedia) { - this.playMedia = playMedia; - } - - public DeviceCapabilities(StorageMedium[] playMedia, StorageMedium[] recMedia, RecordQualityMode[] recQualityModes) { - this.playMedia = playMedia; - this.recMedia = recMedia; - this.recQualityModes = recQualityModes; - } - - public StorageMedium[] getPlayMedia() { - return playMedia; - } - - public StorageMedium[] getRecMedia() { - return recMedia; - } - - public RecordQualityMode[] getRecQualityModes() { - return recQualityModes; - } - - public String getPlayMediaString() { - return ModelUtil.toCommaSeparatedList(playMedia); - } - - public String getRecMediaString() { - return ModelUtil.toCommaSeparatedList(recMedia); - } - - public String getRecQualityModesString() { - return ModelUtil.toCommaSeparatedList(recQualityModes); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/MediaInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/MediaInfo.java deleted file mode 100644 index 50a90e4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/MediaInfo.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.model.action.ActionArgumentValue; - -import java.util.Map; - -/** - * - */ -public class MediaInfo { - - private String currentURI = ""; - private String currentURIMetaData = ""; - private String nextURI = "NOT_IMPLEMENTED"; - private String nextURIMetaData = "NOT_IMPLEMENTED"; - - private UnsignedIntegerFourBytes numberOfTracks = new UnsignedIntegerFourBytes(0); - private String mediaDuration = "00:00:00"; - private StorageMedium playMedium = StorageMedium.NONE; - private StorageMedium recordMedium = StorageMedium.NOT_IMPLEMENTED; - private RecordMediumWriteStatus writeStatus = RecordMediumWriteStatus.NOT_IMPLEMENTED; - - public MediaInfo() { - } - - public MediaInfo(Map args) { - this( - (String) args.get("CurrentURI").getValue(), - (String) args.get("CurrentURIMetaData").getValue(), - (String) args.get("NextURI").getValue(), - (String) args.get("NextURIMetaData").getValue(), - - (UnsignedIntegerFourBytes) args.get("NrTracks").getValue(), - (String) args.get("MediaDuration").getValue(), - StorageMedium.valueOrVendorSpecificOf((String) args.get("PlayMedium").getValue()), - StorageMedium.valueOrVendorSpecificOf((String) args.get("RecordMedium").getValue()), - RecordMediumWriteStatus.valueOrUnknownOf((String) args.get("WriteStatus").getValue()) - ); - } - - public MediaInfo(String currentURI, String currentURIMetaData) { - this.currentURI = currentURI; - this.currentURIMetaData = currentURIMetaData; - } - - public MediaInfo(String currentURI, String currentURIMetaData, - UnsignedIntegerFourBytes numberOfTracks, String mediaDuration, - StorageMedium playMedium) { - this.currentURI = currentURI; - this.currentURIMetaData = currentURIMetaData; - this.numberOfTracks = numberOfTracks; - this.mediaDuration = mediaDuration; - this.playMedium = playMedium; - } - - public MediaInfo(String currentURI, String currentURIMetaData, - UnsignedIntegerFourBytes numberOfTracks, String mediaDuration, - StorageMedium playMedium, - StorageMedium recordMedium, RecordMediumWriteStatus writeStatus) { - this.currentURI = currentURI; - this.currentURIMetaData = currentURIMetaData; - this.numberOfTracks = numberOfTracks; - this.mediaDuration = mediaDuration; - this.playMedium = playMedium; - this.recordMedium = recordMedium; - this.writeStatus = writeStatus; - } - - public MediaInfo(String currentURI, String currentURIMetaData, - String nextURI, String nextURIMetaData, - UnsignedIntegerFourBytes numberOfTracks, String mediaDuration, - StorageMedium playMedium) { - this.currentURI = currentURI; - this.currentURIMetaData = currentURIMetaData; - this.nextURI = nextURI; - this.nextURIMetaData = nextURIMetaData; - this.numberOfTracks = numberOfTracks; - this.mediaDuration = mediaDuration; - this.playMedium = playMedium; - } - - public MediaInfo(String currentURI, String currentURIMetaData, - String nextURI, String nextURIMetaData, - UnsignedIntegerFourBytes numberOfTracks, String mediaDuration, - StorageMedium playMedium, - StorageMedium recordMedium, RecordMediumWriteStatus writeStatus) { - this.currentURI = currentURI; - this.currentURIMetaData = currentURIMetaData; - this.nextURI = nextURI; - this.nextURIMetaData = nextURIMetaData; - this.numberOfTracks = numberOfTracks; - this.mediaDuration = mediaDuration; - this.playMedium = playMedium; - this.recordMedium = recordMedium; - this.writeStatus = writeStatus; - } - - public String getCurrentURI() { - return currentURI; - } - - public String getCurrentURIMetaData() { - return currentURIMetaData; - } - - public String getNextURI() { - return nextURI; - } - - public String getNextURIMetaData() { - return nextURIMetaData; - } - - public UnsignedIntegerFourBytes getNumberOfTracks() { - return numberOfTracks; - } - - public String getMediaDuration() { - return mediaDuration; - } - - public StorageMedium getPlayMedium() { - return playMedium; - } - - public StorageMedium getRecordMedium() { - return recordMedium; - } - - public RecordMediumWriteStatus getWriteStatus() { - return writeStatus; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/Person.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/Person.java deleted file mode 100644 index 185166c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/Person.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * @author Christian Bauer - */ -public class Person { - - private String name; - - public Person(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Person person = (Person) o; - - if (!name.equals(person.name)) return false; - - return true; - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public String toString() { - return getName(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/PersonWithRole.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/PersonWithRole.java deleted file mode 100644 index 84957c9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/PersonWithRole.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.w3c.dom.Element; - -/** - * @author Christian Bauer - */ -public class PersonWithRole extends Person { - - private String role; - - public PersonWithRole(String name) { - super(name); - } - - public PersonWithRole(String name, String role) { - super(name); - this.role = role; - } - - public String getRole() { - return role; - } - - public void setOnElement(Element element) { - element.setTextContent(toString()); - if(getRole() != null) { - element.setAttribute("role", getRole()); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/PlayMode.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/PlayMode.java deleted file mode 100644 index ddcb90f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/PlayMode.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * - */ -public enum PlayMode { - NORMAL, - SHUFFLE, - REPEAT_ONE, - REPEAT_ALL, - RANDOM, - DIRECT_1, - INTRO -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/PortMapping.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/PortMapping.java deleted file mode 100644 index ac00fef..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/PortMapping.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.action.ActionArgumentValue; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class PortMapping { - - public enum Protocol { - UDP, - TCP - } - - private boolean enabled; - private UnsignedIntegerFourBytes leaseDurationSeconds; - private String remoteHost; - private UnsignedIntegerTwoBytes externalPort; - private UnsignedIntegerTwoBytes internalPort; - private String internalClient; - private Protocol protocol; - private String description; - - public PortMapping() { - } - - - public PortMapping(Map> map) { - this( - (Boolean) map.get("NewEnabled").getValue(), - (UnsignedIntegerFourBytes) map.get("NewLeaseDuration").getValue(), - (String) map.get("NewRemoteHost").getValue(), - (UnsignedIntegerTwoBytes) map.get("NewExternalPort").getValue(), - (UnsignedIntegerTwoBytes) map.get("NewInternalPort").getValue(), - (String) map.get("NewInternalClient").getValue(), - Protocol.valueOf(map.get("NewProtocol").toString()), - (String) map.get("NewPortMappingDescription").getValue() - ); - } - - public PortMapping(int port, String internalClient, Protocol protocol) { - this( - true, - new UnsignedIntegerFourBytes(0), - null, - new UnsignedIntegerTwoBytes(port), - new UnsignedIntegerTwoBytes(port), - internalClient, - protocol, - null - ); - } - - public PortMapping(int port, String internalClient, Protocol protocol, String description) { - this( - true, - new UnsignedIntegerFourBytes(0), - null, - new UnsignedIntegerTwoBytes(port), - new UnsignedIntegerTwoBytes(port), - internalClient, - protocol, - description - ); - } - - public PortMapping(String remoteHost, UnsignedIntegerTwoBytes externalPort, Protocol protocol) { - this( - true, - new UnsignedIntegerFourBytes(0), - remoteHost, - externalPort, - null, - null, - protocol, - null - ); - } - - public PortMapping(boolean enabled, UnsignedIntegerFourBytes leaseDurationSeconds, String remoteHost, UnsignedIntegerTwoBytes externalPort, - UnsignedIntegerTwoBytes internalPort, String internalClient, Protocol protocol, String description) { - this.enabled = enabled; - this.leaseDurationSeconds = leaseDurationSeconds; - this.remoteHost = remoteHost; - this.externalPort = externalPort; - this.internalPort = internalPort; - this.internalClient = internalClient; - this.protocol = protocol; - this.description = description; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public UnsignedIntegerFourBytes getLeaseDurationSeconds() { - return leaseDurationSeconds; - } - - public void setLeaseDurationSeconds(UnsignedIntegerFourBytes leaseDurationSeconds) { - this.leaseDurationSeconds = leaseDurationSeconds; - } - - public boolean hasRemoteHost() { - return remoteHost != null && remoteHost.length() > 0; - } - - public String getRemoteHost() { - return remoteHost == null ? "-" : remoteHost; - } - - public void setRemoteHost(String remoteHost) { - this.remoteHost = remoteHost == null || remoteHost.equals("-") || remoteHost.length() == 0 ? null : remoteHost; - } - - public UnsignedIntegerTwoBytes getExternalPort() { - return externalPort; - } - - public void setExternalPort(UnsignedIntegerTwoBytes externalPort) { - this.externalPort = externalPort; - } - - public UnsignedIntegerTwoBytes getInternalPort() { - return internalPort; - } - - public void setInternalPort(UnsignedIntegerTwoBytes internalPort) { - this.internalPort = internalPort; - } - - public String getInternalClient() { - return internalClient; - } - - public void setInternalClient(String internalClient) { - this.internalClient = internalClient; - } - - public Protocol getProtocol() { - return protocol; - } - - public void setProtocol(Protocol protocol) { - this.protocol = protocol; - } - - public boolean hasDescription() { - return description != null; - } - - public String getDescription() { - return description == null ? "-" : description; - } - - public void setDescription(String description) { - this.description = description == null || description.equals("-") || description.length() == 0 ? null : description; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") Protocol: " + getProtocol() + ", " + getExternalPort() + " => " + getInternalClient(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/PositionInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/PositionInfo.java deleted file mode 100644 index b97172e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/PositionInfo.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.action.ActionArgumentValue; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class PositionInfo { - - private UnsignedIntegerFourBytes track = new UnsignedIntegerFourBytes(0); - private String trackDuration = "00:00:00"; - private String trackMetaData = "NOT_IMPLEMENTED"; - private String trackURI = ""; - private String relTime = "00:00:00"; - private String absTime = "00:00:00"; // TODO: MORE VALUES IN DOMAIN! - private int relCount = Integer.MAX_VALUE; // Indicates that we don't support this - private int absCount = Integer.MAX_VALUE; - - public PositionInfo() { - } - - public PositionInfo(Map args) { - this( - ((UnsignedIntegerFourBytes) args.get("Track").getValue()).getValue(), - (String) args.get("TrackDuration").getValue(), - (String) args.get("TrackMetaData").getValue(), - (String) args.get("TrackURI").getValue(), - (String) args.get("RelTime").getValue(), - (String) args.get("AbsTime").getValue(), - (Integer) args.get("RelCount").getValue(), - (Integer) args.get("AbsCount").getValue() - ); - } - - public PositionInfo(PositionInfo copy, String relTime, String absTime) { - this.track = copy.track; - this.trackDuration = copy.trackDuration; - this.trackMetaData = copy.trackMetaData; - this.trackURI = copy.trackURI; - this.relTime = relTime; - this.absTime = absTime; - this.relCount = copy.relCount; - this.absCount = copy.absCount; - } - - public PositionInfo(PositionInfo copy, long relTimeSeconds, long absTimeSeconds) { - this.track = copy.track; - this.trackDuration = copy.trackDuration; - this.trackMetaData = copy.trackMetaData; - this.trackURI = copy.trackURI; - this.relTime = ModelUtil.toTimeString(relTimeSeconds); - this.absTime = ModelUtil.toTimeString(absTimeSeconds); - this.relCount = copy.relCount; - this.absCount = copy.absCount; - } - - public PositionInfo(long track, String trackDuration, String trackURI, - String relTime, String absTime) { - this.track = new UnsignedIntegerFourBytes(track); - this.trackDuration = trackDuration; - this.trackURI = trackURI; - this.relTime = relTime; - this.absTime = absTime; - } - - public PositionInfo(long track, String trackDuration, - String trackMetaData, String trackURI, - String relTime, String absTime, int relCount, int absCount) { - this.track = new UnsignedIntegerFourBytes(track); - this.trackDuration = trackDuration; - this.trackMetaData = trackMetaData; - this.trackURI = trackURI; - this.relTime = relTime; - this.absTime = absTime; - this.relCount = relCount; - this.absCount = absCount; - } - - public PositionInfo(long track, String trackMetaData, String trackURI) { - this.track = new UnsignedIntegerFourBytes(track); - this.trackMetaData = trackMetaData; - this.trackURI = trackURI; - } - - public UnsignedIntegerFourBytes getTrack() { - return track; - } - - public String getTrackDuration() { - return trackDuration; - } - - public String getTrackMetaData() { - return trackMetaData; - } - - public String getTrackURI() { - return trackURI; - } - - public String getRelTime() { - return relTime; - } - - public String getAbsTime() { - return absTime; - } - - public int getRelCount() { - return relCount; - } - - public int getAbsCount() { - return absCount; - } - - public void setTrackDuration(String trackDuration) { - this.trackDuration = trackDuration; - } - - public void setRelTime(String relTime) { - this.relTime = relTime; - } - - public long getTrackDurationSeconds() { - return getTrackDuration() == null ? 0 : ModelUtil.fromTimeString(getTrackDuration()); - } - - public long getTrackElapsedSeconds() { - return getRelTime() == null || getRelTime().equals("NOT_IMPLEMENTED") ? 0 : ModelUtil.fromTimeString(getRelTime()); - } - - public long getTrackRemainingSeconds() { - return getTrackDurationSeconds() - getTrackElapsedSeconds(); - } - - public int getElapsedPercent() { - long elapsed = getTrackElapsedSeconds(); - long total = getTrackDurationSeconds(); - if (elapsed == 0 || total == 0) return 0; - return new Double(elapsed/((double)total/100)).intValue(); - } - - - @Override - public String toString() { - return "(PositionInfo) Track: " + getTrack() + " RelTime: " + getRelTime() + " Duration: " + getTrackDuration() + " Percent: " + getElapsedPercent(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/PresetName.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/PresetName.java deleted file mode 100644 index b5d00bc..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/PresetName.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * - */ -public enum PresetName { - FactoryDefaults -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/Protocol.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/Protocol.java deleted file mode 100644 index a53ed4e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/Protocol.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public enum Protocol { - - ALL(ProtocolInfo.WILDCARD), - HTTP_GET("http-get"), - RTSP_RTP_UDP("rtsp-rtp-udp"), - INTERNAL("internal"), - IEC61883("iec61883"), - XBMC_GET("xbmc-get"), - OTHER("other"); - - private static final Logger LOG = Logger.getLogger(Protocol.class.getName()); - - private String protocolString; - - Protocol(String protocolString) { - this.protocolString = protocolString; - } - - @Override - public String toString() { - return protocolString; - } - - public static Protocol value(String s) { - for (Protocol protocol : values()) { - if (protocol.toString().equals(s)) { - return protocol; - } - } - LOG.info("Unsupported OTHER protocol string: " + s); - return OTHER; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/ProtocolInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/ProtocolInfo.java deleted file mode 100644 index 27e9baf..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/ProtocolInfo.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.types.InvalidValueException; -import org.seamless.util.MimeType; - -/** - * Encaspulates a MIME type (content format) and transport, protocol, additional information. - * - * @author Christian Bauer - */ -public class ProtocolInfo { - - public static final String WILDCARD = "*"; - - protected Protocol protocol = Protocol.ALL; - protected String network = WILDCARD; - protected String contentFormat = WILDCARD; - protected String additionalInfo = WILDCARD; - - public ProtocolInfo(String s) throws InvalidValueException { - if (s == null) throw new NullPointerException(); - s = s.trim(); - String[] split = s.split(":"); - if (split.length != 4) { - throw new InvalidValueException("Can't parse ProtocolInfo string: " + s); - } - this.protocol = Protocol.value(split[0]); - this.network = split[1]; - this.contentFormat = split[2]; - this.additionalInfo = split[3]; - } - - public ProtocolInfo(MimeType contentFormatMimeType) { - this.protocol = Protocol.HTTP_GET; - this.contentFormat = contentFormatMimeType.toString(); - } - - public ProtocolInfo(Protocol protocol, String network, String contentFormat, String additionalInfo) { - this.protocol = protocol; - this.network = network; - this.contentFormat = contentFormat; - this.additionalInfo = additionalInfo; - } - - public Protocol getProtocol() { - return protocol; - } - - public String getNetwork() { - return network; - } - - public String getContentFormat() { - return contentFormat; - } - - public MimeType getContentFormatMimeType() throws IllegalArgumentException { - return MimeType.valueOf(contentFormat); - } - - public String getAdditionalInfo() { - return additionalInfo; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ProtocolInfo that = (ProtocolInfo) o; - - if (!additionalInfo.equals(that.additionalInfo)) return false; - if (!contentFormat.equals(that.contentFormat)) return false; - if (!network.equals(that.network)) return false; - if (protocol != that.protocol) return false; - - return true; - } - - @Override - public int hashCode() { - int result = protocol.hashCode(); - result = 31 * result + network.hashCode(); - result = 31 * result + contentFormat.hashCode(); - result = 31 * result + additionalInfo.hashCode(); - return result; - } - - @Override - public String toString() { - return protocol.toString() + ":" + - network + ":" + - contentFormat + ":" + - additionalInfo; - - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/ProtocolInfos.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/ProtocolInfos.java deleted file mode 100644 index f500ba5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/ProtocolInfos.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.types.InvalidValueException; - -import java.util.ArrayList; - -/** - * @author Christian Bauer - */ -public class ProtocolInfos extends ArrayList { - - public ProtocolInfos(ProtocolInfo... info) { - for (ProtocolInfo protocolInfo : info) { - add(protocolInfo); - } - } - - public ProtocolInfos(String s) throws InvalidValueException { - String[] infos = ModelUtil.fromCommaSeparatedList(s); - if (infos != null) - for (String info : infos) - add(new ProtocolInfo(info)); - } - - @Override - public String toString() { - return ModelUtil.toCommaSeparatedList(toArray(new ProtocolInfo[size()])); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/RecordMediumWriteStatus.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/RecordMediumWriteStatus.java deleted file mode 100644 index a15762e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/RecordMediumWriteStatus.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * - */ -public enum RecordMediumWriteStatus { - - WRITABLE, - PROTECTED, - NOT_WRITABLE, - UNKNOWN, - NOT_IMPLEMENTED; - - static public RecordMediumWriteStatus valueOrUnknownOf(String s) { - if (s == null) - return UNKNOWN; - try { - return valueOf(s); - } catch (IllegalArgumentException ex) { - return UNKNOWN; - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/RecordQualityMode.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/RecordQualityMode.java deleted file mode 100644 index 1262c50..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/RecordQualityMode.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.ModelUtil; - -import java.util.ArrayList; -import java.util.List; - -/** - * - */ -public enum RecordQualityMode { - - EP("0:EP"), - LP("1:LP"), - SP("2:SP"), - BASIC("0:BASIC"), - MEDIUM("1:MEDIUM"), - HIGH("2:HIGH"), - NOT_IMPLEMENTED("NOT_IMPLEMENTED"); - - private String protocolString; - - RecordQualityMode(String protocolString) { - this.protocolString = protocolString; - } - - @Override - public String toString() { - return protocolString; - } - - public static RecordQualityMode valueOrExceptionOf(String s) throws IllegalArgumentException { - for (RecordQualityMode recordQualityMode : values()) { - if (recordQualityMode.protocolString.equals(s)) { - return recordQualityMode; - } - } - throw new IllegalArgumentException("Invalid record quality mode string: " + s); - } - - public static RecordQualityMode[] valueOfCommaSeparatedList(String s) { - String[] strings = ModelUtil.fromCommaSeparatedList(s); - if (strings == null) return new RecordQualityMode[0]; - List result = new ArrayList<>(); - for (String rqm : strings) { - for (RecordQualityMode recordQualityMode : values()) { - if (recordQualityMode.protocolString.equals(rqm)) { - result.add(recordQualityMode); - } - } - } - return result.toArray(new RecordQualityMode[result.size()]); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/Res.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/Res.java deleted file mode 100644 index a868433..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/Res.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.seamless.util.MimeType; - -import java.net.URI; - -/** - * @author Christian Bauer - */ -public class Res { - - protected URI importUri; - protected ProtocolInfo protocolInfo; - protected Long size; - protected String duration; - protected Long bitrate; - protected Long sampleFrequency; - protected Long bitsPerSample; - protected Long nrAudioChannels; - protected Long colorDepth; - protected String protection; - protected String resolution; - - protected String value; - - public Res() { - } - - public Res(String httpGetMimeType, Long size, String duration, Long bitrate, String value) { - this(new ProtocolInfo(Protocol.HTTP_GET, ProtocolInfo.WILDCARD, httpGetMimeType, ProtocolInfo.WILDCARD), size, duration, bitrate, value); - } - - public Res(MimeType httpGetMimeType, Long size, String duration, Long bitrate, String value) { - this(new ProtocolInfo(httpGetMimeType), size, duration, bitrate, value); - } - - public Res(MimeType httpGetMimeType, Long size, String value) { - this(new ProtocolInfo(httpGetMimeType), size, value); - } - - public Res(ProtocolInfo protocolInfo, Long size, String value) { - this.protocolInfo = protocolInfo; - this.size = size; - this.value = value; - } - - public Res(ProtocolInfo protocolInfo, Long size, String duration, Long bitrate, String value) { - this.protocolInfo = protocolInfo; - this.size = size; - this.duration = duration; - this.bitrate = bitrate; - this.value = value; - } - - public Res(URI importUri, ProtocolInfo protocolInfo, Long size, String duration, Long bitrate, Long sampleFrequency, Long bitsPerSample, Long nrAudioChannels, Long colorDepth, String protection, String resolution, String value) { - this.importUri = importUri; - this.protocolInfo = protocolInfo; - this.size = size; - this.duration = duration; - this.bitrate = bitrate; - this.sampleFrequency = sampleFrequency; - this.bitsPerSample = bitsPerSample; - this.nrAudioChannels = nrAudioChannels; - this.colorDepth = colorDepth; - this.protection = protection; - this.resolution = resolution; - this.value = value; - } - - public URI getImportUri() { - return importUri; - } - - public void setImportUri(URI importUri) { - this.importUri = importUri; - } - - public ProtocolInfo getProtocolInfo() { - return protocolInfo; - } - - public void setProtocolInfo(ProtocolInfo protocolInfo) { - this.protocolInfo = protocolInfo; - } - - public Long getSize() { - return size; - } - - public void setSize(Long size) { - this.size = size; - } - - public String getDuration() { - return duration; - } - - public void setDuration(String duration) { - this.duration = duration; - } - - public Long getBitrate() { - return bitrate; - } - - public void setBitrate(Long bitrate) { - this.bitrate = bitrate; - } - - public Long getSampleFrequency() { - return sampleFrequency; - } - - public void setSampleFrequency(Long sampleFrequency) { - this.sampleFrequency = sampleFrequency; - } - - public Long getBitsPerSample() { - return bitsPerSample; - } - - public void setBitsPerSample(Long bitsPerSample) { - this.bitsPerSample = bitsPerSample; - } - - public Long getNrAudioChannels() { - return nrAudioChannels; - } - - public void setNrAudioChannels(Long nrAudioChannels) { - this.nrAudioChannels = nrAudioChannels; - } - - public Long getColorDepth() { - return colorDepth; - } - - public void setColorDepth(Long colorDepth) { - this.colorDepth = colorDepth; - } - - public String getProtection() { - return protection; - } - - public void setProtection(String protection) { - this.protection = protection; - } - - public String getResolution() { - return resolution; - } - - public void setResolution(String resolution) { - this.resolution = resolution; - } - - public void setResolution(int x, int y) { - this.resolution = x + "x" + y; - } - - public int getResolutionX() { - return getResolution() != null && getResolution().split("x").length == 2 - ? Integer.valueOf(getResolution().split("x")[0]) - : 0; - } - - public int getResolutionY() { - return getResolution() != null && getResolution().split("x").length == 2 - ? Integer.valueOf(getResolution().split("x")[1]) - : 0; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/SearchResult.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/SearchResult.java deleted file mode 100644 index f2ff19b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/SearchResult.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -/** - * @author TK Kocheran <rfkrocktk@gmail.com> - */ -public class SearchResult { - - protected String result; - - protected UnsignedIntegerFourBytes count; - - protected UnsignedIntegerFourBytes totalMatches; - - protected UnsignedIntegerFourBytes containerUpdateID; - - public SearchResult(String result, UnsignedIntegerFourBytes count, - UnsignedIntegerFourBytes totalMatches, - UnsignedIntegerFourBytes containerUpdateID) { - this.result = result; - this.count = count; - this.totalMatches = totalMatches; - this.containerUpdateID = containerUpdateID; - } - - public SearchResult(String result, long count, long totalMatches) { - this(result, count, totalMatches, 0); - } - - public SearchResult(String result, long count, long totalMatches, long updateID) { - this( - result, - new UnsignedIntegerFourBytes(count), - new UnsignedIntegerFourBytes(totalMatches), - new UnsignedIntegerFourBytes(updateID) - ); - } - - public String getResult() { - return result; - } - - public UnsignedIntegerFourBytes getCount() { - return count; - } - - public long getCountLong() { - return count.getValue(); - } - - public UnsignedIntegerFourBytes getTotalMatches() { - return totalMatches; - } - - public long getTotalMatchesLong() { - return totalMatches.getValue(); - } - - public UnsignedIntegerFourBytes getContainerUpdateID() { - return containerUpdateID; - } - - public long getContainerUpdateIDLong() { - return containerUpdateID.getValue(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/SeekMode.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/SeekMode.java deleted file mode 100644 index d37e9ec..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/SeekMode.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/* - ui4 (ABS_COUNT, REL_COUNT, TRACK_NR, TAPE-INDEX, FRAME) - time (ABS_TIME, REL_TIME) - float (CHANNEL_FREQ, in Hz) - */ -public enum SeekMode { - - TRACK_NR("TRACK_NR"), - ABS_TIME("ABS_TIME"), - REL_TIME("REL_TIME"), - ABS_COUNT("ABS_COUNT"), - REL_COUNT("REL_COUNT"), - CHANNEL_FREQ("CHANNEL_FREQ"), - TAPE_INDEX("TAPE-INDEX"), - FRAME("FRAME"); - - private String protocolString; - - SeekMode(String protocolString) { - this.protocolString = protocolString; - } - - @Override - public String toString() { - return protocolString; - } - - public static SeekMode valueOrExceptionOf(String s) throws IllegalArgumentException { - for (SeekMode seekMode : values()) { - if (seekMode.protocolString.equals(s)) { - return seekMode; - } - } - throw new IllegalArgumentException("Invalid seek mode string: " + s); - } -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/SortCriterion.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/SortCriterion.java deleted file mode 100644 index afc8068..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/SortCriterion.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class SortCriterion { - - final protected boolean ascending; - final protected String propertyName; - - public SortCriterion(boolean ascending, String propertyName) { - this.ascending = ascending; - this.propertyName = propertyName; - } - - public SortCriterion(String criterion) { - this(criterion.startsWith("+"), criterion.substring(1)); - if (!(criterion.startsWith("-") || criterion.startsWith("+"))) - throw new IllegalArgumentException("Missing sort prefix +/- on criterion: " + criterion); - } - - public boolean isAscending() { - return ascending; - } - - public String getPropertyName() { - return propertyName; - } - - public static SortCriterion[] valueOf(String s) { - if (s == null || s.length() == 0) return new SortCriterion[0]; - List list = new ArrayList<>(); - String[] criteria = s.split(","); - for (String criterion : criteria) { - list.add(new SortCriterion(criterion.trim())); - } - return list.toArray(new SortCriterion[list.size()]); - } - - public static String toString(SortCriterion[] criteria) { - if (criteria == null) return ""; - StringBuilder sb = new StringBuilder(); - for (SortCriterion sortCriterion : criteria) { - sb.append(sortCriterion.toString()).append(","); - } - if (sb.toString().endsWith(",")) sb.deleteCharAt(sb.length()-1); - return sb.toString(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(ascending ? "+" : "-"); - sb.append(propertyName); - return sb.toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/StorageMedium.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/StorageMedium.java deleted file mode 100644 index c083346..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/StorageMedium.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.ModelUtil; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author Christian Bauer - */ -public enum StorageMedium { - - UNKNOWN, - DV, - MINI_DV("MINI-DV"), - VHS, - W_VHS("W-VHS"), - S_VHS("S-VHS"), - D_VHS("D-VHS"), - VHSC, - VIDEO8, - HI8, - CD_ROM("CD-ROM"), - CD_DA("CD-DA"), - CD_R("CD-R"), - CD_RW("CD-RW"), - VIDEO_CD("VIDEO-CD"), - SACD, - MD_AUDIO("M-AUDIO"), - MD_PICTURE("MD-PICTURE"), - DVD_ROM("DVD-ROM"), - DVD_VIDEO("DVD-VIDEO"), - DVD_R("DVD-R"), - DVD_PLUS_RW("DVD+RW"), - DVD_MINUS_RW("DVD-RW"), - DVD_RAM("DVD-RAM"), - DVD_AUDIO("DVD-AUDIO"), - DAT, - LD, - HDD, - MICRO_MV("MICRO_MV"), - NETWORK, - NONE, - NOT_IMPLEMENTED, - VENDOR_SPECIFIC; - - private static Map byProtocolString = new HashMap() {{ - for (StorageMedium e : StorageMedium.values()) { - put(e.protocolString, e); - } - }}; - - private String protocolString; - - StorageMedium() { - this(null); - } - - StorageMedium(String protocolString) { - this.protocolString = protocolString == null ? this.name() : protocolString; - } - - @Override - public String toString() { - return protocolString; - } - - public static StorageMedium valueOrExceptionOf(String s) { - StorageMedium sm = byProtocolString.get(s); - if (sm != null) return sm; - throw new IllegalArgumentException("Invalid storage medium string: " + s); - } - - public static StorageMedium valueOrVendorSpecificOf(String s) { - StorageMedium sm = byProtocolString.get(s); - return sm != null ? sm : StorageMedium.VENDOR_SPECIFIC; - } - - public static StorageMedium[] valueOfCommaSeparatedList(String s) { - String[] strings = ModelUtil.fromCommaSeparatedList(s); - if (strings == null) return new StorageMedium[0]; - StorageMedium[] result = new StorageMedium[strings.length]; - for (int i = 0; i < strings.length; i++) { - result[i] = valueOrVendorSpecificOf(strings[i]); - } - return result; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportAction.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportAction.java deleted file mode 100644 index 0efdfe7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportAction.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.ModelUtil; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Christian Bauer - */ -public enum TransportAction { - - Play, - Stop, - Pause, - Seek, - Next, - Previous, - Record; - - public static TransportAction[] valueOfCommaSeparatedList(String s) { - String[] strings = ModelUtil.fromCommaSeparatedList(s); - if (strings == null) return new TransportAction[0]; - List result = new ArrayList<>(); - for (String taString : strings) { - for (TransportAction ta : values()) { - if (ta.name().equals(taString)) { - result.add(ta); - } - } - - } - return result.toArray(new TransportAction[result.size()]); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportInfo.java deleted file mode 100644 index 95be871..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportInfo.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -import org.fourthline.cling.model.action.ActionArgumentValue; - -import java.util.Map; - -/** - * - */ -public class TransportInfo { - - private TransportState currentTransportState = TransportState.NO_MEDIA_PRESENT; - private TransportStatus currentTransportStatus = TransportStatus.OK; - private String currentSpeed = "1"; - - public TransportInfo() { - } - - public TransportInfo(Map args) { - this( - TransportState.valueOrCustomOf((String) args.get("CurrentTransportState").getValue()), - TransportStatus.valueOrCustomOf((String) args.get("CurrentTransportStatus").getValue()), - (String) args.get("CurrentSpeed").getValue() - ); - } - - public TransportInfo(TransportState currentTransportState) { - this.currentTransportState = currentTransportState; - } - - public TransportInfo(TransportState currentTransportState, String currentSpeed) { - this.currentTransportState = currentTransportState; - this.currentSpeed = currentSpeed; - } - - public TransportInfo(TransportState currentTransportState, TransportStatus currentTransportStatus) { - this.currentTransportState = currentTransportState; - this.currentTransportStatus = currentTransportStatus; - } - - public TransportInfo(TransportState currentTransportState, TransportStatus currentTransportStatus, String currentSpeed) { - this.currentTransportState = currentTransportState; - this.currentTransportStatus = currentTransportStatus; - this.currentSpeed = currentSpeed; - } - - public TransportState getCurrentTransportState() { - return currentTransportState; - } - - public TransportStatus getCurrentTransportStatus() { - return currentTransportStatus; - } - - public String getCurrentSpeed() { - return currentSpeed; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportSettings.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportSettings.java deleted file mode 100644 index 351e635..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportSettings.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * - */ -public class TransportSettings { - - private PlayMode playMode = PlayMode.NORMAL; - private RecordQualityMode recQualityMode = RecordQualityMode.NOT_IMPLEMENTED; - - public TransportSettings() { - } - - public TransportSettings(PlayMode playMode) { - this.playMode = playMode; - } - - public TransportSettings(PlayMode playMode, RecordQualityMode recQualityMode) { - this.playMode = playMode; - this.recQualityMode = recQualityMode; - } - - public PlayMode getPlayMode() { - return playMode; - } - - public RecordQualityMode getRecQualityMode() { - return recQualityMode; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportState.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportState.java deleted file mode 100644 index 425f2cf..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportState.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * @author Christian Bauer - */ -public enum TransportState { - - STOPPED, - PLAYING, - TRANSITIONING, - PAUSED_PLAYBACK, - PAUSED_RECORDING, - RECORDING, - NO_MEDIA_PRESENT, - CUSTOM; - - String value; - - TransportState() { - this.value = name(); - } - - public String getValue() { - return value; - } - - public TransportState setValue(String value) { - this.value = value; - return this; - } - - public static TransportState valueOrCustomOf(String s) { - try { - return TransportState.valueOf(s); - } catch (IllegalArgumentException ex) { - return TransportState.CUSTOM.setValue(s); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportStatus.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportStatus.java deleted file mode 100644 index 1ff77f7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/TransportStatus.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * - */ -public enum TransportStatus { - - OK, - ERROR_OCCURRED, - CUSTOM; - - String value; - - TransportStatus() { - this.value = name(); - } - - public String getValue() { - return value; - } - - public TransportStatus setValue(String value) { - this.value = value; - return this; - } - - public static TransportStatus valueOrCustomOf(String s) { - try { - return TransportStatus.valueOf(s); - } catch (IllegalArgumentException ex) { - return TransportStatus.CUSTOM.setValue(s); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/VolumeDBRange.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/VolumeDBRange.java deleted file mode 100644 index 167f9e0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/VolumeDBRange.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * - */ -public class VolumeDBRange { - - private Integer minValue; - private Integer maxValue; - - public VolumeDBRange(Integer minValue, Integer maxValue) { - this.minValue = minValue; - this.maxValue = maxValue; - } - - public Integer getMinValue() { - return minValue; - } - - public Integer getMaxValue() { - return maxValue; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/WriteStatus.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/WriteStatus.java deleted file mode 100644 index 3475391..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/WriteStatus.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model; - -/** - * @author Christian Bauer - */ -public enum WriteStatus { - - WRITABLE, - NOT_WRITABLE, - UNKNOWN, - MIXED -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/Album.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/Album.java deleted file mode 100644 index 5ec3888..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/Album.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.StorageMedium; - -import java.net.URI; -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class Album extends Container { - - public static final Class CLASS = new Class("object.container.album"); - - public Album() { - setClazz(CLASS); - } - - public Album(Container other) { - super(other); - } - - public Album(String id, Container parent, String title, String creator, Integer childCount) { - this(id, parent.getId(), title, creator, childCount); - } - - public Album(String id, String parentID, String title, String creator, Integer childCount) { - super(id, parentID, title, creator, CLASS, childCount); - } - - public String getDescription() { - return getFirstPropertyValue(DC.DESCRIPTION.class); - } - - public Album setDescription(String description) { - replaceFirstProperty(new DC.DESCRIPTION(description)); - return this; - } - - public String getLongDescription() { - return getFirstPropertyValue(UPNP.LONG_DESCRIPTION.class); - } - - public Album setLongDescription(String description) { - replaceFirstProperty(new UPNP.LONG_DESCRIPTION(description)); - return this; - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public Album setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - - public String getDate() { - return getFirstPropertyValue(DC.DATE.class); - } - - public Album setDate(String date) { - replaceFirstProperty(new DC.DATE(date)); - return this; - } - - public URI getFirstRelation() { - return getFirstPropertyValue(DC.RELATION.class); - } - - public URI[] getRelations() { - List list = getPropertyValues(DC.RELATION.class); - return list.toArray(new URI[list.size()]); - } - - public Album setRelations(URI[] relations) { - removeProperties(DC.RELATION.class); - for (URI relation : relations) { - addProperty(new DC.RELATION(relation)); - } - return this; - } - - public String getFirstRights() { - return getFirstPropertyValue(DC.RIGHTS.class); - } - - public String[] getRights() { - List list = getPropertyValues(DC.RIGHTS.class); - return list.toArray(new String[list.size()]); - } - - public Album setRights(String[] rights) { - removeProperties(DC.RIGHTS.class); - for (String right : rights) { - addProperty(new DC.RIGHTS(right)); - } - return this; - } - - public Person getFirstContributor() { - return getFirstPropertyValue(DC.CONTRIBUTOR.class); - } - - public Person[] getContributors() { - List list = getPropertyValues(DC.CONTRIBUTOR.class); - return list.toArray(new Person[list.size()]); - } - - public Album setContributors(Person[] contributors) { - removeProperties(DC.CONTRIBUTOR.class); - for (Person p : contributors) { - addProperty(new DC.CONTRIBUTOR(p)); - } - return this; - } - - public Person getFirstPublisher() { - return getFirstPropertyValue(DC.PUBLISHER.class); - } - - public Person[] getPublishers() { - List list = getPropertyValues(DC.PUBLISHER.class); - return list.toArray(new Person[list.size()]); - } - - public Album setPublishers(Person[] publishers) { - removeProperties(DC.PUBLISHER.class); - for (Person publisher : publishers) { - addProperty(new DC.PUBLISHER(publisher)); - } - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/Container.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/Container.java deleted file mode 100644 index 8b536f8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/Container.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -import org.fourthline.cling.support.model.DIDLObject; -import org.fourthline.cling.support.model.DescMeta; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.WriteStatus; -import org.fourthline.cling.support.model.item.Item; - -import java.util.ArrayList; -import java.util.List; - -/** - * A container in DIDL content. - *

- * Note that although this container can have sub-containers, the - * {@link org.fourthline.cling.support.contentdirectory.DIDLParser} - * will never read nor write this collection to and from XML. - * Its only purpose is convenience when creating and manipulating a - * recursive structure, that is, modelling the content tree as you - * see fit. You can then pick a list of containers and/or a list of - * items and hand them to the DIDL parser, which will render them - * flat in XML. The only nested structure that can optionally be - * rendered into and read from XML are the items of containers, - * never their sub-containers. - *

- *

- * Also see ContentDirectory 1.0 specification, section 2.8.3: - * "Incremental navigation i.e. the full hierarchy is never returned - * in one call since this is likely to flood the resources available to - * the control point (memory, network bandwidth, etc.)." - *

- * - * @author Christian Bauer - */ -public class Container extends DIDLObject { - - protected Integer childCount = null; - protected boolean searchable; // Default or absent == false - protected List createClasses = new ArrayList<>(); - protected List searchClasses = new ArrayList<>(); - protected List containers = new ArrayList<>(); - protected List items = new ArrayList<>(); - - public Container() { - } - - public Container(Container other) { - super(other); - setChildCount(other.getChildCount()); - setSearchable(other.isSearchable()); - setCreateClasses(other.getCreateClasses()); - setSearchClasses(other.getSearchClasses()); - setItems(other.getItems()); - } - - public Container(String id, String parentID, String title, String creator, boolean restricted, WriteStatus writeStatus, Class clazz, List resources, List properties, List descMetadata) { - super(id, parentID, title, creator, restricted, writeStatus, clazz, resources, properties, descMetadata); - } - - public Container(String id, String parentID, String title, String creator, boolean restricted, WriteStatus writeStatus, Class clazz, List resources, List properties, List descMetadata, Integer childCount, boolean searchable, List createClasses, List searchClasses, List items) { - super(id, parentID, title, creator, restricted, writeStatus, clazz, resources, properties, descMetadata); - this.childCount = childCount; - this.searchable = searchable; - this.createClasses = createClasses; - this.searchClasses = searchClasses; - this.items = items; - } - - public Container(String id, Container parent, String title, String creator, DIDLObject.Class clazz, Integer childCount) { - this(id, parent.getId(), title, creator, true, null, clazz, new ArrayList(), new ArrayList(), new ArrayList(), childCount, false, new ArrayList(), new ArrayList(), new ArrayList()); - } - - public Container(String id, String parentID, String title, String creator, DIDLObject.Class clazz, Integer childCount) { - this(id, parentID, title, creator, true, null, clazz, new ArrayList(), new ArrayList(), new ArrayList(), childCount, false, new ArrayList(), new ArrayList(), new ArrayList()); - } - - public Container(String id, Container parent, String title, String creator, DIDLObject.Class clazz, Integer childCount, boolean searchable, List createClasses, List searchClasses, List items) { - this(id, parent.getId(), title, creator, true, null, clazz, new ArrayList(), new ArrayList(), new ArrayList(), childCount, searchable, createClasses, searchClasses, items); - } - - public Container(String id, String parentID, String title, String creator, DIDLObject.Class clazz, Integer childCount, boolean searchable, List createClasses, List searchClasses, List items) { - this(id, parentID, title, creator, true, null, clazz, new ArrayList(), new ArrayList(), new ArrayList(), childCount, searchable, createClasses, searchClasses, items); - } - - public Integer getChildCount() { - return childCount; - } - - public void setChildCount(Integer childCount) { - this.childCount = childCount; - } - - public boolean isSearchable() { - return searchable; - } - - public void setSearchable(boolean searchable) { - this.searchable = searchable; - } - - public List getCreateClasses() { - return createClasses; - } - - public void setCreateClasses(List createClasses) { - this.createClasses = createClasses; - } - - public List getSearchClasses() { - return searchClasses; - } - - public void setSearchClasses(List searchClasses) { - this.searchClasses = searchClasses; - } - - public Container getFirstContainer() { - return getContainers().get(0); - } - - public Container addContainer(Container container) { - getContainers().add(container); - return this; - } - - public List getContainers() { - return containers; - } - - public void setContainers(List containers) { - this.containers = containers; - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } - - public Container addItem(Item item) { - getItems().add(item); - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/GenreContainer.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/GenreContainer.java deleted file mode 100644 index bce1657..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/GenreContainer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -/** - * @author Christian Bauer - */ -public class GenreContainer extends Container { - - public static final Class CLASS = new Class("object.container.genre"); - - public GenreContainer() { - setClazz(CLASS); - } - - public GenreContainer(Container other) { - super(other); - } - - public GenreContainer(String id, Container parent, String title, String creator, Integer childCount) { - this(id, parent.getId(), title, creator, childCount); - } - - public GenreContainer(String id, String parentID, String title, String creator, Integer childCount) { - super(id, parentID, title, creator, CLASS, childCount); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MovieGenre.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MovieGenre.java deleted file mode 100644 index 47ca80f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MovieGenre.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -/** - * @author Christian Bauer - */ -public class MovieGenre extends GenreContainer { - - public static final Class CLASS = new Class("object.container.genre.movieGenre"); - - public MovieGenre() { - setClazz(CLASS); - } - - public MovieGenre(Container other) { - super(other); - } - - public MovieGenre(String id, Container parent, String title, String creator, Integer childCount) { - this(id, parent.getId(), title, creator, childCount); - } - - public MovieGenre(String id, String parentID, String title, String creator, Integer childCount) { - super(id, parentID, title, creator, childCount); - setClazz(CLASS); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicAlbum.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicAlbum.java deleted file mode 100644 index d4bb7fa..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicAlbum.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.PersonWithRole; -import org.fourthline.cling.support.model.item.Item; -import org.fourthline.cling.support.model.item.MusicTrack; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class MusicAlbum extends Album { - - public static final Class CLASS = new Class("object.container.album.musicAlbum"); - - public MusicAlbum() { - setClazz(CLASS); - } - - public MusicAlbum(Container other) { - super(other); - } - - public MusicAlbum(String id, Container parent, String title, String creator, Integer childCount) { - this(id, parent.getId(), title, creator, childCount, new ArrayList()); - } - - public MusicAlbum(String id, Container parent, String title, String creator, Integer childCount, List musicTracks) { - this(id, parent.getId(), title, creator, childCount, musicTracks); - } - - public MusicAlbum(String id, String parentID, String title, String creator, Integer childCount) { - this(id, parentID, title, creator, childCount, new ArrayList()); - } - - public MusicAlbum(String id, String parentID, String title, String creator, Integer childCount, List musicTracks) { - super(id, parentID, title, creator, childCount); - setClazz(CLASS); - addMusicTracks(musicTracks); - } - - public PersonWithRole getFirstArtist() { - return getFirstPropertyValue(UPNP.ARTIST.class); - } - - public PersonWithRole[] getArtists() { - List list = getPropertyValues(UPNP.ARTIST.class); - return list.toArray(new PersonWithRole[list.size()]); - } - - public MusicAlbum setArtists(PersonWithRole[] artists) { - removeProperties(UPNP.ARTIST.class); - for (PersonWithRole artist : artists) { - addProperty(new UPNP.ARTIST(artist)); - } - return this; - } - - public String getFirstGenre() { - return getFirstPropertyValue(UPNP.GENRE.class); - } - - public String[] getGenres() { - List list = getPropertyValues(UPNP.GENRE.class); - return list.toArray(new String[list.size()]); - } - - public MusicAlbum setGenres(String[] genres) { - removeProperties(UPNP.GENRE.class); - for (String genre : genres) { - addProperty(new UPNP.GENRE(genre)); - } - return this; - } - - public Person getFirstProducer() { - return getFirstPropertyValue(UPNP.PRODUCER.class); - } - - public Person[] getProducers() { - List list = getPropertyValues(UPNP.PRODUCER.class); - return list.toArray(new Person[list.size()]); - } - - public MusicAlbum setProducers(Person[] persons) { - removeProperties(UPNP.PRODUCER.class); - for (Person p : persons) { - addProperty(new UPNP.PRODUCER(p)); - } - return this; - } - - public URI getFirstAlbumArtURI() { - return getFirstPropertyValue(UPNP.ALBUM_ART_URI.class); - } - - public URI[] getAlbumArtURIs() { - List list = getPropertyValues(UPNP.ALBUM_ART_URI.class); - return list.toArray(new URI[list.size()]); - } - - public MusicAlbum setAlbumArtURIs(URI[] uris) { - removeProperties(UPNP.ALBUM_ART_URI.class); - for (URI uri : uris) { - addProperty(new UPNP.ALBUM_ART_URI(uri)); - } - return this; - } - - public String getToc() { - return getFirstPropertyValue(UPNP.TOC.class); - } - - public MusicAlbum setToc(String toc) { - replaceFirstProperty(new UPNP.TOC(toc)); - return this; - } - - public MusicTrack[] getMusicTracks() { - List list = new ArrayList<>(); - for (Item item : getItems()) { - if (item instanceof MusicTrack) list.add((MusicTrack)item); - } - return list.toArray(new MusicTrack[list.size()]); - } - - public void addMusicTracks(List musicTracks) { - addMusicTracks(musicTracks.toArray(new MusicTrack[musicTracks.size()])); - } - - public void addMusicTracks(MusicTrack[] musicTracks) { - if (musicTracks != null) { - for (MusicTrack musicTrack : musicTracks) { - musicTrack.setAlbum(getTitle()); - addItem(musicTrack); - } - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicArtist.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicArtist.java deleted file mode 100644 index ee7d8c8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicArtist.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -import java.net.URI; -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class MusicArtist extends PersonContainer { - - public static final Class CLASS = new Class("object.container.person.musicArtist"); - - public MusicArtist() { - setClazz(CLASS); - } - - public MusicArtist(Container other) { - super(other); - } - - public MusicArtist(String id, Container parent, String title, String creator, Integer childCount) { - this(id, parent.getId(), title, creator, childCount); - } - - public MusicArtist(String id, String parentID, String title, String creator, Integer childCount) { - super(id, parentID, title, creator, childCount); - setClazz(CLASS); - } - - public String getFirstGenre() { - return getFirstPropertyValue(UPNP.GENRE.class); - } - - public String[] getGenres() { - List list = getPropertyValues(UPNP.GENRE.class); - return list.toArray(new String[list.size()]); - } - - public MusicArtist setGenres(String[] genres) { - removeProperties(UPNP.GENRE.class); - for (String genre : genres) { - addProperty(new UPNP.GENRE(genre)); - } - return this; - } - - public URI getArtistDiscographyURI() { - return getFirstPropertyValue(UPNP.ARTIST_DISCO_URI.class); - } - - public MusicArtist setArtistDiscographyURI(URI uri) { - replaceFirstProperty(new UPNP.ARTIST_DISCO_URI(uri)); - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicGenre.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicGenre.java deleted file mode 100644 index ca59619..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/MusicGenre.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -/** - * @author Christian Bauer - */ -public class MusicGenre extends GenreContainer { - - public static final Class CLASS = new Class("object.container.genre.musicGenre"); - - public MusicGenre() { - setClazz(CLASS); - } - - public MusicGenre(Container other) { - super(other); - } - - public MusicGenre(String id, Container parent, String title, String creator, Integer childCount) { - this(id, parent.getId(), title, creator, childCount); - } - - public MusicGenre(String id, String parentID, String title, String creator, Integer childCount) { - super(id, parentID, title, creator, childCount); - setClazz(CLASS); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PersonContainer.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PersonContainer.java deleted file mode 100644 index 1007639..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PersonContainer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; - -/** - * @author Christian Bauer - */ -public class PersonContainer extends Container { - - public static final Class CLASS = new Class("object.container.person"); - - public PersonContainer() { - setClazz(CLASS); - } - - public PersonContainer(Container other) { - super(other); - } - - public PersonContainer(String id, Container parent, String title, String creator, Integer childCount) { - this(id, parent.getId(), title, creator, childCount); - } - - public PersonContainer(String id, String parentID, String title, String creator, Integer childCount) { - super(id, parentID, title, creator, CLASS, childCount); - } - - public String getLanguage() { - return getFirstPropertyValue(DC.LANGUAGE.class); - } - - public PersonContainer setLanguage(String language) { - replaceFirstProperty(new DC.LANGUAGE(language)); - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PhotoAlbum.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PhotoAlbum.java deleted file mode 100644 index a17eff4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PhotoAlbum.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -import org.fourthline.cling.support.model.item.Item; -import org.fourthline.cling.support.model.item.Photo; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class PhotoAlbum extends Album { - - public static final Class CLASS = new Class("object.container.album.photoAlbum"); - - public PhotoAlbum() { - setClazz(CLASS); - } - - public PhotoAlbum(Container other) { - super(other); - } - - public PhotoAlbum(String id, Container parent, String title, String creator, Integer childCount) { - this(id, parent.getId(), title, creator, childCount, new ArrayList()); - } - - public PhotoAlbum(String id, Container parent, String title, String creator, Integer childCount, List photos) { - this(id, parent.getId(), title, creator, childCount, photos); - } - - public PhotoAlbum(String id, String parentID, String title, String creator, Integer childCount) { - this(id, parentID, title, creator, childCount, new ArrayList()); - } - - public PhotoAlbum(String id, String parentID, String title, String creator, Integer childCount, List photos) { - super(id, parentID, title, creator, childCount); - setClazz(CLASS); - addPhotos(photos); - } - - public Photo[] getPhotos() { - List list = new ArrayList<>(); - for (Item item : getItems()) { - if (item instanceof Photo) list.add((Photo)item); - } - return list.toArray(new Photo[list.size()]); - } - - public void addPhotos(List photos) { - addPhotos(photos.toArray(new Photo[photos.size()])); - } - - public void addPhotos(Photo[] photos) { - if (photos != null) { - for (Photo photo : photos) { - photo.setAlbum(getTitle()); - addItem(photo); - } - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PlaylistContainer.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PlaylistContainer.java deleted file mode 100644 index 89399d4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/PlaylistContainer.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.PersonWithRole; -import org.fourthline.cling.support.model.StorageMedium; - -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class PlaylistContainer extends Container { - - public static final Class CLASS = new Class("object.container.playlistContainer"); - - public PlaylistContainer() { - setClazz(CLASS); - } - - public PlaylistContainer(Container other) { - super(other); - } - - public PlaylistContainer(String id, Container parent, String title, String creator, Integer childCount) { - this(id, parent.getId(), title, creator, childCount); - } - - public PlaylistContainer(String id, String parentID, String title, String creator, Integer childCount) { - super(id, parentID, title, creator, CLASS, childCount); - } - - public PersonWithRole getFirstArtist() { - return getFirstPropertyValue(UPNP.ARTIST.class); - } - - public PersonWithRole[] getArtists() { - List list = getPropertyValues(UPNP.ARTIST.class); - return list.toArray(new PersonWithRole[list.size()]); - } - - public PlaylistContainer setArtists(PersonWithRole[] artists) { - removeProperties(UPNP.ARTIST.class); - for (PersonWithRole artist : artists) { - addProperty(new UPNP.ARTIST(artist)); - } - return this; - } - - public String getFirstGenre() { - return getFirstPropertyValue(UPNP.GENRE.class); - } - - public String[] getGenres() { - List list = getPropertyValues(UPNP.GENRE.class); - return list.toArray(new String[list.size()]); - } - - public PlaylistContainer setGenres(String[] genres) { - removeProperties(UPNP.GENRE.class); - for (String genre : genres) { - addProperty(new UPNP.GENRE(genre)); - } - return this; - } - - public String getDescription() { - return getFirstPropertyValue(DC.DESCRIPTION.class); - } - - public PlaylistContainer setDescription(String description) { - replaceFirstProperty(new DC.DESCRIPTION(description)); - return this; - } - - public String getLongDescription() { - return getFirstPropertyValue(UPNP.LONG_DESCRIPTION.class); - } - - public PlaylistContainer setLongDescription(String description) { - replaceFirstProperty(new UPNP.LONG_DESCRIPTION(description)); - return this; - } - - public Person getFirstProducer() { - return getFirstPropertyValue(UPNP.PRODUCER.class); - } - - public Person[] getProducers() { - List list = getPropertyValues(UPNP.PRODUCER.class); - return list.toArray(new Person[list.size()]); - } - - public PlaylistContainer setProducers(Person[] persons) { - removeProperties(UPNP.PRODUCER.class); - for (Person p : persons) { - addProperty(new UPNP.PRODUCER(p)); - } - return this; - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public PlaylistContainer setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - - public String getDate() { - return getFirstPropertyValue(DC.DATE.class); - } - - public PlaylistContainer setDate(String date) { - replaceFirstProperty(new DC.DATE(date)); - return this; - } - - public String getFirstRights() { - return getFirstPropertyValue(DC.RIGHTS.class); - } - - public String[] getRights() { - List list = getPropertyValues(DC.RIGHTS.class); - return list.toArray(new String[list.size()]); - } - - public PlaylistContainer setRights(String[] rights) { - removeProperties(DC.RIGHTS.class); - for (String right : rights) { - addProperty(new DC.RIGHTS(right)); - } - return this; - } - - public Person getFirstContributor() { - return getFirstPropertyValue(DC.CONTRIBUTOR.class); - } - - public Person[] getContributors() { - List list = getPropertyValues(DC.CONTRIBUTOR.class); - return list.toArray(new Person[list.size()]); - } - - public PlaylistContainer setContributors(Person[] contributors) { - removeProperties(DC.CONTRIBUTOR.class); - for (Person p : contributors) { - addProperty(new DC.CONTRIBUTOR(p)); - } - return this; - } - - public String getLanguage() { - return getFirstPropertyValue(DC.LANGUAGE.class); - } - - public PlaylistContainer setLanguage(String language) { - replaceFirstProperty(new DC.LANGUAGE(language)); - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageFolder.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageFolder.java deleted file mode 100644 index 2b191a9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageFolder.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class StorageFolder extends Container { - - public static final Class CLASS = new Class("object.container.storageFolder"); - - public StorageFolder() { - setClazz(CLASS); - } - - public StorageFolder(Container other) { - super(other); - } - - public StorageFolder(String id, Container parent, String title, String creator, Integer childCount, - Long storageUsed) { - this(id, parent.getId(), title, creator, childCount, storageUsed); - } - - public StorageFolder(String id, String parentID, String title, String creator, Integer childCount, - Long storageUsed) { - super(id, parentID, title, creator, CLASS, childCount); - if (storageUsed!= null) - setStorageUsed(storageUsed); - } - - public Long getStorageUsed() { - return getFirstPropertyValue(UPNP.STORAGE_USED.class); - } - - public StorageFolder setStorageUsed(Long l) { - replaceFirstProperty(new UPNP.STORAGE_USED(l)); - return this; - } - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageSystem.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageSystem.java deleted file mode 100644 index 49462ce..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageSystem.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -import org.fourthline.cling.support.model.StorageMedium; - -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class StorageSystem extends Container { - - public static final Class CLASS = new Class("object.container.storageSystem"); - - public StorageSystem() { - setClazz(CLASS); - } - - public StorageSystem(Container other) { - super(other); - } - - public StorageSystem(String id, Container parent, String title, String creator, Integer childCount, - Long storageTotal, Long storageUsed, Long storageFree, Long storageMaxPartition, StorageMedium storageMedium) { - this(id, parent.getId(), title, creator, childCount, storageTotal, storageUsed, storageFree, storageMaxPartition, storageMedium); - } - - public StorageSystem(String id, String parentID, String title, String creator, Integer childCount, - Long storageTotal, Long storageUsed, Long storageFree, Long storageMaxPartition, StorageMedium storageMedium) { - super(id, parentID, title, creator, CLASS, childCount); - if (storageTotal != null) - setStorageTotal(storageTotal); - if (storageUsed!= null) - setStorageUsed(storageUsed); - if (storageFree != null) - setStorageFree(storageFree); - if (storageMaxPartition != null) - setStorageMaxPartition(storageMaxPartition); - if (storageMedium != null) - setStorageMedium(storageMedium); - } - - public Long getStorageTotal() { - return getFirstPropertyValue(UPNP.STORAGE_TOTAL.class); - } - - public StorageSystem setStorageTotal(Long l) { - replaceFirstProperty(new UPNP.STORAGE_TOTAL(l)); - return this; - } - - public Long getStorageUsed() { - return getFirstPropertyValue(UPNP.STORAGE_USED.class); - } - - public StorageSystem setStorageUsed(Long l) { - replaceFirstProperty(new UPNP.STORAGE_USED(l)); - return this; - } - - public Long getStorageFree() { - return getFirstPropertyValue(UPNP.STORAGE_FREE.class); - } - - public StorageSystem setStorageFree(Long l) { - replaceFirstProperty(new UPNP.STORAGE_FREE(l)); - return this; - } - - public Long getStorageMaxPartition() { - return getFirstPropertyValue(UPNP.STORAGE_MAX_PARTITION.class); - } - - public StorageSystem setStorageMaxPartition(Long l) { - replaceFirstProperty(new UPNP.STORAGE_MAX_PARTITION(l)); - return this; - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public StorageSystem setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageVolume.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageVolume.java deleted file mode 100644 index 3a83223..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/container/StorageVolume.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.container; - -import org.fourthline.cling.support.model.StorageMedium; - -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class StorageVolume extends Container { - - public static final Class CLASS = new Class("object.container.storageVolume"); - - public StorageVolume() { - setClazz(CLASS); - } - - public StorageVolume(Container other) { - super(other); - } - - public StorageVolume(String id, Container parent, String title, String creator, Integer childCount, - Long storageTotal, Long storageUsed, Long storageFree, StorageMedium storageMedium) { - this(id, parent.getId(), title, creator, childCount, storageTotal, storageUsed, storageFree, storageMedium); - } - - public StorageVolume(String id, String parentID, String title, String creator, Integer childCount, - Long storageTotal, Long storageUsed, Long storageFree, StorageMedium storageMedium) { - super(id, parentID, title, creator, CLASS, childCount); - if (storageTotal != null) - setStorageTotal(storageTotal); - if (storageUsed!= null) - setStorageUsed(storageUsed); - if (storageFree != null) - setStorageFree(storageFree); - if (storageMedium != null) - setStorageMedium(storageMedium); - } - - public Long getStorageTotal() { - return getFirstPropertyValue(UPNP.STORAGE_TOTAL.class); - } - - public StorageVolume setStorageTotal(Long l) { - replaceFirstProperty(new UPNP.STORAGE_TOTAL(l)); - return this; - } - - public Long getStorageUsed() { - return getFirstPropertyValue(UPNP.STORAGE_USED.class); - } - - public StorageVolume setStorageUsed(Long l) { - replaceFirstProperty(new UPNP.STORAGE_USED(l)); - return this; - } - - public Long getStorageFree() { - return getFirstPropertyValue(UPNP.STORAGE_FREE.class); - } - - public StorageVolume setStorageFree(Long l) { - replaceFirstProperty(new UPNP.STORAGE_FREE(l)); - return this; - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public StorageVolume setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAAttribute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAAttribute.java deleted file mode 100644 index 0689dab..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAAttribute.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -import org.seamless.util.Exceptions; - -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Transforms known and standardized DLNA attributes from/to string representation. - *

- * The {@link #newInstance(org.fourthline.cling.support.model.dlna.DLNAAttribute.Type, String, String)} - * method attempts to instantiate the best header subtype for a given header (name) and string value. - *

- * - * @author Christian Bauer - * @author Mario Franco - */ -public abstract class DLNAAttribute { - - final private static Logger log = Logger.getLogger(DLNAAttribute.class.getName()); - - /** - * Maps a standardized DLNA attribute to potential attribute subtypes. - */ - public static enum Type { - - /** - * Order is important for DLNAProtocolInfo - */ - DLNA_ORG_PN("DLNA.ORG_PN", DLNAProfileAttribute.class), - DLNA_ORG_OP("DLNA.ORG_OP", DLNAOperationsAttribute.class), - DLNA_ORG_PS("DLNA.ORG_PS", DLNAPlaySpeedAttribute.class), - DLNA_ORG_CI("DLNA.ORG_CI", DLNAConversionIndicatorAttribute.class), - DLNA_ORG_FLAGS("DLNA.ORG_FLAGS", DLNAFlagsAttribute.class); - - private static Map byName = new HashMap() { - { - for (Type t : Type.values()) { - put(t.getAttributeName().toUpperCase(Locale.ROOT), t); - } - } - }; - - private String attributeName; - private Class[] attributeTypes; - - @SafeVarargs - private Type(String attributeName, Class... attributeClass) { - this.attributeName = attributeName; - this.attributeTypes = attributeClass; - } - - public String getAttributeName() { - return attributeName; - } - - public Class[] getAttributeTypes() { - return attributeTypes; - } - - public static Type valueOfAttributeName(String attributeName) { - if (attributeName == null) { - return null; - } - return byName.get(attributeName.toUpperCase(Locale.ROOT)); - } - } - - private T value; - - public void setValue(T value) { - this.value = value; - } - - public T getValue() { - return value; - } - - /** - * @param s This attribute's value as a string representation. - * @param cf This attribute's mime type as a string representation, optional. - * @throws InvalidDLNAProtocolAttributeException - * If the value is invalid for this DLNA attribute. - */ - public abstract void setString(String s, String cf) throws InvalidDLNAProtocolAttributeException; - - /** - * @return A string representing this attribute's value. - */ - public abstract String getString(); - - /** - * Create a new instance of a {@link DLNAAttribute} subtype that matches the given type and value. - *

- * This method iterates through all potential attribute subtype classes as declared in {@link Type}. - * It creates a new instance of the subtype class and calls its {@link #setString(String, String)} method. - * If no {@link org.fourthline.cling.support.model.dlna.InvalidDLNAProtocolAttributeException} is thrown, - * the subtype instance is returned. - *

- * - * @param type The type of the attribute. - * @param attributeValue The value of the attribute. - * @param contentFormat The DLNA mime type of the attribute, optional. - * @return The best matching attribute subtype instance, or null if no subtype can be found. - */ - public static DLNAAttribute newInstance(DLNAAttribute.Type type, String attributeValue, String contentFormat) { - - DLNAAttribute attr = null; - for (int i = 0; i < type.getAttributeTypes().length && attr == null; i++) { - Class attributeClass = type.getAttributeTypes()[i]; - try { - log.finest("Trying to parse DLNA '" + type + "' with class: " + attributeClass.getSimpleName()); - attr = attributeClass.newInstance(); - if (attributeValue != null) { - attr.setString(attributeValue, contentFormat); - } - } catch (InvalidDLNAProtocolAttributeException ex) { - log.finest("Invalid DLNA attribute value for tested type: " + attributeClass.getSimpleName() + " - " + ex.getMessage()); - attr = null; - } catch (Exception ex) { - log.severe("Error instantiating DLNA attribute of type '" + type + "' with value: " + attributeValue); - log.log(Level.SEVERE, "Exception root cause: ", Exceptions.unwrap(ex)); - } - } - return attr; - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ") '" + getValue() + "'"; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAConversionIndicator.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAConversionIndicator.java deleted file mode 100644 index c70c0f5..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAConversionIndicator.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -/** DLNA.ORG_CI: conversion indicator parameter (integer) - *
- *     0 not transcoded
- *     1 transcoded
- * 
- * - * @author Mario Franco - */ -public enum DLNAConversionIndicator { - - NONE(0), - TRANSCODED(1); - - private int code; - - DLNAConversionIndicator(int code) { - this.code = code; - } - - public int getCode() { - return code; - } - - public static DLNAConversionIndicator valueOf(int code) { - for (DLNAConversionIndicator errorCode : values()) { - if (errorCode.getCode() == code) { - return errorCode; - } - } - return null; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAConversionIndicatorAttribute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAConversionIndicatorAttribute.java deleted file mode 100644 index ce9c542..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAConversionIndicatorAttribute.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -/** - * @author Mario Franco - */ -public class DLNAConversionIndicatorAttribute extends DLNAAttribute { - - public DLNAConversionIndicatorAttribute() { - setValue(DLNAConversionIndicator.NONE); - } - - public DLNAConversionIndicatorAttribute(DLNAConversionIndicator indicator) { - setValue(indicator); - } - - public void setString(String s, String cf) throws InvalidDLNAProtocolAttributeException { - DLNAConversionIndicator value = null; - try { - value = DLNAConversionIndicator.valueOf(Integer.parseInt(s)); - } catch (NumberFormatException numberFormatException) { - } - if (value == null) { - throw new InvalidDLNAProtocolAttributeException("Can't parse DLNA play speed integer from: " + s); - } - setValue(value); - } - - public String getString() { - return Integer.toString(getValue().getCode()); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAFlags.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAFlags.java deleted file mode 100644 index 98f1d5b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAFlags.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -/** DLNA.ORG_FLAGS, padded with 24 trailing 0s - * - *
- *     80000000  31  senderPaced
- *     40000000  30  lsopTimeBasedSeekSupported
- *     20000000  29  lsopByteBasedSeekSupported
- *     10000000  28  playcontainerSupported
- *      8000000  27  s0IncreasingSupported
- *      4000000  26  sNIncreasingSupported
- *      2000000  25  rtspPauseSupported
- *      1000000  24  streamingTransferModeSupported
- *       800000  23  interactiveTransferModeSupported
- *       400000  22  backgroundTransferModeSupported
- *       200000  21  connectionStallingSupported
- *       100000  20  dlnaVersion15Supported
- *
- *     Example: (1 << 24) | (1 << 22) | (1 << 21) | (1 << 20)
- *       DLNA.ORG_FLAGS=01700000[000000000000000000000000] // [] show padding
- * 
- * - * @author Mario Franco - */ -public enum DLNAFlags { - - SENDER_PACED(1 << 31), - TIME_BASED_SEEK(1 << 30), - BYTE_BASED_SEEK(1 << 29), - FLAG_PLAY_CONTAINER(1 << 28), - S0_INCREASE(1 << 27), - SN_INCREASE(1 << 26), - RTSP_PAUSE(1 << 25), - STREAMING_TRANSFER_MODE(1 << 24), - INTERACTIVE_TRANSFERT_MODE(1 << 23), - BACKGROUND_TRANSFERT_MODE(1 << 22), - CONNECTION_STALL(1 << 21), - DLNA_V15(1 << 20); - - private int code; - - DLNAFlags(int code) { - this.code = code; - } - - public int getCode() { - return code; - } - - public static DLNAFlags valueOf(int code) { - for (DLNAFlags errorCode : values()) { - if (errorCode.getCode() == code) { - return errorCode; - } - } - return null; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAFlagsAttribute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAFlagsAttribute.java deleted file mode 100644 index 18d0784..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAFlagsAttribute.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -import java.util.EnumSet; -import java.util.Locale; - -/** - * @author Mario Franco - */ -public class DLNAFlagsAttribute extends DLNAAttribute> { - - public DLNAFlagsAttribute() { - setValue(EnumSet.noneOf(DLNAFlags.class)); - } - - public DLNAFlagsAttribute(DLNAFlags... flags) { - if (flags != null && flags.length > 0) { - DLNAFlags first = flags[0]; - if (flags.length > 1) { - System.arraycopy(flags, 1, flags, 0, flags.length - 1); - setValue(EnumSet.of(first, flags)); - } else { - setValue(EnumSet.of(first)); - } - } - } - - public void setString(String s, String cf) throws InvalidDLNAProtocolAttributeException { - EnumSet value = EnumSet.noneOf(DLNAFlags.class); - try { - int parseInt = Integer.parseInt(s.substring(0, s.length() - 24), 16); - for (DLNAFlags op : DLNAFlags.values()) { - int code = op.getCode() & parseInt; - if (op.getCode() == code) { - value.add(op); - } - } - } catch (Exception e) { - } - - if (value.isEmpty()) - throw new InvalidDLNAProtocolAttributeException("Can't parse DLNA flags integer from: " + s); - - setValue(value); - } - - public String getString() { - int code = 0; - for (DLNAFlags op : getValue()) { - code |= op.getCode(); - } - return String.format(Locale.ROOT, "%08x%024x", code, 0); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAOperations.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAOperations.java deleted file mode 100644 index b6676e8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAOperations.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -/** - * DLNA.ORG_OP: operations parameter (string) - * - *
- *     "00" (or "0") neither time seek range nor range supported
- *     "01" range supported
- *     "10" time seek range supported
- *     "11" both time seek range and range supported
- * 
- * - * @author Mario Franco - */ -public enum DLNAOperations { - - NONE(0x00), - RANGE(0x01), - TIMESEEK(0x10); - - private int code; - - DLNAOperations(int code) { - this.code = code; - } - - public int getCode() { - return code; - } - - public static DLNAOperations valueOf(int code) { - for (DLNAOperations errorCode : values()) { - if (errorCode.getCode() == code) { - return errorCode; - } - } - return null; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAOperationsAttribute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAOperationsAttribute.java deleted file mode 100644 index 5841687..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAOperationsAttribute.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -import java.util.EnumSet; -import java.util.Locale; - -/** - * @author Mario Franco - */ -public class DLNAOperationsAttribute extends DLNAAttribute> { - - public DLNAOperationsAttribute() { - setValue(EnumSet.of(DLNAOperations.NONE)); - } - - public DLNAOperationsAttribute(DLNAOperations... op) { - if (op != null && op.length > 0) { - DLNAOperations first = op[0]; - if (op.length > 1) { - System.arraycopy(op, 1, op, 0, op.length - 1); - setValue(EnumSet.of(first, op)); - } else { - setValue(EnumSet.of(first)); - } - } - } - - public void setString(String s, String cf) throws InvalidDLNAProtocolAttributeException { - EnumSet value = EnumSet.noneOf(DLNAOperations.class); - try { - int parseInt = Integer.parseInt(s, 16); - for (DLNAOperations op : DLNAOperations.values()) { - int code = op.getCode() & parseInt; - if (op != DLNAOperations.NONE && (op.getCode() == code)) { - value.add(op); - } - } - } catch (NumberFormatException numberFormatException) { - } - - if (value.isEmpty()) - throw new InvalidDLNAProtocolAttributeException("Can't parse DLNA operations integer from: " + s); - - setValue(value); - } - - public String getString() { - int code = DLNAOperations.NONE.getCode(); - for (DLNAOperations op : getValue()) { - code |= op.getCode(); - } - return String.format(Locale.ROOT, "%02x", code); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAPlaySpeedAttribute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAPlaySpeedAttribute.java deleted file mode 100644 index 50c14a1..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAPlaySpeedAttribute.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.support.avtransport.lastchange.AVTransportVariable.TransportPlaySpeed; - -/** - * @author Mario Franco - */ -public class DLNAPlaySpeedAttribute extends DLNAAttribute { - - public DLNAPlaySpeedAttribute() { - setValue(new TransportPlaySpeed[] {}); - } - - public DLNAPlaySpeedAttribute(TransportPlaySpeed[] speeds) { - setValue(speeds); - } - - public DLNAPlaySpeedAttribute(String[] speeds) { - TransportPlaySpeed[] sp = new TransportPlaySpeed[speeds.length]; - try { - for (int i = 0; i < speeds.length; i++) { - sp[i] = new TransportPlaySpeed(speeds[i]); - } - } catch (InvalidValueException invalidValueException) { - throw new InvalidDLNAProtocolAttributeException("Can't parse DLNA play speeds."); - } - setValue(sp); - } - - public void setString(String s, String cf) throws InvalidDLNAProtocolAttributeException { - TransportPlaySpeed[] value = null; - if (s != null && s.length() != 0) { - String[] speeds = s.split(","); - try { - value = new TransportPlaySpeed[speeds.length]; - for (int i = 0; i < speeds.length; i++) { - value[i] = new TransportPlaySpeed(speeds[i]); - } - } catch (InvalidValueException invalidValueException) { - value = null; - } - } - if (value == null) { - throw new InvalidDLNAProtocolAttributeException("Can't parse DLNA play speeds from: " + s); - } - setValue(value); - } - - public String getString() { - String s = ""; - for (TransportPlaySpeed speed : getValue()) { - if (speed.getValue().equals("1")) - continue; - s += (s.length() == 0 ? "" : ",") + speed; - } - return s; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProfileAttribute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProfileAttribute.java deleted file mode 100644 index 4c83d2d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProfileAttribute.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -/** - * @author Mario Franco - */ -public class DLNAProfileAttribute extends DLNAAttribute { - - public DLNAProfileAttribute() { - setValue(DLNAProfiles.NONE); - } - - public DLNAProfileAttribute(DLNAProfiles profile) { - setValue(profile); - } - - public void setString(String s, String cf) throws InvalidDLNAProtocolAttributeException { - DLNAProfiles value = DLNAProfiles.valueOf(s, cf); - if (value == null) { - throw new InvalidDLNAProtocolAttributeException("Can't parse DLNA profile from: " + s); - } - setValue(value); - } - - public String getString() { - return getValue().getCode(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProfiles.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProfiles.java deleted file mode 100644 index 1c60db3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProfiles.java +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -/** - * DLNA.ORG_PN: DLNA Profiles - * - * @author Mario Franco - */ -public enum DLNAProfiles { - - NONE("",""), - - //Image - JPEG_SM("JPEG_SM", DLNAMimeTypes.MIME_IMAGE_JPEG), /* Profile for image media class content of small resolution */ - JPEG_MED("JPEG_MED", DLNAMimeTypes.MIME_IMAGE_JPEG), /* Profile for image media class content of medium resolution */ - JPEG_LRG("JPEG_LRG", DLNAMimeTypes.MIME_IMAGE_JPEG), /* Profile for image media class content of high resolution */ - JPEG_TN("JPEG_TN", DLNAMimeTypes.MIME_IMAGE_JPEG), /* Profile for image thumbnails */ - JPEG_SM_ICO("JPEG_SM_ICO", DLNAMimeTypes.MIME_IMAGE_JPEG), /* Profile for small icons */ - JPEG_LRG_ICO("JPEG_LRG_ICO", DLNAMimeTypes.MIME_IMAGE_JPEG), /* Profile for large icons */ - - PNG_TN("PNG_TN", DLNAMimeTypes.MIME_IMAGE_PNG), /* Profile for image thumbnails */ - PNG_SM_ICO("PNG_SM_ICO", DLNAMimeTypes.MIME_IMAGE_PNG), /* Profile for small icons */ - PNG_LRG_ICO("PNG_LRG_ICO", DLNAMimeTypes.MIME_IMAGE_PNG), /* Profile for image class content of high resolution */ - PNG_LRG("PNG_LRG", DLNAMimeTypes.MIME_IMAGE_PNG), - - //Audio - LPCM("LPCM",DLNAMimeTypes.MIME_AUDIO_LPCM), - LPCM_LOW("LPCM_low",DLNAMimeTypes.MIME_AUDIO_LPCM), - - MP3("MP3",DLNAMimeTypes.MIME_AUDIO_MPEG), - MP3X("MP3X",DLNAMimeTypes.MIME_AUDIO_MPEG), - - WMABASE("WMABASE",DLNAMimeTypes.MIME_AUDIO_WMA), - WMAFULL("WMAFULL",DLNAMimeTypes.MIME_AUDIO_WMA), - WMAPRO("WMAPRO",DLNAMimeTypes.MIME_AUDIO_WMA), - - AAC_ADTS("AAC_ADTS", DLNAMimeTypes.MIME_AUDIO_ADTS), - AAC_ADTS_320("AAC_ADTS_320", DLNAMimeTypes.MIME_AUDIO_ADTS), - AAC_ISO("AAC_ISO", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - AAC_ISO_320("AAC_ISO_320", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - AAC_LTP_ISO("AAC_LTP_ISO", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - AAC_LTP_MULT5_ISO("AAC_LTP_MULT5_ISO", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - AAC_LTP_MULT7_ISO("AAC_LTP_MULT7_ISO", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - AAC_MULT5_ADTS("AAC_MULT5_ADTS", DLNAMimeTypes.MIME_AUDIO_ADTS), - AAC_MULT5_ISO("AAC_MULT5_ISO", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - - HEAAC_L2_ADTS("HEAAC_L2_ADTS", DLNAMimeTypes.MIME_AUDIO_ADTS), - HEAAC_L2_ISO("HEAAC_L2_ISO", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - HEAAC_L3_ADTS("HEAAC_L3_ADTS", DLNAMimeTypes.MIME_AUDIO_ADTS), - HEAAC_L3_ISO("HEAAC_L3_ISO", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - HEAAC_MULT5_ADTS("HEAAC_MULT5_ADTS", DLNAMimeTypes.MIME_AUDIO_ADTS), - HEAAC_MULT5_ISO("HEAAC_MULT5_ISO", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - HEAAC_L2_ADTS_320("HEAAC_L2_ADTS_320", DLNAMimeTypes.MIME_AUDIO_ADTS), - HEAAC_L2_ISO_320("HEAAC_L2_ISO_320", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - - BSAC_ISO("BSAC_ISO", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - BSAC_MULT5_ISO("BSAC_MULT5_ISO", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - - HEAACv2_L2("HEAACv2_L2", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - HEAACv2_L2_ADTS("HEAACv2_L2", DLNAMimeTypes.MIME_AUDIO_ADTS), - HEAACv2_L2_320("HEAACv2_L2_320", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - HEAACv2_L2_320_ADTS("HEAACv2_L2_320", DLNAMimeTypes.MIME_AUDIO_ADTS), - HEAACv2_L3("HEAACv2_L3", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - HEAACv2_L3_ADTS("HEAACv2_L3", "vnd.dlna.adts"), - HEAACv2_MULT5("HEAACv2_MULT5", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - HEAACv2_MULT5_ADTS("HEAACv2_MULT5", "vnd.dlna.adts"), - - AC3("AC3", DLNAMimeTypes.MIME_AUDIO_DOLBY_DIGITAL), - - AMR("AMR_3GPP", DLNAMimeTypes.MIME_AUDIO_MPEG_4), - THREE_GPP("AMR_3GPP", DLNAMimeTypes.MIME_AUDIO_3GP), - - AMR_WBplus("AMR_WBplus", DLNAMimeTypes.MIME_AUDIO_3GP), - ATRAC3("ATRAC3plus", DLNAMimeTypes.MIME_AUDIO_ATRAC), - - //Video - WMVMED_BASE("WMVMED_BASE", DLNAMimeTypes.MIME_VIDEO_WMV), - WMVMED_FULL("WMVMED_FULL", DLNAMimeTypes.MIME_VIDEO_WMV), - WMVMED_PRO("WMVMED_PRO", DLNAMimeTypes.MIME_VIDEO_WMV), - WMVHIGH_FULL("WMVHIGH_FULL", DLNAMimeTypes.MIME_VIDEO_WMV), - WMVHIGH_PRO("WMVHIGH_PRO", DLNAMimeTypes.MIME_VIDEO_WMV), - WMVHM_BASE("WMVHM_BASE", DLNAMimeTypes.MIME_VIDEO_WMV), - WMVSPLL_BASE("WMVSPLL_BASE", DLNAMimeTypes.MIME_VIDEO_WMV), - WMVSPML_BASE("WMVSPML_BASE", DLNAMimeTypes.MIME_VIDEO_WMV), - WMVSPML_MP3("WMVSPML_MP3", DLNAMimeTypes.MIME_VIDEO_WMV), - - MPEG1("MPEG1", DLNAMimeTypes.MIME_VIDEO_MPEG), - - MPEG_PS_NTSC("MPEG_PS_NTSC", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG_PS_NTSC_XAC3("MPEG_PS_NTSC_XAC3", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG_PS_PAL("MPEG_PS_PAL", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG_PS_PAL_XAC3("MPEG_PS_PAL_XAC3", DLNAMimeTypes.MIME_VIDEO_MPEG), - - MPEG_TS_MP_LL_AAC("MPEG_TS_MP_LL_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_MP_LL_AAC_T("MPEG_TS_MP_LL_AAC_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_MP_LL_AAC_ISO("MPEG_TS_MP_LL_AAC_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - - MPEG_TS_SD_50_L2_T("MPEG_TS_SD_50_L2_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_SD_60_L2_T("MPEG_TS_SD_60_L2_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_SD_60_AC3_T("MPEG_TS_SD_60_AC3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - - MPEG_TS_SD_EU("MPEG_TS_SD_EU", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_SD_EU_T("MPEG_TS_SD_EU_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_SD_EU_ISO("MPEG_TS_SD_EU_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG_TS_SD_50_AC3_T("MPEG_TS_SD_50_AC3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - - MPEG_TS_SD_NA("MPEG_TS_SD_NA", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_SD_NA_T("MPEG_TS_SD_NA_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_SD_NA_ISO("MPEG_TS_SD_NA_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG_TS_SD_NA_XAC3("MPEG_TS_SD_NA_XAC3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_SD_NA_XAC3_T("MPEG_TS_SD_NA_XAC3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_SD_NA_XAC3_ISO("MPEG_TS_SD_NA_XAC3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - - MPEG_TS_HD_NA("MPEG_TS_HD_NA", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_HD_NA_T("MPEG_TS_HD_NA_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_HD_50_L2_T("MPEG_TS_HD_50_L2_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_HD_50_L2_ISO("MPEG_TS_HD_50_L2_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG_TS_HD_60_L2_T("MPEG_TS_HD_60_L2_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_HD_60_L2_ISO("MPEG_TS_HD_60_L2_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - - MPEG_TS_HD_NA_ISO("MPEG_TS_HD_NA_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG_TS_HD_NA_XAC3("MPEG_TS_HD_NA_XAC3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_HD_NA_XAC3_T("MPEG_TS_HD_NA_XAC3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG_TS_HD_NA_XAC3_ISO("MPEG_TS_HD_NA_XAC3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - - MPEG_ES_PAL("MPEG_ES_PAL", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG_ES_NTSC("MPEG_ES_NTSC", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG_ES_PAL_XAC3("MPEG_ES_PAL_XAC3", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG_ES_NTSC_XAC3("MPEG_ES_NTSC_XAC3", DLNAMimeTypes.MIME_VIDEO_MPEG), - - MPEG4_P2_MP4_SP_AAC("MPEG4_P2_MP4_SP_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_SP_HEAAC("MPEG4_P2_MP4_SP_HEAAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_SP_ATRAC3plus("MPEG4_P2_MP4_SP_ATRAC3plus", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_SP_AAC_LTP("MPEG4_P2_MP4_SP_AAC_LTP", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_SP_L2_AAC("MPEG4_P2_MP4_SP_L2_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_SP_L2_AMR("MPEG4_P2_MP4_SP_L2_AMR", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_SP_VGA_AAC("MPEG4_P2_MP4_SP_VGA_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_SP_VGA_HEAAC("MPEG4_P2_MP4_SP_VGA_HEAAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_ASP_AAC("MPEG4_P2_MP4_ASP_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_ASP_HEAAC("MPEG4_P2_MP4_ASP_HEAAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_ASP_HEAAC_MULT5("MPEG4_P2_MP4_ASP_HEAAC_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_ASP_ATRAC3plus("MPEG4_P2_MP4_ASP_ATRAC3plus", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_ASP_L5_SO_AAC("MPEG4_P2_MP4_ASP_L5_SO_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_ASP_L5_SO_HEAAC("MPEG4_P2_MP4_ASP_L5_SO_HEAAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_ASP_L5_SO_HEAAC_MULT5("MPEG4_P2_MP4_ASP_L5_SO_HEAAC_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_ASP_L4_SO_AAC("MPEG4_P2_MP4_ASP_L4_SO_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_ASP_L4_SO_HEAAC("MPEG4_P2_MP4_ASP_L4_SO_HEAAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - MPEG4_P2_MP4_ASP_L4_SO_HEAAC_MULT5("MPEG4_P2_MP4_ASP_L4_SO_HEAAC_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - - MPEG4_H263_MP4_P0_L10_AAC("MPEG4_H263_MP4_P0_L10_AAC", DLNAMimeTypes.MIME_VIDEO_3GP), - MPEG4_H263_MP4_P0_L10_AAC_LTP("MPEG4_H263_MP4_P0_L10_AAC_LTP", DLNAMimeTypes.MIME_VIDEO_3GP), - - MPEG4_P2_TS_SP_AAC("MPEG4_P2_TS_SP_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_SP_AAC_T("MPEG4_P2_TS_SP_AAC_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_SP_AAC_ISO("MPEG4_P2_TS_SP_AAC_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG4_P2_TS_SP_MPEG1_L3("MPEG4_P2_TS_SP_MPEG1_L3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_SP_MPEG1_L3_T("MPEG4_P2_TS_SP_MPEG1_L3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_SP_MPEG1_L3_ISO("MPEG4_P2_TS_SP_MPEG1_L3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG4_P2_TS_SP_AC3_L3("MPEG4_P2_TS_SP_AC3_L3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_SP_AC3_T("MPEG4_P2_TS_SP_AC3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_SP_AC3_ISO("MPEG4_P2_TS_SP_AC3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG4_P2_TS_SP_MPEG2_L2("MPEG4_P2_TS_SP_MPEG2_L2", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_SP_MPEG2_L2_T("MPEG4_P2_TS_SP_MPEG2_L2_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_SP_MPEG2_L2_ISO("MPEG4_P2_TS_SP_MPEG2_L2_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG4_P2_TS_ASP_AAC("MPEG4_P2_TS_ASP_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_ASP_AAC_T("MPEG4_P2_TS_ASP_AAC_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_ASP_AAC_ISO("MPEG4_P2_TS_ASP_AAC_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG4_P2_TS_ASP_MPEG1_L3("MPEG4_P2_TS_ASP_MPEG1_L3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_ASP_MPEG1_L3_T("MPEG4_P2_TS_ASP_MPEG1_L3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_ASP_MPEG1_L3_ISO("MPEG4_P2_TS_ASP_MPEG1_L3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG4_P2_TS_ASP_AC3_L3("MPEG4_P2_TS_ASP_AC3_L3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_ASP_AC3_T("MPEG4_P2_TS_ASP_AC3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_ASP_AC3_ISO("MPEG4_P2_TS_ASP_AC3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG4_P2_TS_CO_AC3("MPEG4_P2_TS_CO_AC3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_CO_AC3_T("MPEG4_P2_TS_CO_AC3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_CO_AC3_ISO("MPEG4_P2_TS_CO_AC3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - MPEG4_P2_TS_CO_MPEG2_L2("MPEG4_P2_TS_CO_MPEG2_L2", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_CO_MPEG2_L2_T("MPEG4_P2_TS_CO_MPEG2_L2_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - MPEG4_P2_TS_CO_MPEG2_L2_ISO("MPEG4_P2_TS_CO_MPEG2_L2_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - - MPEG4_P2_ASF_SP_G726("MPEG4_P2_ASF_SP_G726", DLNAMimeTypes.MIME_VIDEO_ASF), - MPEG4_P2_ASF_ASP_L5_SO_G726("MPEG4_P2_ASF_ASP_L5_SO_G726", DLNAMimeTypes.MIME_VIDEO_ASF), - MPEG4_P2_ASF_ASP_L4_SO_G726("MPEG4_P2_ASF_ASP_L4_SO_G726", DLNAMimeTypes.MIME_VIDEO_ASF), - - MPEG4_H263_3GPP_P0_L10_AMR_WBplus("MPEG4_H263_3GPP_P0_L10_AMR_WBplus", DLNAMimeTypes.MIME_VIDEO_3GP), - MPEG4_P2_3GPP_SP_L0B_AAC("MPEG4_P2_3GPP_SP_L0B_AAC", DLNAMimeTypes.MIME_VIDEO_3GP), - MPEG4_P2_3GPP_SP_L0B_AMR("MPEG4_P2_3GPP_SP_L0B_AMR", DLNAMimeTypes.MIME_VIDEO_3GP), - MPEG4_H263_3GPP_P3_L10_AMR("MPEG4_H263_3GPP_P3_L10_AMR", DLNAMimeTypes.MIME_VIDEO_3GP), - - AVC_MP4_MP_SD_AAC_MULT5("AVC_MP4_MP_SD_AAC_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_MP_SD_HEAAC_L2("AVC_MP4_MP_SD_HEAAC_L2", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_MP_SD_MPEG1_L3("AVC_MP4_MP_SD_MPEG1_L3", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_MP_SD_AC3("AVC_MP4_MP_SD_AC3", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_MP_SD_AAC_LTP("AVC_MP4_MP_SD_AAC_LTP", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_MP_SD_AAC_LTP_MULT5("AVC_MP4_MP_SD_AAC_LTP_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_MP_SD_AAC_LTP_MULT7("AVC_MP4_MP_SD_AAC_LTP_MULT7", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_MP_SD_ATRAC3plus("AVC_MP4_MP_SD_ATRAC3plus", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_MP_SD_BSAC("AVC_MP4_MP_SD_BSAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - - AVC_MP4_MP_HD_720p_AAC("AVC_MP4_MP_HD_720p_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_MP_HD_1080i_AAC("AVC_MP4_MP_HD_1080i_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - - AVC_MP4_HP_HD_AAC("AVC_MP4_HP_HD_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - - AVC_MP4_BL_L3L_SD_AAC("AVC_MP4_BL_L3L_SD_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_L3L_SD_HEAAC("AVC_MP4_BL_L3L_SD_HEAAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_L3_SD_AAC("AVC_MP4_BL_L3_SD_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF30_AAC_MULT5("AVC_MP4_BL_CIF30_AAC_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF30_HEAAC_L2("AVC_MP4_BL_CIF30_HEAAC_L2", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF30_MPEG1_L3("AVC_MP4_BL_CIF30_MPEG1_L3", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF30_AC3("AVC_MP4_BL_CIF30_AC3", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF30_AAC_LTP("AVC_MP4_BL_CIF30_AAC_LTP", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF30_AAC_LTP_MULT5("AVC_MP4_BL_CIF30_AAC_LTP_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_L2_CIF30_AAC("AVC_MP4_BL_L2_CIF30_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF30_BSAC("AVC_MP4_BL_CIF30_BSAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF30_BSAC_MULT5("AVC_MP4_BL_CIF30_BSAC_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF15_HEAAC("AVC_MP4_BL_CIF15_HEAAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF15_AMR("AVC_MP4_BL_CIF15_AMR", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF15_AAC("AVC_MP4_BL_CIF15_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF15_AAC_520("AVC_MP4_BL_CIF15_AAC_520", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF15_AAC_LTP("AVC_MP4_BL_CIF15_AAC_LTP", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF15_AAC_LTP_520("AVC_MP4_BL_CIF15_AAC_LTP_520", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_CIF15_BSAC("AVC_MP4_BL_CIF15_BSAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_L12_CIF15_HEAAC("AVC_MP4_BL_L12_CIF15_HEAAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - AVC_MP4_BL_L1B_QCIF15_HEAAC("AVC_MP4_BL_L1B_QCIF15_HEAAC", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - - AVC_TS_MP_SD_AAC_MULT5("AVC_TS_MP_SD_AAC_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_AAC_MULT5_T("AVC_TS_MP_SD_AAC_MULT5_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_AAC_MULT5_ISO("AVC_TS_MP_SD_AAC_MULT5_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_SD_HEAAC_L2("AVC_TS_MP_SD_HEAAC_L2", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_HEAAC_L2_T("AVC_TS_MP_SD_HEAAC_L2_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_HEAAC_L2_ISO("AVC_TS_MP_SD_HEAAC_L2_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_SD_MPEG1_L3("AVC_TS_MP_SD_MPEG1_L3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_MPEG1_L3_T("AVC_TS_MP_SD_MPEG1_L3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_MPEG1_L3_ISO("AVC_TS_MP_SD_MPEG1_L3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_SD_AC3("AVC_TS_MP_SD_AC3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_AC3_T("AVC_TS_MP_SD_AC3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_AC3_ISO("AVC_TS_MP_SD_AC3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_SD_AAC_LTP("AVC_TS_MP_SD_AAC_LTP", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_AAC_LTP_T("AVC_TS_MP_SD_AAC_LTP_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_AAC_LTP_ISO("AVC_TS_MP_SD_AAC_LTP_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_SD_AAC_LTP_MULT5("AVC_TS_MP_SD_AAC_LTP_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_AAC_LTP_MULT5_T("AVC_TS_MP_SD_AAC_LTP_MULT5_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_AAC_LTP_MULT5_ISO("AVC_TS_MP_SD_AAC_LTP_MULT5_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_SD_AAC_LTP_MULT7("AVC_TS_MP_SD_AAC_LTP_MULT7", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_AAC_LTP_MULT7_T("AVC_TS_MP_SD_AAC_LTP_MULT7_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_AAC_LTP_MULT7_ISO("AVC_TS_MP_SD_AAC_LTP_MULT7_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_SD_BSAC("AVC_TS_MP_SD_BSAC", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_BSAC_T("AVC_TS_MP_SD_BSAC_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_SD_BSAC_ISO("AVC_TS_MP_SD_BSAC_ISO",DLNAMimeTypes.MIME_VIDEO_MPEG), - - AVC_TS_HD_24_AC3("AVC_TS_HD_24_AC3",DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_HD_24_AC3_T("AVC_TS_HD_24_AC3_T",DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_HD_24_AC3_ISO("AVC_TS_HD_24_AC3_ISO",DLNAMimeTypes.MIME_VIDEO_MPEG), - - AVC_TS_HD_50_LPCM_T("AVC_TS_HD_50_LPCM_T",DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_HD_50_AC3("AVC_TS_HD_50_AC3",DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_HD_50_AC3_T("AVC_TS_HD_50_AC3_T",DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_HD_50_AC3_ISO("AVC_TS_HD_50_AC3_ISO",DLNAMimeTypes.MIME_VIDEO_MPEG), - - AVC_TS_HD_60_AC3("AVC_TS_HD_60_AC3",DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_HD_60_AC3_T("AVC_TS_HD_60_AC3_T",DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_HD_60_AC3_ISO("AVC_TS_HD_60_AC3_ISO",DLNAMimeTypes.MIME_VIDEO_MPEG), - - AVC_TS_BL_CIF30_AAC_MULT5("AVC_TS_BL_CIF30_AAC_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_AAC_MULT5_T("AVC_TS_BL_CIF30_AAC_MULT5_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_AAC_MULT5_ISO("AVC_TS_BL_CIF30_AAC_MULT5_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_BL_CIF30_HEAAC_L2("AVC_TS_BL_CIF30_HEAAC_L2", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_HEAAC_L2_T("AVC_TS_BL_CIF30_HEAAC_L2_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_HEAAC_L2_ISO("AVC_TS_BL_CIF30_HEAAC_L2_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_BL_CIF30_MPEG1_L3("AVC_TS_BL_CIF30_MPEG1_L3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_MPEG1_L3_T("AVC_TS_BL_CIF30_MPEG1_L3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_MPEG1_L3_ISO("AVC_TS_BL_CIF30_MPEG1_L3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_BL_CIF30_AC3("AVC_TS_BL_CIF30_AC3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_AC3_T("AVC_TS_BL_CIF30_AC3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_AC3_ISO("AVC_TS_BL_CIF30_AC3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_BL_CIF30_AAC_LTP("AVC_TS_BL_CIF30_AAC_LTP", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_AAC_LTP_T("AVC_TS_BL_CIF30_AAC_LTP_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_AAC_LTP_ISO("AVC_TS_BL_CIF30_AAC_LTP_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_BL_CIF30_AAC_LTP_MULT5("AVC_TS_BL_CIF30_AAC_LTP_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_AAC_LTP_MULT5_T("AVC_TS_BL_CIF30_AAC_LTP_MULT5_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_AAC_LTP_MULT5_ISO("AVC_TS_BL_CIF30_AAC_LTP_MULT5_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_BL_CIF30_AAC_940("AVC_TS_BL_CIF30_AAC_940", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_AAC_940_T("AVC_TS_BL_CIF30_AAC_940_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF30_AAC_940_ISO("AVC_TS_BL_CIF30_AAC_940_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - - AVC_TS_MP_HD_AAC_MULT5("AVC_TS_MP_HD_AAC_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AAC_MULT5_T("AVC_TS_MP_HD_AAC_MULT5_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AAC_MULT5_ISO("AVC_TS_MP_HD_AAC_MULT5_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_HD_HEAAC_L2("AVC_TS_MP_HD_HEAAC_L2", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_HEAAC_L2_T("AVC_TS_MP_HD_HEAAC_L2_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_HEAAC_L2_ISO("AVC_TS_MP_HD_HEAAC_L2_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_HD_MPEG1_L3("AVC_TS_MP_HD_MPEG1_L3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_MPEG1_L3_T("AVC_TS_MP_HD_MPEG1_L3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_MPEG1_L3_ISO("AVC_TS_MP_HD_MPEG1_L3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_HD_AC3("AVC_TS_MP_HD_AC3", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AC3_T("AVC_TS_MP_HD_AC3_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AC3_ISO("AVC_TS_MP_HD_AC3_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_HD_AAC("AVC_TS_MP_HD_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AAC_T("AVC_TS_MP_HD_AAC_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AAC_ISO("AVC_TS_MP_HD_AAC_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_HD_AAC_LTP("AVC_TS_MP_HD_AAC_LTP", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AAC_LTP_T("AVC_TS_MP_HD_AAC_LTP_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AAC_LTP_ISO("AVC_TS_MP_HD_AAC_LTP_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_HD_AAC_LTP_MULT5("AVC_TS_MP_HD_AAC_LTP_MULT5", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AAC_LTP_MULT5_T("AVC_TS_MP_HD_AAC_LTP_MULT5_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AAC_LTP_MULT5_ISO("AVC_TS_MP_HD_AAC_LTP_MULT5_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_MP_HD_AAC_LTP_MULT7("AVC_TS_MP_HD_AAC_LTP_MULT7", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AAC_LTP_MULT7_T("AVC_TS_MP_HD_AAC_LTP_MULT7_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_MP_HD_AAC_LTP_MULT7_ISO("AVC_TS_MP_HD_AAC_LTP_MULT7_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - - AVC_TS_BL_CIF15_AAC("AVC_TS_BL_CIF15_AAC", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF15_AAC_T("AVC_TS_BL_CIF15_AAC_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF15_AAC_ISO("AVC_TS_BL_CIF15_AAC_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_BL_CIF15_AAC_540("AVC_TS_BL_CIF15_AAC_540", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF15_AAC_540_T("AVC_TS_BL_CIF15_AAC_540_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF15_AAC_540_ISO("AVC_TS_BL_CIF15_AAC_540_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_BL_CIF15_AAC_LTP("AVC_TS_BL_CIF15_AAC_LTP", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF15_AAC_LTP_T("AVC_TS_BL_CIF15_AAC_LTP_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF15_AAC_LTP_ISO("AVC_TS_BL_CIF15_AAC_LTP_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - AVC_TS_BL_CIF15_BSAC("AVC_TS_BL_CIF15_BSAC", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF15_BSAC_T("AVC_TS_BL_CIF15_BSAC_T", DLNAMimeTypes.MIME_VIDEO_MPEG_TS), - AVC_TS_BL_CIF15_BSAC_ISO("AVC_TS_BL_CIF15_BSAC_ISO", DLNAMimeTypes.MIME_VIDEO_MPEG), - - - AVC_3GPP_BL_CIF30_AMR_WBplus("AVC_3GPP_BL_CIF30_AMR_WBplus", DLNAMimeTypes.MIME_VIDEO_3GP), - AVC_3GPP_BL_CIF15_AMR_WBplus("AVC_3GPP_BL_CIF15_AMR_WBplus", DLNAMimeTypes.MIME_VIDEO_3GP), - AVC_3GPP_BL_QCIF15_AAC("AVC_3GPP_BL_QCIF15_AAC", DLNAMimeTypes.MIME_VIDEO_3GP), - AVC_3GPP_BL_QCIF15_AAC_LTP("AVC_3GPP_BL_QCIF15_AAC_LTP", DLNAMimeTypes.MIME_VIDEO_3GP), - AVC_3GPP_BL_QCIF15_HEAAC("AVC_3GPP_BL_QCIF15_HEAAC", DLNAMimeTypes.MIME_VIDEO_3GP), - AVC_3GPP_BL_QCIF15_AMR_WBplus("AVC_3GPP_BL_QCIF15_AMR_WBplus", DLNAMimeTypes.MIME_VIDEO_3GP), - AVC_3GPP_BL_QCIF15_AMR("AVC_3GPP_BL_QCIF15_AMR", DLNAMimeTypes.MIME_VIDEO_3GP), - - AVC_MP4_LPCM("AVC_MP4_LPCM", DLNAMimeTypes.MIME_VIDEO_MPEG_4), - - AVI("AVI", DLNAMimeTypes.MIME_VIDEO_AVI), - AVI_XMS("AVI", DLNAMimeTypes.MIME_VIDEO_XMS_AVI), - DIVX("AVI", DLNAMimeTypes.MIME_VIDEO_DIVX), - - MATROSKA("MATROSKA", DLNAMimeTypes.MIME_VIDEO_MATROSKA), - MATROSKA_MKV("MATROSKA", DLNAMimeTypes.MIME_VIDEO_MKV), - - VC1_ASF_AP_L1_WMA("VC1_ASF_AP_L1_WMA", DLNAMimeTypes.MIME_VIDEO_ASF), - VC1_ASF_AP_L2_WMA("VC1_ASF_AP_L2_WMA", DLNAMimeTypes.MIME_VIDEO_ASF), - VC1_ASF_AP_L3_WMA("VC1_ASF_AP_L3_WMA", DLNAMimeTypes.MIME_VIDEO_ASF), - - VC1_ASF_AP_L1_WMA_WMV("VC1_ASF_AP_L1_WMA", DLNAMimeTypes.MIME_VIDEO_WMV), - VC1_ASF_AP_L2_WMA_WMV("VC1_ASF_AP_L2_WMA", DLNAMimeTypes.MIME_VIDEO_WMV), - VC1_ASF_AP_L3_WMA_WMV("VC1_ASF_AP_L3_WMA", DLNAMimeTypes.MIME_VIDEO_WMV); - - private String code; - private String contentFormat; - - DLNAProfiles(String code, String contentFormat) { - this.code = code; - this.contentFormat = contentFormat; - } - - public String getCode() { - return code; - } - - public String getContentFormat() { - return contentFormat; - } - - public static DLNAProfiles valueOf(String code, String contentFormat) { - for (DLNAProfiles errorCode : values()) { - if (errorCode.getCode().equals(code) && - (contentFormat.length() == 0 || errorCode.getContentFormat().equals(contentFormat))) { - return errorCode; - } - } - return null; - } - - class DLNAMimeTypes { - public static final String MIME_IMAGE_JPEG = "image/jpeg"; - public static final String MIME_IMAGE_PNG = "image/png"; - - public static final String MIME_AUDIO_3GP = "audio/3gpp"; - public static final String MIME_AUDIO_ADTS = "audio/vnd.dlna.adts"; - public static final String MIME_AUDIO_ATRAC = "audio/x-sony-oma"; - public static final String MIME_AUDIO_DOLBY_DIGITAL = "audio/vnd.dolby.dd-raw"; - public static final String MIME_AUDIO_LPCM = "audio/L16"; - public static final String MIME_AUDIO_MPEG = "audio/mpeg"; - public static final String MIME_AUDIO_MPEG_4 = "audio/mp4"; - public static final String MIME_AUDIO_WMA = "audio/x-ms-wma"; - - public static final String MIME_VIDEO_3GP = "video/3gpp"; - public static final String MIME_VIDEO_ASF = "video/x-ms-asf"; - public static final String MIME_VIDEO_MPEG = "video/mpeg"; - public static final String MIME_VIDEO_MPEG_4 = "video/mp4"; - public static final String MIME_VIDEO_MPEG_TS = "video/vnd.dlna.mpeg-tts"; - public static final String MIME_VIDEO_WMV = "video/x-ms-wmv"; - public static final String MIME_VIDEO_DIVX = "video/divx"; - public static final String MIME_VIDEO_AVI = "video/avi"; - public static final String MIME_VIDEO_XMS_AVI = "video/x-msvideo"; - public static final String MIME_VIDEO_MATROSKA = "video/x-matroska"; - public static final String MIME_VIDEO_MKV = "video/x-mkv"; - - } -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProtocolInfo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProtocolInfo.java deleted file mode 100644 index c61b3a1..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/DLNAProtocolInfo.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna; - -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.support.model.Protocol; -import org.fourthline.cling.support.model.ProtocolInfo; -import org.seamless.util.MimeType; - -import java.util.EnumMap; -import java.util.Map; - -/** - * Encaspulates a MIME type (content format) and transport, protocol, additional information. - *

- * Parses DLNA attributes in the additional information. - * - * @author Mario Franco - */ -public class DLNAProtocolInfo extends ProtocolInfo { - - protected final Map attributes = new EnumMap<>(DLNAAttribute.Type.class); - - public DLNAProtocolInfo(String s) throws InvalidValueException { - super(s); - parseAdditionalInfo(); - } - - public DLNAProtocolInfo(MimeType contentFormatMimeType) { - super(contentFormatMimeType); - } - - public DLNAProtocolInfo(DLNAProfiles profile) { - super(MimeType.valueOf(profile.getContentFormat())); - this.attributes.put(DLNAAttribute.Type.DLNA_ORG_PN, new DLNAProfileAttribute(profile)); - this.additionalInfo = this.getAttributesString(); - } - - public DLNAProtocolInfo(DLNAProfiles profile, EnumMap attributes) { - super(MimeType.valueOf(profile.getContentFormat())); - this.attributes.putAll(attributes); - this.attributes.put(DLNAAttribute.Type.DLNA_ORG_PN, new DLNAProfileAttribute(profile)); - this.additionalInfo = this.getAttributesString(); - } - - public DLNAProtocolInfo(Protocol protocol, String network, String contentFormat, String additionalInfo) { - super(protocol, network, contentFormat, additionalInfo); - parseAdditionalInfo(); - } - - public DLNAProtocolInfo(Protocol protocol, String network, String contentFormat, EnumMap attributes) { - super(protocol, network, contentFormat, ""); - this.attributes.putAll(attributes); - this.additionalInfo = this.getAttributesString(); - } - - public DLNAProtocolInfo(ProtocolInfo template) { - this(template.getProtocol(), - template.getNetwork(), - template.getContentFormat(), - template.getAdditionalInfo() - ); - } - - public boolean contains(DLNAAttribute.Type type) { - return attributes.containsKey(type); - } - - public DLNAAttribute getAttribute(DLNAAttribute.Type type) { - return attributes.get(type); - } - - public Map getAttributes() { - return attributes; - } - - protected String getAttributesString() { - String s = ""; - for (DLNAAttribute.Type type : DLNAAttribute.Type.values() ) { - String value = attributes.containsKey(type)?attributes.get(type).getString():null; - if (value!=null && value.length() != 0) - s += (s.length() == 0 ? "" : ";") + type.getAttributeName() + "=" + value; - } - return s; - } - - protected void parseAdditionalInfo() { - if (additionalInfo != null) { - String[] atts = additionalInfo.split(";"); - for (String att : atts) { - String[] attNameValue = att.split("="); - if (attNameValue.length == 2) { - DLNAAttribute.Type type = - DLNAAttribute.Type.valueOfAttributeName(attNameValue[0]); - if (type != null) { - DLNAAttribute dlnaAttrinute = - DLNAAttribute.newInstance(type, attNameValue[1], this.getContentFormat()); - attributes.put(type, dlnaAttrinute); - } - } - } - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/InvalidDLNAProtocolAttributeException.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/InvalidDLNAProtocolAttributeException.java deleted file mode 100644 index 4118c71..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/InvalidDLNAProtocolAttributeException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.dlna; - -/** - * Thrown if the value of a header was invalid for the given header. - * - * @author Mario Franco - */ -public class InvalidDLNAProtocolAttributeException extends RuntimeException { - - public InvalidDLNAProtocolAttributeException(String s) { - super(s); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/DLNAHeaders.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/DLNAHeaders.java deleted file mode 100644 index 45fcc53..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/DLNAHeaders.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.dlna.message; - -import org.fourthline.cling.model.message.header.UpnpHeader; - -import java.io.ByteArrayInputStream; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.support.model.dlna.message.header.DLNAHeader; - -/** - * Provides UPnP header API in addition to plain multi-map HTTP header access. - * - * @author Mario Franco - * @author Christian Bauer - */ -public class DLNAHeaders extends UpnpHeaders { - - private static final Logger log = Logger.getLogger(DLNAHeaders.class.getName()); - - protected Map> parsedDLNAHeaders; - - public DLNAHeaders() { - } - - public DLNAHeaders(Map> headers) { - super(headers); - } - - public DLNAHeaders(ByteArrayInputStream inputStream) { - super(inputStream); - } - - @Override - protected void parseHeaders() { - if (parsedHeaders == null) super.parseHeaders(); - - // This runs as late as possible and only when necessary (getter called and map is dirty) - parsedDLNAHeaders = new LinkedHashMap<>(); - log.log(Level.FINE, "Parsing all HTTP headers for known UPnP headers: {0}", size()); - for (Entry> entry : entrySet()) { - - if (entry.getKey() == null) continue; // Oh yes, the JDK has 'null' HTTP headers - - DLNAHeader.Type type = DLNAHeader.Type.getByHttpName(entry.getKey()); - if (type == null) { - log.log(Level.FINE, "Ignoring non-UPNP HTTP header: {0}", entry.getKey()); - continue; - } - - for (String value : entry.getValue()) { - UpnpHeader upnpHeader = DLNAHeader.newInstance(type, value); - if (upnpHeader == null || upnpHeader.getValue() == null) { - log.log(Level.FINE, "Ignoring known but non-parsable header (value violates the UDA specification?) '{0}': {1}", new Object[]{type.getHttpName(), value}); - } else { - addParsedValue(type, upnpHeader); - } - } - } - } - - protected void addParsedValue(DLNAHeader.Type type, UpnpHeader value) { - log.log(Level.FINE, "Adding parsed header: {0}", value); - List list = parsedDLNAHeaders.get(type); - if (list == null) { - list = new LinkedList<>(); - parsedDLNAHeaders.put(type, list); - } - list.add(value); - } - - @Override - public List put(String key, List values) { - parsedDLNAHeaders = null; - return super.put(key, values); - } - - @Override - public void add(String key, String value) { - parsedDLNAHeaders = null; - super.add(key, value); - } - - @Override - public List remove(Object key) { - parsedDLNAHeaders = null; - return super.remove(key); - } - - @Override - public void clear() { - parsedDLNAHeaders = null; - super.clear(); - } - - public boolean containsKey(DLNAHeader.Type type) { - if (parsedDLNAHeaders == null) parseHeaders(); - return parsedDLNAHeaders.containsKey(type); - } - - public List get(DLNAHeader.Type type) { - if (parsedDLNAHeaders == null) parseHeaders(); - return parsedDLNAHeaders.get(type); - } - - public void add(DLNAHeader.Type type, UpnpHeader value) { - super.add(type.getHttpName(), value.getString()); - if (parsedDLNAHeaders != null) - addParsedValue(type, value); - } - - public void remove(DLNAHeader.Type type) { - super.remove(type.getHttpName()); - if (parsedDLNAHeaders != null) - parsedDLNAHeaders.remove(type); - } - - public UpnpHeader[] getAsArray(DLNAHeader.Type type) { - if (parsedDLNAHeaders == null) parseHeaders(); - return parsedDLNAHeaders.get(type) != null - ? parsedDLNAHeaders.get(type).toArray(new UpnpHeader[parsedDLNAHeaders.get(type).size()]) - : new UpnpHeader[0]; - } - - public UpnpHeader getFirstHeader(DLNAHeader.Type type) { - return getAsArray(type).length > 0 - ? getAsArray(type)[0] - : null; - } - - public H getFirstHeader(DLNAHeader.Type type, Class subtype) { - UpnpHeader[] headers = getAsArray(type); - if (headers.length == 0) return null; - - for (UpnpHeader header : headers) { - if (subtype.isAssignableFrom(header.getClass())) { - return (H) header; - } - } - return null; - } - - @Override - public void log() { - if (log.isLoggable(Level.FINE)) { - super.log(); - if (parsedDLNAHeaders != null && parsedDLNAHeaders.size() > 0) { - log.fine("########################## PARSED DLNA HEADERS ##########################"); - for (Map.Entry> entry : parsedDLNAHeaders.entrySet()) { - log.log(Level.FINE, "=== TYPE: {0}", entry.getKey()); - for (UpnpHeader upnpHeader : entry.getValue()) { - log.log(Level.FINE, "HEADER: {0}", upnpHeader); - } - } - } - log.fine("####################################################################"); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/AvailableRangeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/AvailableRangeHeader.java deleted file mode 100644 index 22a74fb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/AvailableRangeHeader.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.support.model.dlna.types.NormalPlayTimeRange; - -/** - * @author Mario Franco - */ -public class AvailableRangeHeader extends DLNAHeader { - - public AvailableRangeHeader() { - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - try { - setValue(NormalPlayTimeRange.valueOf(s, true)); - return; - } catch (Exception ex) {} - } - throw new InvalidHeaderException("Invalid AvailableRange header value: " + s); - } - - @Override - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/AvailableSeekRangeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/AvailableSeekRangeHeader.java deleted file mode 100644 index 7dcc29d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/AvailableSeekRangeHeader.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.model.types.BytesRange; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.support.model.dlna.types.AvailableSeekRangeType; -import org.fourthline.cling.support.model.dlna.types.NormalPlayTimeRange; - -/** - * @author Mario Franco - */ -public class AvailableSeekRangeHeader extends DLNAHeader { - - public AvailableSeekRangeHeader() { - } - - public AvailableSeekRangeHeader(AvailableSeekRangeType timeSeekRange) { - setValue(timeSeekRange); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - String[] params = s.split(" "); - if (params.length > 1) { - try { - AvailableSeekRangeType.Mode mode = null; - NormalPlayTimeRange timeRange = null; - BytesRange byteRange = null; - - //Parse Mode - try { - mode = AvailableSeekRangeType.Mode.valueOf("MODE_" + params[0]); - } catch (IllegalArgumentException e) { - throw new InvalidValueException("Invalid AvailableSeekRange Mode"); - } - - boolean useTime = true; - //Parse Second Token - try { - timeRange = NormalPlayTimeRange.valueOf(params[1],true); - } catch (InvalidValueException timeInvalidValueException) { - try { - byteRange = BytesRange.valueOf(params[1]); - useTime = false; - } catch (InvalidValueException bytesInvalidValueException) { - throw new InvalidValueException("Invalid AvailableSeekRange Range"); - } - } - if (useTime) { - if (params.length > 2) { - //Parse Third Token - byteRange = BytesRange.valueOf(params[2]); - setValue(new AvailableSeekRangeType(mode, timeRange, byteRange)); - } - else { - setValue(new AvailableSeekRangeType(mode, timeRange)); - } - } else { - setValue(new AvailableSeekRangeType(mode, byteRange)); - } - return; - } catch (InvalidValueException invalidValueException) { - throw new InvalidHeaderException("Invalid AvailableSeekRange header value: " + s + "; " + invalidValueException.getMessage()); - } - } - } - throw new InvalidHeaderException("Invalid AvailableSeekRange header value: " + s); - } - - @Override - public String getString() { - AvailableSeekRangeType t = getValue(); - String s = Integer.toString(t.getModeFlag().ordinal()); - if (t.getNormalPlayTimeRange() != null) { - s += " " + t.getNormalPlayTimeRange().getString(false); - } - if (t.getBytesRange() != null) { - s += " " + t.getBytesRange().getString(false); - } - return s; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/BufferBytesHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/BufferBytesHeader.java deleted file mode 100644 index 284d1ab..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/BufferBytesHeader.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -/** - * @author Mario Franco - */ -public class BufferBytesHeader extends DLNAHeader { - - public BufferBytesHeader() { - setValue(new UnsignedIntegerFourBytes(0L)); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - try { - setValue(new UnsignedIntegerFourBytes(s)); - return; - } catch (NumberFormatException numberFormatException) { - } - throw new InvalidHeaderException("Invalid header value: " + s); - } - - @Override - public String getString() { - return getValue().getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/BufferInfoHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/BufferInfoHeader.java deleted file mode 100644 index c5774ce..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/BufferInfoHeader.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.support.model.dlna.types.BufferInfoType; - -/** - * @author Mario Franco - */ -public class BufferInfoHeader extends DLNAHeader { - - public BufferInfoHeader() { - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - try { - setValue(BufferInfoType.valueOf(s)); - return; - } catch (Exception ex) {} - } - throw new InvalidHeaderException("Invalid BufferInfo header value: " + s); - } - - @Override - public String getString() { - return getValue().getString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/ContentFeaturesHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/ContentFeaturesHeader.java deleted file mode 100644 index 7640acd..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/ContentFeaturesHeader.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import java.util.EnumMap; -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.support.model.dlna.DLNAAttribute; - -/** - * @author Mario Franco - */ -public class ContentFeaturesHeader extends DLNAHeader> { - - public ContentFeaturesHeader() { - setValue(new EnumMap(DLNAAttribute.Type.class)); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - String[] atts = s.split(";"); - for (String att : atts) { - String[] attNameValue = att.split("="); - if (attNameValue.length == 2) { - DLNAAttribute.Type type = DLNAAttribute.Type.valueOfAttributeName(attNameValue[0]); - if (type != null) { - DLNAAttribute dlnaAttrinute = DLNAAttribute.newInstance(type, attNameValue[1], ""); - getValue().put(type, dlnaAttrinute); - } - } - } - } - } - - @Override - public String getString() { - String s = ""; - for (DLNAAttribute.Type type : DLNAAttribute.Type.values()) { - String value = getValue().containsKey(type) ? getValue().get(type).getString() : null; - if (value != null && value.length() != 0) { - s += (s.length() == 0 ? "" : ";") + type.getAttributeName() + "=" + value; - } - } - return s; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/DLNAHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/DLNAHeader.java deleted file mode 100644 index 9eceb34..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/DLNAHeader.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.dlna.message.header; - -import org.seamless.util.Exceptions; - -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.model.message.header.UpnpHeader; - -/** - * Transforms known and standardized DLNA/HTTP headers from/to string representation. - *

- * The {@link #newInstance(org.fourthline.cling.support.model.dlna.message.header.DLNAHeader.Type, String)} method - * attempts to instantiate the best header subtype for a given header (name) and string value. - *

- * - * @author Mario Franco - * @author Christian Bauer - */ -public abstract class DLNAHeader extends UpnpHeader { - - final private static Logger log = Logger.getLogger(DLNAHeader.class.getName()); - - /** - * Maps a standardized DLNA header to potential header subtypes. - */ - public static enum Type { - - TimeSeekRange("TimeSeekRange.dlna.org", TimeSeekRangeHeader.class), - XSeekRange("X-Seek-Range", TimeSeekRangeHeader.class), - PlaySpeed("PlaySpeed.dlna.org", PlaySpeedHeader.class), - AvailableSeekRange("availableSeekRange.dlna.org", AvailableSeekRangeHeader.class), - GetAvailableSeekRange("getAvailableSeekRange.dlna.org", GetAvailableSeekRangeHeader.class), - GetContentFeatures("getcontentFeatures.dlna.org", GetContentFeaturesHeader.class), - ContentFeatures("contentFeatures.dlna.org", ContentFeaturesHeader.class), - TransferMode("transferMode.dlna.org", TransferModeHeader.class), - FriendlyName("friendlyName.dlna.org", FriendlyNameHeader.class), - PeerManager("peerManager.dlna.org", PeerManagerHeader.class), - AvailableRange("Available-Range.dlna.org", AvailableRangeHeader.class), - SCID("scid.dlna.org", SCIDHeader.class), - RealTimeInfo("realTimeInfo.dlna.org", RealTimeInfoHeader.class), - ScmsFlag("scmsFlag.dlna.org", ScmsFlagHeader.class), - WCT("WCT.dlna.org", WCTHeader.class), - MaxPrate("Max-Prate.dlna.org", MaxPrateHeader.class), - EventType("Event-Type.dlna.org", EventTypeHeader.class), - Supported("Supported", SupportedHeader.class), - BufferInfo("Buffer-Info.dlna.org", BufferInfoHeader.class), - RTPH264DeInterleaving("rtp-h264-deint-buf-cap.dlna.org", BufferBytesHeader.class), - RTPAACDeInterleaving("rtp-aac-deint-buf-cap.dlna.org", BufferBytesHeader.class), - RTPAMRDeInterleaving("rtp-amr-deint-buf-cap.dlna.org", BufferBytesHeader.class), - RTPAMRWBPlusDeInterleaving("rtp-amrwbplus-deint-buf-cap.dlna.org", BufferBytesHeader.class), - PRAGMA("PRAGMA", PragmaHeader.class); - - private static Map byName = new HashMap() {{ - for (Type t : Type.values()) { - put(t.getHttpName(), t); - } - }}; - - private String httpName; - private Class[] headerTypes; - - @SafeVarargs - private Type(String httpName, Class... headerClass) { - this.httpName = httpName; - this.headerTypes = headerClass; - } - - public String getHttpName() { - return httpName; - } - - public Class[] getHeaderTypes() { - return headerTypes; - } - - public boolean isValidHeaderType(Class clazz) { - for (Class permissibleType : getHeaderTypes()) { - if (permissibleType.isAssignableFrom(clazz)) { - return true; - } - } - return false; - } - - /** - * @param httpName A case-insensitive HTTP header name. - */ - public static Type getByHttpName(String httpName) { - if (httpName == null) return null; - return byName.get(httpName); - } - } - - - - /** - * Create a new instance of a {@link DLNAHeader} subtype that matches the given type and value. - *

- * This method iterates through all potential header subtype classes as declared in {@link Type}. - * It creates a new instance of the subtype class and calls its {@link #setString(String)} method. - * If no {@link org.fourthline.cling.model.message.header.InvalidHeaderException} is thrown, the subtype - * instance is returned. - *

- * - * @param type The type (or name) of the header. - * @param headerValue The value of the header. - * @return The best matching header subtype instance, or null if no subtype can be found. - */ - public static DLNAHeader newInstance(DLNAHeader.Type type, String headerValue) { - - // Try all the UPnP headers and see if one matches our value parsers - DLNAHeader upnpHeader = null; - for (int i = 0; i < type.getHeaderTypes().length && upnpHeader == null; i++) { - Class headerClass = type.getHeaderTypes()[i]; - try { - log.finest("Trying to parse '" + type + "' with class: " + headerClass.getSimpleName()); - upnpHeader = headerClass.newInstance(); - if (headerValue != null) { - upnpHeader.setString(headerValue); - } - } catch (InvalidHeaderException ex) { - log.finest("Invalid header value for tested type: " + headerClass.getSimpleName() + " - " + ex.getMessage()); - upnpHeader = null; - } catch (Exception ex) { - log.severe("Error instantiating header of type '" + type + "' with value: " + headerValue); - log.log(Level.SEVERE, "Exception root cause: ", Exceptions.unwrap(ex)); - } - - } - return upnpHeader; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/EventTypeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/EventTypeHeader.java deleted file mode 100644 index 044b437..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/EventTypeHeader.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import java.util.regex.Pattern; -import org.fourthline.cling.model.message.header.InvalidHeaderException; - -/** - * @author Mario Franco - */ -public class EventTypeHeader extends DLNAHeader { - - final static Pattern pattern = Pattern.compile("^[0-9]{4}$", Pattern.CASE_INSENSITIVE); - - public EventTypeHeader() { - setValue("0000"); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (pattern.matcher(s).matches()) { - setValue(s); - return; - } - throw new InvalidHeaderException("Invalid EventType header value: " + s); - } - - @Override - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/FriendlyNameHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/FriendlyNameHeader.java deleted file mode 100644 index fd57c3d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/FriendlyNameHeader.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; - -/** - * @author Mario Franco - */ -public class FriendlyNameHeader extends DLNAHeader { - - public FriendlyNameHeader() { - setValue(""); - } - - public FriendlyNameHeader(String name) { - setValue(name); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - setValue(s); - return; - } - throw new InvalidHeaderException("Invalid GetAvailableSeekRange header value: " + s); - } - - @Override - public String getString() { - return getValue(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/GetAvailableSeekRangeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/GetAvailableSeekRangeHeader.java deleted file mode 100644 index 1468d1f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/GetAvailableSeekRangeHeader.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; - -/** - * @author Mario Franco - */ -public class GetAvailableSeekRangeHeader extends DLNAHeader { - - public GetAvailableSeekRangeHeader() { - setValue(1); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - try { - int t = Integer.parseInt(s); - if (t==1) - return; - } catch (Exception ex) {} - } - throw new InvalidHeaderException("Invalid GetAvailableSeekRange header value: " + s); - } - - @Override - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/GetContentFeaturesHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/GetContentFeaturesHeader.java deleted file mode 100644 index 6f90a0c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/GetContentFeaturesHeader.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; - -/** - * @author Mario Franco - */ -public class GetContentFeaturesHeader extends DLNAHeader { - - public GetContentFeaturesHeader() { - setValue(1); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - try { - int t = Integer.parseInt(s); - if (t==1) - return; - } catch (Exception ex) {} - } - throw new InvalidHeaderException("Invalid GetContentFeatures header value: " + s); - } - - @Override - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/MaxPrateHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/MaxPrateHeader.java deleted file mode 100644 index db40c03..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/MaxPrateHeader.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; - -/** - * @author Mario Franco - */ -public class MaxPrateHeader extends DLNAHeader { - - public MaxPrateHeader() { - setValue(0L); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - try { - setValue(Long.parseLong(s)); - return; - } catch (NumberFormatException numberFormatException) { - } - throw new InvalidHeaderException("Invalid SCID header value: " + s); - } - - @Override - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PeerManagerHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PeerManagerHeader.java deleted file mode 100644 index dc0eb17..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PeerManagerHeader.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.ServiceReference; -import org.fourthline.cling.model.message.header.InvalidHeaderException; - -/** - * @author Mario Franco - */ -public class PeerManagerHeader extends DLNAHeader { - - public PeerManagerHeader() { - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - try { - ServiceReference serviceReference = new ServiceReference(s); - if (serviceReference.getUdn()!=null && serviceReference.getServiceId()!=null) { - setValue(serviceReference); - return; - } - } catch (Exception ex) { - } - } - throw new InvalidHeaderException("Invalid PeerManager header value: " + s); - } - - @Override - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PlaySpeedHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PlaySpeedHeader.java deleted file mode 100644 index 5f6e484..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PlaySpeedHeader.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.support.avtransport.lastchange.AVTransportVariable.TransportPlaySpeed; - -/** - * @author Mario Franco - */ -public class PlaySpeedHeader extends DLNAHeader { - - public PlaySpeedHeader() { - } - - public PlaySpeedHeader(TransportPlaySpeed speed) { - setValue(speed); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - try { - TransportPlaySpeed t = new TransportPlaySpeed(s); - setValue(t); - return; - } catch (InvalidValueException invalidValueException) {} - } - throw new InvalidHeaderException("Invalid PlaySpeed header value: " + s); - } - - @Override - public String getString() { - return getValue().getValue(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PragmaHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PragmaHeader.java deleted file mode 100644 index e04a6a9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/PragmaHeader.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import java.util.ArrayList; -import java.util.List; -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.model.types.PragmaType; - -/** - * DLNA Pragma tokens: - * - getIfoFileURI.dlna.org - * - ifoFileURI.dlna.org - * - * @author Mario Franco - */ -public class PragmaHeader extends DLNAHeader> { - - public PragmaHeader() { - setValue(new ArrayList()); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - if (s.endsWith(";")) { - s = s.substring(0, s.length() - 1); - } - String[] list = s.split("\\s*;\\s*"); - List value = new ArrayList<>(); - for (String pragma : list) { - value.add(PragmaType.valueOf(pragma)); - } - return; - } - throw new InvalidHeaderException("Invalid Pragma header value: " + s); - } - - @Override - public String getString() { - List v = getValue(); - String r = ""; - for (PragmaType pragma : v) { - r += (r.length() == 0 ? "": "," )+ pragma.getString(); - } - return r; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/RealTimeInfoHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/RealTimeInfoHeader.java deleted file mode 100644 index 821acf4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/RealTimeInfoHeader.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.support.model.dlna.types.NormalPlayTime; - -/** - * @author Mario Franco - */ -public class RealTimeInfoHeader extends DLNAHeader { - - public static final String PREFIX = "DLNA.ORG_TLAG="; - - public RealTimeInfoHeader() { - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0 && s.startsWith(PREFIX) ) { - try { - s = s.substring(PREFIX.length()); - setValue(s.equals("*") ? null : NormalPlayTime.valueOf(s) ); - return; - } catch (Exception ex) {} - } - throw new InvalidHeaderException("Invalid RealTimeInfo header value: " + s); - } - - @Override - public String getString() { - NormalPlayTime v = getValue(); - if (v == null) - return PREFIX+"*"; - return PREFIX+v.getString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/SCIDHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/SCIDHeader.java deleted file mode 100644 index be9998d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/SCIDHeader.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; - -/** - * @author Mario Franco - */ -public class SCIDHeader extends DLNAHeader { - - public SCIDHeader() { - setValue(""); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - setValue(s); - return; - } - throw new InvalidHeaderException("Invalid SCID header value: " + s); - } - - @Override - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/ScmsFlagHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/ScmsFlagHeader.java deleted file mode 100644 index 16d1a23..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/ScmsFlagHeader.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import java.util.regex.Pattern; -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.support.model.dlna.types.ScmsFlagType; - -/** - * @author Mario Franco - */ -public class ScmsFlagHeader extends DLNAHeader { - - final static Pattern pattern = Pattern.compile("^[01]{2}$", Pattern.CASE_INSENSITIVE); - - public ScmsFlagHeader() { - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (pattern.matcher(s).matches()) { - setValue(new ScmsFlagType(s.charAt(0) == '0', s.charAt(1) == '0')); - return; - } - throw new InvalidHeaderException("Invalid ScmsFlag header value: " + s); - } - - @Override - public String getString() { - ScmsFlagType v = getValue(); - return (v.isCopyright()?"0":"1") + (v.isOriginal()?"0":"1"); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/SupportedHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/SupportedHeader.java deleted file mode 100644 index 6917447..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/SupportedHeader.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; - -/** - * @author Mario Franco - */ -public class SupportedHeader extends DLNAHeader { - - public SupportedHeader() { - setValue(new String[]{}); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - if (s.endsWith(";")) - s = s.substring(0, s.length()-1); - setValue(s.split("\\s*,\\s*")); - return; - } - throw new InvalidHeaderException("Invalid Supported header value: " + s); - } - - @Override - public String getString() { - String[] v = getValue(); - String r = v.length>0 ? v[0] : ""; - for (int i = 1; i < v.length; i++) { - r += ","+v[i]; - } - return r; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/TimeSeekRangeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/TimeSeekRangeHeader.java deleted file mode 100644 index 408c018..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/TimeSeekRangeHeader.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; -import org.fourthline.cling.model.types.BytesRange; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.support.model.dlna.types.NormalPlayTimeRange; -import org.fourthline.cling.support.model.dlna.types.TimeSeekRangeType; - -/** - * @author Mario Franco - */ -public class TimeSeekRangeHeader extends DLNAHeader { - - public TimeSeekRangeHeader() { - } - - public TimeSeekRangeHeader(TimeSeekRangeType timeSeekRange) { - setValue(timeSeekRange); - } - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - String[] params = s.split(" "); - if (params.length>0) { - try { - TimeSeekRangeType t = new TimeSeekRangeType(NormalPlayTimeRange.valueOf(params[0])); - if (params.length > 1) { - t.setBytesRange(BytesRange.valueOf(params[1])); - } - setValue(t); - return; - } catch (InvalidValueException invalidValueException) { - throw new InvalidHeaderException("Invalid TimeSeekRange header value: " + s + "; "+invalidValueException.getMessage()); - } - } - } - throw new InvalidHeaderException("Invalid TimeSeekRange header value: " + s); - } - - @Override - public String getString() { - TimeSeekRangeType t = getValue(); - String s = t.getNormalPlayTimeRange().getString(); - if (t.getBytesRange()!=null) s+= " "+t.getBytesRange().getString(true); - return s; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/TransferModeHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/TransferModeHeader.java deleted file mode 100644 index a3d3938..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/TransferModeHeader.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import org.fourthline.cling.model.message.header.InvalidHeaderException; - -/** - * @author Mario Franco - */ -public class TransferModeHeader extends DLNAHeader { - - public enum Type { - Streaming, - Interactive, - Background; - } - - public TransferModeHeader() { - setValue(Type.Interactive); - } - - public TransferModeHeader(Type mode) { - setValue(mode); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (s.length() != 0) { - try { - setValue(TransferModeHeader.Type.valueOf(s)); - return; - } catch (Exception ex) {} - } - throw new InvalidHeaderException("Invalid TransferMode header value: " + s); - } - - @Override - public String getString() { - return getValue().toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/WCTHeader.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/WCTHeader.java deleted file mode 100644 index 22106df..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/message/header/WCTHeader.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.message.header; - -import java.util.regex.Pattern; -import org.fourthline.cling.model.message.header.InvalidHeaderException; - -/** - * @author Mario Franco - */ -public class WCTHeader extends DLNAHeader { - - final static Pattern pattern = Pattern.compile("^[01]{1}$", Pattern.CASE_INSENSITIVE); - - public WCTHeader() { - setValue(false); - } - - @Override - public void setString(String s) throws InvalidHeaderException { - if (pattern.matcher(s).matches()) { - setValue( s.equals("1")); - return; - } - throw new InvalidHeaderException("Invalid SCID header value: " + s); - } - - @Override - public String getString() { - return getValue() ? "1":"0"; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/AvailableSeekRangeType.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/AvailableSeekRangeType.java deleted file mode 100644 index 33d371f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/AvailableSeekRangeType.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.types; - -import org.fourthline.cling.model.types.BytesRange; - -/** - * - * @author Mario Franco - */ -public class AvailableSeekRangeType { - - - public enum Mode { - MODE_0, - MODE_1, - } - - private Mode modeFlag; - private NormalPlayTimeRange normalPlayTimeRange; - private BytesRange bytesRange; - - - public AvailableSeekRangeType(Mode modeFlag, NormalPlayTimeRange nptRange) { - this.modeFlag = modeFlag; - this.normalPlayTimeRange = nptRange; - } - - public AvailableSeekRangeType(Mode modeFlag, BytesRange byteRange) { - this.modeFlag = modeFlag; - this.bytesRange = byteRange; - } - - public AvailableSeekRangeType(Mode modeFlag, NormalPlayTimeRange nptRange, BytesRange byteRange) { - this.modeFlag = modeFlag; - this.normalPlayTimeRange = nptRange; - this.bytesRange = byteRange; - } - - /** - * @return the normalPlayTimeRange - */ - public NormalPlayTimeRange getNormalPlayTimeRange() { - return normalPlayTimeRange; - } - - /** - * @return the bytesRange - */ - public BytesRange getBytesRange() { - return bytesRange; - } - - /** - * @return the modeFlag - */ - public Mode getModeFlag() { - return modeFlag; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/BufferInfoType.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/BufferInfoType.java deleted file mode 100644 index e408126..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/BufferInfoType.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.types; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.support.model.dlna.types.CodedDataBuffer.TransferMechanism; - -/** - * - * @author Mario Franco - */ -public class BufferInfoType { - - final static Pattern pattern = Pattern.compile("^dejitter=(\\d{1,10})(;CDB=(\\d{1,10});BTM=(0|1|2))?(;TD=(\\d{1,10}))?(;BFR=(0|1))?$", Pattern.CASE_INSENSITIVE); - private Long dejitterSize; - private CodedDataBuffer cdb; - private Long targetDuration; - private Boolean fullnessReports; - - public BufferInfoType(Long dejitterSize) { - this.dejitterSize = dejitterSize; - } - - public BufferInfoType(Long dejitterSize, CodedDataBuffer cdb, - Long targetDuration, Boolean fullnessReports) { - this.dejitterSize = dejitterSize; - this.cdb = cdb; - this.targetDuration = targetDuration; - this.fullnessReports = fullnessReports; - } - - public static BufferInfoType valueOf(String s) throws InvalidValueException { - Matcher matcher = pattern.matcher(s); - if (matcher.matches()) { - try { - Long dejitterSize = Long.parseLong(matcher.group(1)); - CodedDataBuffer cdb = null; - Long targetDuration = null; - Boolean fullnessReports = null; - - if (matcher.group(2) != null) { - cdb = new CodedDataBuffer(Long.parseLong(matcher.group(3)), - TransferMechanism.values()[Integer.parseInt(matcher.group(4))]); - } - if (matcher.group(5) != null) { - targetDuration = Long.parseLong(matcher.group(6)); - } - if (matcher.group(7) != null) { - fullnessReports = matcher.group(8).equals("1"); - } - return new BufferInfoType(dejitterSize, cdb, targetDuration, fullnessReports); - } catch (NumberFormatException ex1) { - } - } - throw new InvalidValueException("Can't parse BufferInfoType: " + s); - } - - public String getString() { - String s = "dejitter=" + dejitterSize.toString(); - if (cdb != null) { - s += ";CDB=" + cdb.getSize().toString() + ";BTM=" + cdb.getTranfer().ordinal(); - } - if (targetDuration != null) { - s += ";TD=" + targetDuration.toString(); - } - if (fullnessReports != null) { - s += ";BFR=" + (fullnessReports?"1":"0"); - } - return s; - } - - /** - * @return the dejitter size - */ - public Long getDejitterSize() { - return dejitterSize; - } - - /** - * @return the cdb - */ - public CodedDataBuffer getCdb() { - return cdb; - } - - /** - * @return the targetDuration - */ - public Long getTargetDuration() { - return targetDuration; - } - - /** - * @return the fullnessReports - */ - public Boolean isFullnessReports() { - return fullnessReports; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/CodedDataBuffer.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/CodedDataBuffer.java deleted file mode 100644 index eb2972a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/CodedDataBuffer.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.types; - -/** - * - * @author Mario Franco - */ -public class CodedDataBuffer { - - public enum TransferMechanism { - IMMEDIATELY, - TIMESTAMP, - OTHER; - } - - private Long size; - private TransferMechanism tranfer; - - public CodedDataBuffer(Long size, TransferMechanism transfer) { - this.size = size; - this.tranfer = transfer; - } - - /** - * @return the size - */ - public Long getSize() { - return size; - } - - /** - * @return the tranfer - */ - public TransferMechanism getTranfer() { - return tranfer; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/NormalPlayTime.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/NormalPlayTime.java deleted file mode 100644 index dc3f46b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/NormalPlayTime.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.types; - -import java.util.Locale; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * @author Mario Franco - */ -public class NormalPlayTime { - - public enum Format { - - SECONDS, - TIME - } - final static Pattern pattern = Pattern.compile("^(\\d+):(\\d{1,2}):(\\d{1,2})(\\.(\\d{1,3}))?|(\\d+)(\\.(\\d{1,3}))?$", Pattern.CASE_INSENSITIVE); - private long milliseconds; - - public NormalPlayTime(long milliseconds) { - if (milliseconds < 0) { - throw new InvalidValueException("Invalid parameter milliseconds: " + milliseconds); - } - - this.milliseconds = milliseconds; - } - - public NormalPlayTime(long hours, long minutes, long seconds, long milliseconds) throws InvalidValueException { - if (hours < 0) { - throw new InvalidValueException("Invalid parameter hours: " + hours); - } - - if (minutes < 0 || minutes > 59) { - throw new InvalidValueException("Invalid parameter minutes: " + hours); - } - - if (seconds < 0 || seconds > 59) { - throw new InvalidValueException("Invalid parameter seconds: " + hours); - } - if (milliseconds < 0 || milliseconds > 999) { - throw new InvalidValueException("Invalid parameter milliseconds: " + milliseconds); - } - - this.milliseconds = (hours * 60 * 60 + minutes * 60 + seconds) * 1000 + milliseconds; - } - - /** - * @return the milliseconds - */ - public long getMilliseconds() { - return milliseconds; - } - - /** - * @param milliseconds the milliseconds to set - */ - public void setMilliseconds(long milliseconds) { - if (milliseconds < 0) { - throw new InvalidValueException("Invalid parameter milliseconds: " + milliseconds); - } - - this.milliseconds = milliseconds; - } - - public String getString() { - return getString(Format.SECONDS); - } - - /** - * We don't ignore the right zeros in milliseconds, a small compromise - * @param format - */ - public String getString(Format format) { - long seconds = TimeUnit.MILLISECONDS.toSeconds(milliseconds); - long ms = milliseconds % 1000; - switch (format) { - case TIME: - seconds = TimeUnit.MILLISECONDS.toSeconds(milliseconds) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliseconds)); - long hours = TimeUnit.MILLISECONDS.toHours(milliseconds); - long minutes = TimeUnit.MILLISECONDS.toMinutes(milliseconds) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milliseconds)); - return String.format(Locale.ROOT, "%d:%02d:%02d.%03d", hours, minutes, seconds, ms); - default: - return String.format(Locale.ROOT, "%d.%03d", seconds, ms); - } - } - - public static NormalPlayTime valueOf(String s) throws InvalidValueException { - Matcher matcher = pattern.matcher(s); - if (matcher.matches()) { - int msMultiplier = 0; - try { - if (matcher.group(1) != null) { - msMultiplier = (int) Math.pow(10, 3 - matcher.group(5).length()); - return new NormalPlayTime( - Long.parseLong(matcher.group(1)), - Long.parseLong(matcher.group(2)), - Long.parseLong(matcher.group(3)), - Long.parseLong(matcher.group(5))*msMultiplier); - } else { - msMultiplier = (int) Math.pow(10, 3 - matcher.group(8).length()); - return new NormalPlayTime( - Long.parseLong(matcher.group(6)) * 1000 + Long.parseLong(matcher.group(8))*msMultiplier); - } - } catch (NumberFormatException ex1) { - } - } - throw new InvalidValueException("Can't parse NormalPlayTime: " + s); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/NormalPlayTimeRange.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/NormalPlayTimeRange.java deleted file mode 100644 index 42d4620..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/NormalPlayTimeRange.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.types; - -import org.fourthline.cling.model.types.InvalidValueException; - -/** - * - * @author Mario Franco - */ -public class NormalPlayTimeRange { - - public static final String PREFIX = "npt="; - - private NormalPlayTime timeStart; - private NormalPlayTime timeEnd; - private NormalPlayTime timeDuration; - - public NormalPlayTimeRange(long timeStart, long timeEnd) { - this.timeStart = new NormalPlayTime(timeStart); - this.timeEnd = new NormalPlayTime(timeEnd); - } - - public NormalPlayTimeRange(NormalPlayTime timeStart, NormalPlayTime timeEnd) { - this.timeStart = timeStart; - this.timeEnd = timeEnd; - } - - public NormalPlayTimeRange(NormalPlayTime timeStart, NormalPlayTime timeEnd, NormalPlayTime timeDuration) { - this.timeStart = timeStart; - this.timeEnd = timeEnd; - this.timeDuration = timeDuration; - } - - /** - * @return the timeStart - */ - public NormalPlayTime getTimeStart() { - return timeStart; - } - - /** - * @return the timeEnd - */ - public NormalPlayTime getTimeEnd() { - return timeEnd; - } - - /** - * @return the timeDuration - */ - public NormalPlayTime getTimeDuration() { - return timeDuration; - } - - /** - * - * @return String format of Normal Play Time Range for response message header - */ - public String getString() { - return getString(true); - } - - /** - * - * @return String format of Normal Play Time Range for response message header - */ - public String getString(boolean includeDuration) { - String s = PREFIX; - - s += timeStart.getString() + "-"; - if (timeEnd != null) { - s += timeEnd.getString(); - } - if (includeDuration) { - s += "/" + (timeDuration != null ? timeDuration.getString() : "*"); - } - - return s; - } - - public static NormalPlayTimeRange valueOf(String s) throws InvalidValueException { - return valueOf(s, false); - } - - public static NormalPlayTimeRange valueOf(String s, boolean mandatoryTimeEnd) throws InvalidValueException { - if (s.startsWith(PREFIX)) { - NormalPlayTime timeStart, timeEnd = null, timeDuration = null; - String[] params = s.substring(PREFIX.length()).split("[-/]"); - switch (params.length) { - case 3: - if (params[2].length() != 0 && !params[2].equals("*")) { - timeDuration = NormalPlayTime.valueOf(params[2]); - } - case 2: - if (params[1].length() != 0) { - timeEnd = NormalPlayTime.valueOf(params[1]); - } - case 1: - if (params[0].length() != 0 && (!mandatoryTimeEnd || ( mandatoryTimeEnd && params.length>1))) { - timeStart = NormalPlayTime.valueOf(params[0]); - return new NormalPlayTimeRange(timeStart, timeEnd, timeDuration); - } - default: - break; - } - } - throw new InvalidValueException("Can't parse NormalPlayTimeRange: " + s); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/ScmsFlagType.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/ScmsFlagType.java deleted file mode 100644 index 16def45..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/ScmsFlagType.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.types; - -/** - * - * @author Mario Franco - */ -public class ScmsFlagType { - - private boolean copyright; - private boolean original; - - public ScmsFlagType() { - this.copyright = true; - this.original = true; - } - - public ScmsFlagType(boolean copyright, boolean original) { - this.copyright = copyright; - this.original = original; - } - - /** - * @return the copyright - */ - public boolean isCopyright() { - return copyright; - } - - /** - * @return the original - */ - public boolean isOriginal() { - return original; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/TimeSeekRangeType.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/TimeSeekRangeType.java deleted file mode 100644 index 6397e55..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/dlna/types/TimeSeekRangeType.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.support.model.dlna.types; - -import org.fourthline.cling.model.types.BytesRange; - -/** - * - * @author Mario Franco - */ -public class TimeSeekRangeType { - - private NormalPlayTimeRange normalPlayTimeRange; - private BytesRange bytesRange; - - - public TimeSeekRangeType(NormalPlayTimeRange nptRange) { - this.normalPlayTimeRange = nptRange; - } - - public TimeSeekRangeType(NormalPlayTimeRange nptRange, BytesRange byteRange) { - this.normalPlayTimeRange = nptRange; - this.bytesRange = byteRange; - } - - /** - * @return the normalPlayTimeRange - */ - public NormalPlayTimeRange getNormalPlayTimeRange() { - return normalPlayTimeRange; - } - - /** - * @return the bytesRange - */ - public BytesRange getBytesRange() { - return bytesRange; - } - - /** - * @param bytesRange the bytesRange to set - */ - public void setBytesRange(BytesRange bytesRange) { - this.bytesRange = bytesRange; - } - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioBook.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioBook.java deleted file mode 100644 index f3b347e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioBook.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.model.container.Container; - -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class AudioBook extends AudioItem { - - public static final Class CLASS = new Class("object.item.audioItem.audioBook"); - - public AudioBook() { - setClazz(CLASS); - } - - public AudioBook(Item other) { - super(other); - } - - public AudioBook(String id, Container parent, String title, String creator, Res... resource) { - this(id, parent.getId(), title, creator, null, null, null, resource); - } - - public AudioBook(String id, Container parent, String title, String creator, String producer, String contributor, String date, Res... resource) { - this(id, parent.getId(), title, creator, new Person(producer), new Person(contributor), date, resource); - } - - public AudioBook(String id, String parentID, String title, String creator, Person producer, Person contributor, String date, Res... resource) { - super(id, parentID, title, creator, resource); - setClazz(CLASS); - if (producer != null) - addProperty(new UPNP.PRODUCER(producer)); - if (contributor != null) - addProperty(new DC.CONTRIBUTOR(contributor)); - if (date != null) - setDate(date); - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public AudioBook setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - - public Person getFirstProducer() { - return getFirstPropertyValue(UPNP.PRODUCER.class); - } - - public Person[] getProducers() { - List list = getPropertyValues(UPNP.PRODUCER.class); - return list.toArray(new Person[list.size()]); - } - - public AudioBook setProducers(Person[] persons) { - removeProperties(UPNP.PRODUCER.class); - for (Person p : persons) { - addProperty(new UPNP.PRODUCER(p)); - } - return this; - } - - public Person getFirstContributor() { - return getFirstPropertyValue(DC.CONTRIBUTOR.class); - } - - public Person[] getContributors() { - List list = getPropertyValues(DC.CONTRIBUTOR.class); - return list.toArray(new Person[list.size()]); - } - - public AudioBook setContributors(Person[] contributors) { - removeProperties(DC.CONTRIBUTOR.class); - for (Person p : contributors) { - addProperty(new DC.CONTRIBUTOR(p)); - } - return this; - } - - public String getDate() { - return getFirstPropertyValue(DC.DATE.class); - } - - public AudioBook setDate(String date) { - replaceFirstProperty(new DC.DATE(date)); - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioBroadcast.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioBroadcast.java deleted file mode 100644 index b7cd89b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioBroadcast.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Res; - -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class AudioBroadcast extends AudioItem { - - public static final Class CLASS = new Class("object.item.audioItem.audioBroadcast"); - - public AudioBroadcast() { - setClazz(CLASS); - } - - public AudioBroadcast(Item other) { - super(other); - } - - public AudioBroadcast(String id, String parentID, String title, String creator, Res... resource) { - super(id, parentID, title, creator, resource); - setClazz(CLASS); - } - - public String getRegion() { - return getFirstPropertyValue(UPNP.REGION.class); - } - - public AudioBroadcast setRegion(String region) { - replaceFirstProperty(new UPNP.REGION(region)); - return this; - } - - public String getRadioCallSign() { - return getFirstPropertyValue(UPNP.RADIO_CALL_SIGN.class); - } - - public AudioBroadcast setRadioCallSign(String radioCallSign) { - replaceFirstProperty(new UPNP.RADIO_CALL_SIGN(radioCallSign)); - return this; - } - - public String getRadioStationID() { - return getFirstPropertyValue(UPNP.RADIO_STATION_ID.class); - } - - public AudioBroadcast setRadioStationID(String radioStationID) { - replaceFirstProperty(new UPNP.RADIO_STATION_ID(radioStationID)); - return this; - } - - public String getRadioBand() { - return getFirstPropertyValue(UPNP.RADIO_BAND.class); - } - - public AudioBroadcast setRadioBand(String radioBand) { - replaceFirstProperty(new UPNP.RADIO_BAND(radioBand)); - return this; - } - - public Integer getChannelNr() { - return getFirstPropertyValue(UPNP.CHANNEL_NR.class); - } - - public AudioBroadcast setChannelNr(Integer channelNr) { - replaceFirstProperty(new UPNP.CHANNEL_NR(channelNr)); - return this; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioItem.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioItem.java deleted file mode 100644 index 2f75b23..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/AudioItem.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.container.Container; - -import java.net.URI; -import java.util.Arrays; -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class AudioItem extends Item { - - public static final Class CLASS = new Class("object.item.audioItem"); - - public AudioItem() { - setClazz(CLASS); - } - - public AudioItem(Item other) { - super(other); - } - - public AudioItem(String id, Container parent, String title, String creator, Res... resource) { - this(id, parent.getId(), title, creator, resource); - } - - public AudioItem(String id, String parentID, String title, String creator, Res... resource) { - super(id, parentID, title, creator, CLASS); - if (resource != null) { - getResources().addAll(Arrays.asList(resource)); - } - } - - public String getFirstGenre() { - return getFirstPropertyValue(UPNP.GENRE.class); - } - - public String[] getGenres() { - List list = getPropertyValues(UPNP.GENRE.class); - return list.toArray(new String[list.size()]); - } - - public AudioItem setGenres(String[] genres) { - removeProperties(UPNP.GENRE.class); - for (String genre : genres) { - addProperty(new UPNP.GENRE(genre)); - } - return this; - } - - public String getDescription() { - return getFirstPropertyValue(DC.DESCRIPTION.class); - } - - public AudioItem setDescription(String description) { - replaceFirstProperty(new DC.DESCRIPTION(description)); - return this; - } - - public String getLongDescription() { - return getFirstPropertyValue(UPNP.LONG_DESCRIPTION.class); - } - - public AudioItem setLongDescription(String description) { - replaceFirstProperty(new UPNP.LONG_DESCRIPTION(description)); - return this; - } - - public Person getFirstPublisher() { - return getFirstPropertyValue(DC.PUBLISHER.class); - } - - public Person[] getPublishers() { - List list = getPropertyValues(DC.PUBLISHER.class); - return list.toArray(new Person[list.size()]); - } - - public AudioItem setPublishers(Person[] publishers) { - removeProperties(DC.PUBLISHER.class); - for (Person publisher : publishers) { - addProperty(new DC.PUBLISHER(publisher)); - } - return this; - } - - public URI getFirstRelation() { - return getFirstPropertyValue(DC.RELATION.class); - } - - public URI[] getRelations() { - List list = getPropertyValues(DC.RELATION.class); - return list.toArray(new URI[list.size()]); - } - - public AudioItem setRelations(URI[] relations) { - removeProperties(DC.RELATION.class); - for (URI relation : relations) { - addProperty(new DC.RELATION(relation)); - } - return this; - } - - public String getLanguage() { - return getFirstPropertyValue(DC.LANGUAGE.class); - } - - public AudioItem setLanguage(String language) { - replaceFirstProperty(new DC.LANGUAGE(language)); - return this; - } - - public String getFirstRights() { - return getFirstPropertyValue(DC.RIGHTS.class); - } - - public String[] getRights() { - List list = getPropertyValues(DC.RIGHTS.class); - return list.toArray(new String[list.size()]); - } - - public AudioItem setRights(String[] rights) { - removeProperties(DC.RIGHTS.class); - for (String right : rights) { - addProperty(new DC.RIGHTS(right)); - } - return this; - } -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/ImageItem.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/ImageItem.java deleted file mode 100644 index 5f43043..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/ImageItem.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.model.container.Container; - -import java.util.Arrays; -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class ImageItem extends Item{ - - public static final Class CLASS = new Class("object.item.imageItem"); - - public ImageItem() { - setClazz(CLASS); - } - - public ImageItem(Item other) { - super(other); - } - - public ImageItem(String id, Container parent, String title, String creator, Res... resource) { - this(id, parent.getId(), title, creator, resource); - } - - public ImageItem(String id, String parentID, String title, String creator, Res... resource) { - super(id, parentID, title, creator, CLASS); - if (resource != null) { - getResources().addAll(Arrays.asList(resource)); - } - } - - public String getDescription() { - return getFirstPropertyValue(DC.DESCRIPTION.class); - } - - public ImageItem setDescription(String description) { - replaceFirstProperty(new DC.DESCRIPTION(description)); - return this; - } - - public String getLongDescription() { - return getFirstPropertyValue(UPNP.LONG_DESCRIPTION.class); - } - - public ImageItem setLongDescription(String description) { - replaceFirstProperty(new UPNP.LONG_DESCRIPTION(description)); - return this; - } - - public Person getFirstPublisher() { - return getFirstPropertyValue(DC.PUBLISHER.class); - } - - public Person[] getPublishers() { - List list = getPropertyValues(DC.PUBLISHER.class); - return list.toArray(new Person[list.size()]); - } - - public ImageItem setPublishers(Person[] publishers) { - removeProperties(DC.PUBLISHER.class); - for (Person publisher : publishers) { - addProperty(new DC.PUBLISHER(publisher)); - } - return this; - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public ImageItem setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - - public String getRating() { - return getFirstPropertyValue(UPNP.RATING.class); - } - - public ImageItem setRating(String rating) { - replaceFirstProperty(new UPNP.RATING(rating)); - return this; - } - - public String getDate() { - return getFirstPropertyValue(DC.DATE.class); - } - - public ImageItem setDate(String date) { - replaceFirstProperty(new DC.DATE(date)); - return this; - } - - public String getFirstRights() { - return getFirstPropertyValue(DC.RIGHTS.class); - } - - public String[] getRights() { - List list = getPropertyValues(DC.RIGHTS.class); - return list.toArray(new String[list.size()]); - } - - public ImageItem setRights(String[] rights) { - removeProperties(DC.RIGHTS.class); - for (String right : rights) { - addProperty(new DC.RIGHTS(right)); - } - return this; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Item.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Item.java deleted file mode 100644 index a965da2..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Item.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.DIDLObject; -import org.fourthline.cling.support.model.DescMeta; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.WriteStatus; -import org.fourthline.cling.support.model.container.Container; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Christian Bauer - */ -public class Item extends DIDLObject { - - protected String refID; - - public Item() { - } - - public Item(Item other) { - super(other); - setRefID(other.getRefID()); - } - - public Item(String id, String parentID, String title, String creator, boolean restricted, WriteStatus writeStatus, Class clazz, List resources, List properties, List descMetadata) { - super(id, parentID, title, creator, restricted, writeStatus, clazz, resources, properties, descMetadata); - } - - public Item(String id, String parentID, String title, String creator, boolean restricted, WriteStatus writeStatus, Class clazz, List resources, List properties, List descMetadata, String refID) { - super(id, parentID, title, creator, restricted, writeStatus, clazz, resources, properties, descMetadata); - this.refID = refID; - } - - public Item(String id, Container parent, String title, String creator, DIDLObject.Class clazz) { - this(id, parent.getId(), title, creator, false, null, clazz, new ArrayList(), new ArrayList(), new ArrayList()); - } - - public Item(String id, Container parent, String title, String creator, DIDLObject.Class clazz, String refID) { - this(id, parent.getId(), title, creator, false, null, clazz, new ArrayList(), new ArrayList(), new ArrayList(), refID); - } - - public Item(String id, String parentID, String title, String creator, DIDLObject.Class clazz) { - this(id, parentID, title, creator, false, null, clazz, new ArrayList(), new ArrayList(), new ArrayList()); - } - - public Item(String id, String parentID, String title, String creator, DIDLObject.Class clazz, String refID) { - this(id, parentID, title, creator, false, null, clazz, new ArrayList(), new ArrayList(), new ArrayList(), refID); - } - - public String getRefID() { - return refID; - } - - public void setRefID(String refID) { - this.refID = refID; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Movie.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Movie.java deleted file mode 100644 index 2fadf48..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Movie.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.model.container.Container; - -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class Movie extends VideoItem { - - public static final Class CLASS = new Class("object.item.videoItem.movie"); - - public Movie() { - setClazz(CLASS); - } - - public Movie(Item other) { - super(other); - } - - public Movie(String id, Container parent, String title, String creator, Res... resource) { - this(id, parent.getId(), title, creator, resource); - } - - public Movie(String id, String parentID, String title, String creator, Res... resource) { - super(id, parentID, title, creator, resource); - setClazz(CLASS); - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public Movie setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - - public Integer getDVDRegionCode() { - return getFirstPropertyValue(UPNP.DVD_REGION_CODE.class); - } - - public Movie setDVDRegionCode(Integer DVDRegionCode) { - replaceFirstProperty(new UPNP.DVD_REGION_CODE(DVDRegionCode)); - return this; - } - - public String getChannelName() { - return getFirstPropertyValue(UPNP.CHANNEL_NAME.class); - } - - public Movie setChannelName(String channelName) { - replaceFirstProperty(new UPNP.CHANNEL_NAME(channelName)); - return this; - } - - public String getFirstScheduledStartTime() { - return getFirstPropertyValue(UPNP.SCHEDULED_START_TIME.class); - } - - public String[] getScheduledStartTimes() { - List list = getPropertyValues(UPNP.SCHEDULED_START_TIME.class); - return list.toArray(new String[list.size()]); - } - - public Movie setScheduledStartTimes(String[] strings) { - removeProperties(UPNP.SCHEDULED_START_TIME.class); - for (String s : strings) { - addProperty(new UPNP.SCHEDULED_START_TIME(s)); - } - return this; - } - - public String getFirstScheduledEndTime() { - return getFirstPropertyValue(UPNP.SCHEDULED_END_TIME.class); - } - - public String[] getScheduledEndTimes() { - List list = getPropertyValues(UPNP.SCHEDULED_END_TIME.class); - return list.toArray(new String[list.size()]); - } - - public Movie setScheduledEndTimes(String[] strings) { - removeProperties(UPNP.SCHEDULED_END_TIME.class); - for (String s : strings) { - addProperty(new UPNP.SCHEDULED_END_TIME(s)); - } - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/MusicTrack.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/MusicTrack.java deleted file mode 100644 index a5c943e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/MusicTrack.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.PersonWithRole; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.model.container.Container; - -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class MusicTrack extends AudioItem { - - public static final Class CLASS = new Class("object.item.audioItem.musicTrack"); - - public MusicTrack() { - setClazz(CLASS); - } - - public MusicTrack(Item other) { - super(other); - } - - public MusicTrack(String id, Container parent, String title, String creator, String album, String artist, Res... resource) { - this(id, parent.getId(), title, creator, album, artist, resource); - } - - public MusicTrack(String id, Container parent, String title, String creator, String album, PersonWithRole artist, Res... resource) { - this(id, parent.getId(), title, creator, album, artist, resource); - } - - public MusicTrack(String id, String parentID, String title, String creator, String album, String artist, Res... resource) { - this(id, parentID, title, creator, album, artist == null ? null : new PersonWithRole(artist), resource); - } - - public MusicTrack(String id, String parentID, String title, String creator, String album, PersonWithRole artist, Res... resource) { - super(id, parentID, title, creator, resource); - setClazz(CLASS); - if (album != null) - setAlbum(album); - if (artist != null) - addProperty(new UPNP.ARTIST(artist)); - } - - public PersonWithRole getFirstArtist() { - return getFirstPropertyValue(UPNP.ARTIST.class); - } - - public PersonWithRole[] getArtists() { - List list = getPropertyValues(UPNP.ARTIST.class); - return list.toArray(new PersonWithRole[list.size()]); - } - - public MusicTrack setArtists(PersonWithRole[] artists) { - removeProperties(UPNP.ARTIST.class); - for (PersonWithRole artist : artists) { - addProperty(new UPNP.ARTIST(artist)); - } - return this; - } - - public String getAlbum() { - return getFirstPropertyValue(UPNP.ALBUM.class); - } - - public MusicTrack setAlbum(String album) { - replaceFirstProperty(new UPNP.ALBUM(album)); - return this; - } - - public Integer getOriginalTrackNumber() { - return getFirstPropertyValue(UPNP.ORIGINAL_TRACK_NUMBER.class); - } - - public MusicTrack setOriginalTrackNumber(Integer number) { - replaceFirstProperty(new UPNP.ORIGINAL_TRACK_NUMBER(number)); - return this; - } - - public String getFirstPlaylist() { - return getFirstPropertyValue(UPNP.PLAYLIST.class); - } - - public String[] getPlaylists() { - List list = getPropertyValues(UPNP.PLAYLIST.class); - return list.toArray(new String[list.size()]); - } - - public MusicTrack setPlaylists(String[] playlists) { - removeProperties(UPNP.PLAYLIST.class); - for (String s : playlists) { - addProperty(new UPNP.PLAYLIST(s)); - } - return this; - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public MusicTrack setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - - public Person getFirstContributor() { - return getFirstPropertyValue(DC.CONTRIBUTOR.class); - } - - public Person[] getContributors() { - List list = getPropertyValues(DC.CONTRIBUTOR.class); - return list.toArray(new Person[list.size()]); - } - - public MusicTrack setContributors(Person[] contributors) { - removeProperties(DC.CONTRIBUTOR.class); - for (Person p : contributors) { - addProperty(new DC.CONTRIBUTOR(p)); - } - return this; - } - - public String getDate() { - return getFirstPropertyValue(DC.DATE.class); - } - - public MusicTrack setDate(String date) { - replaceFirstProperty(new DC.DATE(date)); - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/MusicVideoClip.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/MusicVideoClip.java deleted file mode 100644 index ebc61a2..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/MusicVideoClip.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.PersonWithRole; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.model.container.Container; - -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class MusicVideoClip extends VideoItem { - - public static final Class CLASS = new Class("object.item.videoItem.musicVideoClip"); - - public MusicVideoClip() { - setClazz(CLASS); - } - - public MusicVideoClip(Item other) { - super(other); - } - - public MusicVideoClip(String id, Container parent, String title, String creator, Res... resource) { - this(id, parent.getId(), title, creator, resource); - } - - public MusicVideoClip(String id, String parentID, String title, String creator, Res... resource) { - super(id, parentID, title, creator, resource); - setClazz(CLASS); - } - - public PersonWithRole getFirstArtist() { - return getFirstPropertyValue(UPNP.ARTIST.class); - } - - public PersonWithRole[] getArtists() { - List list = getPropertyValues(UPNP.ARTIST.class); - return list.toArray(new PersonWithRole[list.size()]); - } - - public MusicVideoClip setArtists(PersonWithRole[] artists) { - removeProperties(UPNP.ARTIST.class); - for (PersonWithRole artist : artists) { - addProperty(new UPNP.ARTIST(artist)); - } - return this; - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public MusicVideoClip setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - - public String getAlbum() { - return getFirstPropertyValue(UPNP.ALBUM.class); - } - - public MusicVideoClip setAlbum(String album) { - replaceFirstProperty(new UPNP.ALBUM(album)); - return this; - } - - public String getFirstScheduledStartTime() { - return getFirstPropertyValue(UPNP.SCHEDULED_START_TIME.class); - } - - public String[] getScheduledStartTimes() { - List list = getPropertyValues(UPNP.SCHEDULED_START_TIME.class); - return list.toArray(new String[list.size()]); - } - - public MusicVideoClip setScheduledStartTimes(String[] strings) { - removeProperties(UPNP.SCHEDULED_START_TIME.class); - for (String s : strings) { - addProperty(new UPNP.SCHEDULED_START_TIME(s)); - } - return this; - } - - public String getFirstScheduledEndTime() { - return getFirstPropertyValue(UPNP.SCHEDULED_END_TIME.class); - } - - public String[] getScheduledEndTimes() { - List list = getPropertyValues(UPNP.SCHEDULED_END_TIME.class); - return list.toArray(new String[list.size()]); - } - - public MusicVideoClip setScheduledEndTimes(String[] strings) { - removeProperties(UPNP.SCHEDULED_END_TIME.class); - for (String s : strings) { - addProperty(new UPNP.SCHEDULED_END_TIME(s)); - } - return this; - } - - public Person getFirstContributor() { - return getFirstPropertyValue(DC.CONTRIBUTOR.class); - } - - public Person[] getContributors() { - List list = getPropertyValues(DC.CONTRIBUTOR.class); - return list.toArray(new Person[list.size()]); - } - - public MusicVideoClip setContributors(Person[] contributors) { - removeProperties(DC.CONTRIBUTOR.class); - for (Person p : contributors) { - addProperty(new DC.CONTRIBUTOR(p)); - } - return this; - } - - public String getDate() { - return getFirstPropertyValue(DC.DATE.class); - } - - public MusicVideoClip setDate(String date) { - replaceFirstProperty(new DC.DATE(date)); - return this; - } - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Photo.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Photo.java deleted file mode 100644 index d43f8ba..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/Photo.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.container.Container; - -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class Photo extends ImageItem { - - public static final Class CLASS = new Class("object.item.imageItem.photo"); - - public Photo() { - setClazz(CLASS); - } - - public Photo(Item other) { - super(other); - } - - public Photo(String id, Container parent, String title, String creator, String album, Res... resource) { - this(id, parent.getId(), title, creator, album, resource); - } - - public Photo(String id, String parentID, String title, String creator, String album, Res... resource) { - super(id, parentID, title, creator, resource); - setClazz(CLASS); - if (album != null) - setAlbum(album); - } - - public String getAlbum() { - return getFirstPropertyValue(UPNP.ALBUM.class); - } - - public Photo setAlbum(String album) { - replaceFirstProperty(new UPNP.ALBUM(album)); - return this; - } - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/PlaylistItem.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/PlaylistItem.java deleted file mode 100644 index 5eb6edb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/PlaylistItem.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.PersonWithRole; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.model.container.Container; - -import java.util.Arrays; -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class PlaylistItem extends Item { - - public static final Class CLASS = new Class("object.item.playlistItem"); - - public PlaylistItem() { - setClazz(CLASS); - } - - public PlaylistItem(Item other) { - super(other); - } - - public PlaylistItem(String id, Container parent, String title, String creator, Res... resource) { - this(id, parent.getId(), title, creator, resource); - } - - public PlaylistItem(String id, String parentID, String title, String creator, Res... resource) { - super(id, parentID, title, creator, CLASS); - if (resource != null) { - getResources().addAll(Arrays.asList(resource)); - } - } - - public PersonWithRole getFirstArtist() { - return getFirstPropertyValue(UPNP.ARTIST.class); - } - - public PersonWithRole[] getArtists() { - List list = getPropertyValues(UPNP.ARTIST.class); - return list.toArray(new PersonWithRole[list.size()]); - } - - public PlaylistItem setArtists(PersonWithRole[] artists) { - removeProperties(UPNP.ARTIST.class); - for (PersonWithRole artist : artists) { - addProperty(new UPNP.ARTIST(artist)); - } - return this; - } - - public String getFirstGenre() { - return getFirstPropertyValue(UPNP.GENRE.class); - } - - public String[] getGenres() { - List list = getPropertyValues(UPNP.GENRE.class); - return list.toArray(new String[list.size()]); - } - - public PlaylistItem setGenres(String[] genres) { - removeProperties(UPNP.GENRE.class); - for (String genre : genres) { - addProperty(new UPNP.GENRE(genre)); - } - return this; - } - - public String getDescription() { - return getFirstPropertyValue(DC.DESCRIPTION.class); - } - - public PlaylistItem setDescription(String description) { - replaceFirstProperty(new DC.DESCRIPTION(description)); - return this; - } - - public String getLongDescription() { - return getFirstPropertyValue(UPNP.LONG_DESCRIPTION.class); - } - - public PlaylistItem setLongDescription(String description) { - replaceFirstProperty(new UPNP.LONG_DESCRIPTION(description)); - return this; - } - - public String getLanguage() { - return getFirstPropertyValue(DC.LANGUAGE.class); - } - - public PlaylistItem setLanguage(String language) { - replaceFirstProperty(new DC.LANGUAGE(language)); - return this; - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public PlaylistItem setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - - public String getDate() { - return getFirstPropertyValue(DC.DATE.class); - } - - public PlaylistItem setDate(String date) { - replaceFirstProperty(new DC.DATE(date)); - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/TextItem.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/TextItem.java deleted file mode 100644 index 52a122b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/TextItem.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.PersonWithRole; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.StorageMedium; -import org.fourthline.cling.support.model.container.Container; - -import java.net.URI; -import java.util.Arrays; -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class TextItem extends Item { - - public static final Class CLASS = new Class("object.item.textItem"); - - public TextItem() { - setClazz(CLASS); - } - - public TextItem(Item other) { - super(other); - } - - public TextItem(String id, Container parent, String title, String creator, Res... resource) { - this(id, parent.getId(), title, creator, resource); - } - - public TextItem(String id, String parentID, String title, String creator, Res... resource) { - super(id, parentID, title, creator, CLASS); - if (resource != null) { - getResources().addAll(Arrays.asList(resource)); - } - } - - public PersonWithRole getFirstAuthor() { - return getFirstPropertyValue(UPNP.AUTHOR.class); - } - - public PersonWithRole[] getAuthors() { - List list = getPropertyValues(UPNP.AUTHOR.class); - return list.toArray(new PersonWithRole[list.size()]); - } - - public TextItem setAuthors(PersonWithRole[] persons) { - removeProperties(UPNP.AUTHOR.class); - for (PersonWithRole p: persons) { - addProperty(new UPNP.AUTHOR(p)); - } - return this; - } - - public String getDescription() { - return getFirstPropertyValue(DC.DESCRIPTION.class); - } - - public TextItem setDescription(String description) { - replaceFirstProperty(new DC.DESCRIPTION(description)); - return this; - } - - public String getLongDescription() { - return getFirstPropertyValue(UPNP.LONG_DESCRIPTION.class); - } - - public TextItem setLongDescription(String description) { - replaceFirstProperty(new UPNP.LONG_DESCRIPTION(description)); - return this; - } - - public String getLanguage() { - return getFirstPropertyValue(DC.LANGUAGE.class); - } - - public TextItem setLanguage(String language) { - replaceFirstProperty(new DC.LANGUAGE(language)); - return this; - } - - public StorageMedium getStorageMedium() { - return getFirstPropertyValue(UPNP.STORAGE_MEDIUM.class); - } - - public TextItem setStorageMedium(StorageMedium storageMedium) { - replaceFirstProperty(new UPNP.STORAGE_MEDIUM(storageMedium)); - return this; - } - - public String getDate() { - return getFirstPropertyValue(DC.DATE.class); - } - - public TextItem setDate(String date) { - replaceFirstProperty(new DC.DATE(date)); - return this; - } - - public URI getFirstRelation() { - return getFirstPropertyValue(DC.RELATION.class); - } - - public URI[] getRelations() { - List list = getPropertyValues(DC.RELATION.class); - return list.toArray(new URI[list.size()]); - } - - public TextItem setRelations(URI[] relations) { - removeProperties(DC.RELATION.class); - for (URI relation : relations) { - addProperty(new DC.RELATION(relation)); - } - return this; - } - - public String getFirstRights() { - return getFirstPropertyValue(DC.RIGHTS.class); - } - - public String[] getRights() { - List list = getPropertyValues(DC.RIGHTS.class); - return list.toArray(new String[list.size()]); - } - - public TextItem setRights(String[] rights) { - removeProperties(DC.RIGHTS.class); - for (String right : rights) { - addProperty(new DC.RIGHTS(right)); - } - return this; - } - - public String getRating() { - return getFirstPropertyValue(UPNP.RATING.class); - } - - public TextItem setRating(String rating) { - replaceFirstProperty(new UPNP.RATING(rating)); - return this; - } - - public Person getFirstContributor() { - return getFirstPropertyValue(DC.CONTRIBUTOR.class); - } - - public Person[] getContributors() { - List list = getPropertyValues(DC.CONTRIBUTOR.class); - return list.toArray(new Person[list.size()]); - } - - public TextItem setContributors(Person[] contributors) { - removeProperties(DC.CONTRIBUTOR.class); - for (Person p : contributors) { - addProperty(new DC.CONTRIBUTOR(p)); - } - return this; - } - - public Person getFirstPublisher() { - return getFirstPropertyValue(DC.PUBLISHER.class); - } - - public Person[] getPublishers() { - List list = getPropertyValues(DC.PUBLISHER.class); - return list.toArray(new Person[list.size()]); - } - - public TextItem setPublishers(Person[] publishers) { - removeProperties(DC.PUBLISHER.class); - for (Person publisher : publishers) { - addProperty(new DC.PUBLISHER(publisher)); - } - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/VideoBroadcast.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/VideoBroadcast.java deleted file mode 100644 index 576735b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/VideoBroadcast.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.container.Container; - -import java.net.URI; - -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class VideoBroadcast extends VideoItem { - - public static final Class CLASS = new Class("object.item.videoItem.videoBroadcast"); - - public VideoBroadcast() { - setClazz(CLASS); - } - - public VideoBroadcast(Item other) { - super(other); - } - - public VideoBroadcast(String id, Container parent, String title, String creator, Res... resource) { - this(id, parent.getId(), title, creator, resource); - } - - public VideoBroadcast(String id, String parentID, String title, String creator, Res... resource) { - super(id, parentID, title, creator, resource); - setClazz(CLASS); - } - - public URI getIcon() { - return getFirstPropertyValue(UPNP.ICON.class); - } - - public VideoBroadcast setIcon(URI icon) { - replaceFirstProperty(new UPNP.ICON(icon)); - return this; - } - - public String getRegion() { - return getFirstPropertyValue(UPNP.REGION.class); - } - - public VideoBroadcast setRegion(String region) { - replaceFirstProperty(new UPNP.REGION(region)); - return this; - } - - public Integer getChannelNr() { - return getFirstPropertyValue(UPNP.CHANNEL_NR.class); - } - - public VideoBroadcast setChannelNr(Integer channelNr) { - replaceFirstProperty(new UPNP.CHANNEL_NR(channelNr)); - return this; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/VideoItem.java b/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/VideoItem.java deleted file mode 100644 index 8c6a83c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/model/item/VideoItem.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.model.item; - -import org.fourthline.cling.support.model.Person; -import org.fourthline.cling.support.model.PersonWithRole; -import org.fourthline.cling.support.model.Res; -import org.fourthline.cling.support.model.container.Container; - -import java.net.URI; -import java.util.Arrays; -import java.util.List; - -import static org.fourthline.cling.support.model.DIDLObject.Property.DC; -import static org.fourthline.cling.support.model.DIDLObject.Property.UPNP; - -/** - * @author Christian Bauer - */ -public class VideoItem extends Item { - - public static final Class CLASS = new Class("object.item.videoItem"); - - public VideoItem() { - setClazz(CLASS); - } - - public VideoItem(Item other) { - super(other); - } - - public VideoItem(String id, Container parent, String title, String creator, Res... resource) { - this(id, parent.getId(), title, creator, resource); - } - - public VideoItem(String id, String parentID, String title, String creator, Res... resource) { - super(id, parentID, title, creator, CLASS); - if (resource != null) { - getResources().addAll(Arrays.asList(resource)); - } - } - - public String getFirstGenre() { - return getFirstPropertyValue(UPNP.GENRE.class); - } - - public String[] getGenres() { - List list = getPropertyValues(UPNP.GENRE.class); - return list.toArray(new String[list.size()]); - } - - public VideoItem setGenres(String[] genres) { - removeProperties(UPNP.GENRE.class); - for (String genre : genres) { - addProperty(new UPNP.GENRE(genre)); - } - return this; - } - - public String getDescription() { - return getFirstPropertyValue(DC.DESCRIPTION.class); - } - - public VideoItem setDescription(String description) { - replaceFirstProperty(new DC.DESCRIPTION(description)); - return this; - } - - public String getLongDescription() { - return getFirstPropertyValue(UPNP.LONG_DESCRIPTION.class); - } - - public VideoItem setLongDescription(String description) { - replaceFirstProperty(new UPNP.LONG_DESCRIPTION(description)); - return this; - } - - public Person getFirstProducer() { - return getFirstPropertyValue(UPNP.PRODUCER.class); - } - - public Person[] getProducers() { - List list = getPropertyValues(UPNP.PRODUCER.class); - return list.toArray(new Person[list.size()]); - } - - public VideoItem setProducers(Person[] persons) { - removeProperties(UPNP.PRODUCER.class); - for (Person p : persons) { - addProperty(new UPNP.PRODUCER(p)); - } - return this; - } - - public String getRating() { - return getFirstPropertyValue(UPNP.RATING.class); - } - - public VideoItem setRating(String rating) { - replaceFirstProperty(new UPNP.RATING(rating)); - return this; - } - - public PersonWithRole getFirstActor() { - return getFirstPropertyValue(UPNP.ACTOR.class); - } - - public PersonWithRole[] getActors() { - List list = getPropertyValues(UPNP.ACTOR.class); - return list.toArray(new PersonWithRole[list.size()]); - } - - public VideoItem setActors(PersonWithRole[] persons) { - removeProperties(UPNP.ACTOR.class); - for (PersonWithRole p : persons) { - addProperty(new UPNP.ACTOR(p)); - } - return this; - } - - public Person getFirstDirector() { - return getFirstPropertyValue(UPNP.DIRECTOR.class); - } - - public Person[] getDirectors() { - List list = getPropertyValues(UPNP.DIRECTOR.class); - return list.toArray(new Person[list.size()]); - } - - public VideoItem setDirectors(Person[] persons) { - removeProperties(UPNP.DIRECTOR.class); - for (Person p : persons) { - addProperty(new UPNP.DIRECTOR(p)); - } - return this; - } - - public Person getFirstPublisher() { - return getFirstPropertyValue(DC.PUBLISHER.class); - } - - public Person[] getPublishers() { - List list = getPropertyValues(DC.PUBLISHER.class); - return list.toArray(new Person[list.size()]); - } - - public VideoItem setPublishers(Person[] publishers) { - removeProperties(DC.PUBLISHER.class); - for (Person publisher : publishers) { - addProperty(new DC.PUBLISHER(publisher)); - } - return this; - } - - public String getLanguage() { - return getFirstPropertyValue(DC.LANGUAGE.class); - } - - public VideoItem setLanguage(String language) { - replaceFirstProperty(new DC.LANGUAGE(language)); - return this; - } - - public URI getFirstRelation() { - return getFirstPropertyValue(DC.RELATION.class); - } - - public URI[] getRelations() { - List list = getPropertyValues(DC.RELATION.class); - return list.toArray(new URI[list.size()]); - } - - public VideoItem setRelations(URI[] relations) { - removeProperties(DC.RELATION.class); - for (URI relation : relations) { - addProperty(new DC.RELATION(relation)); - } - return this; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/AbstractAudioRenderingControl.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/AbstractAudioRenderingControl.java deleted file mode 100644 index a1f52e8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/AbstractAudioRenderingControl.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol; - -import org.fourthline.cling.binding.annotations.UpnpAction; -import org.fourthline.cling.binding.annotations.UpnpInputArgument; -import org.fourthline.cling.binding.annotations.UpnpOutputArgument; -import org.fourthline.cling.binding.annotations.UpnpService; -import org.fourthline.cling.binding.annotations.UpnpServiceId; -import org.fourthline.cling.binding.annotations.UpnpServiceType; -import org.fourthline.cling.binding.annotations.UpnpStateVariable; -import org.fourthline.cling.binding.annotations.UpnpStateVariables; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes; -import org.fourthline.cling.support.lastchange.LastChange; -import org.fourthline.cling.support.lastchange.LastChangeDelegator; -import org.fourthline.cling.support.model.Channel; -import org.fourthline.cling.support.model.PresetName; -import org.fourthline.cling.support.model.VolumeDBRange; -import org.fourthline.cling.support.renderingcontrol.lastchange.ChannelLoudness; -import org.fourthline.cling.support.renderingcontrol.lastchange.ChannelMute; -import org.fourthline.cling.support.renderingcontrol.lastchange.ChannelVolume; -import org.fourthline.cling.support.renderingcontrol.lastchange.ChannelVolumeDB; -import org.fourthline.cling.support.renderingcontrol.lastchange.RenderingControlLastChangeParser; -import org.fourthline.cling.support.renderingcontrol.lastchange.RenderingControlVariable; - -import java.beans.PropertyChangeSupport; - -/** - * - */ -@UpnpService( - serviceId = @UpnpServiceId("RenderingControl"), - serviceType = @UpnpServiceType(value = "RenderingControl", version = 1), - stringConvertibleTypes = LastChange.class -) -@UpnpStateVariables({ - @UpnpStateVariable( - name = "PresetNameList", - sendEvents = false, - datatype = "string"), - @UpnpStateVariable( - name = "Mute", - sendEvents = false, - datatype = "boolean"), - @UpnpStateVariable( - name = "Volume", - sendEvents = false, - datatype = "ui2", - allowedValueMinimum = 0, - allowedValueMaximum = 100), - @UpnpStateVariable( - name = "VolumeDB", - sendEvents = false, - datatype = "i2", - allowedValueMinimum = -36864, - allowedValueMaximum = 32767), - @UpnpStateVariable( - name = "Loudness", - sendEvents = false, - datatype = "boolean"), - @UpnpStateVariable( - name = "A_ARG_TYPE_Channel", - sendEvents = false, - allowedValuesEnum = Channel.class), - @UpnpStateVariable( - name = "A_ARG_TYPE_PresetName", - sendEvents = false, - allowedValuesEnum = PresetName.class), - @UpnpStateVariable( - name = "A_ARG_TYPE_InstanceID", - sendEvents = false, - datatype = "ui4") - -}) -public abstract class AbstractAudioRenderingControl implements LastChangeDelegator { - - @UpnpStateVariable(eventMaximumRateMilliseconds = 200) - final private LastChange lastChange; - - final protected PropertyChangeSupport propertyChangeSupport; - - protected AbstractAudioRenderingControl() { - this.propertyChangeSupport = new PropertyChangeSupport(this); - this.lastChange = new LastChange(new RenderingControlLastChangeParser()); - } - - protected AbstractAudioRenderingControl(LastChange lastChange) { - this.propertyChangeSupport = new PropertyChangeSupport(this); - this.lastChange = lastChange; - } - - protected AbstractAudioRenderingControl(PropertyChangeSupport propertyChangeSupport) { - this.propertyChangeSupport = propertyChangeSupport; - this.lastChange = new LastChange(new RenderingControlLastChangeParser()); - } - - protected AbstractAudioRenderingControl(PropertyChangeSupport propertyChangeSupport, LastChange lastChange) { - this.propertyChangeSupport = propertyChangeSupport; - this.lastChange = lastChange; - } - - @Override - public LastChange getLastChange() { - return lastChange; - } - - @Override - public void appendCurrentState(LastChange lc, UnsignedIntegerFourBytes instanceId) throws Exception { - for (Channel channel : getCurrentChannels()) { - String channelString = channel.name(); - lc.setEventedValue( - instanceId, - new RenderingControlVariable.Mute(new ChannelMute(channel, getMute(instanceId, channelString))), - new RenderingControlVariable.Loudness(new ChannelLoudness(channel, getLoudness(instanceId, channelString))), - new RenderingControlVariable.Volume(new ChannelVolume(channel, getVolume(instanceId, channelString).getValue().intValue())), - new RenderingControlVariable.VolumeDB(new ChannelVolumeDB(channel, getVolumeDB(instanceId, channelString))), - new RenderingControlVariable.PresetNameList(PresetName.FactoryDefaults.name()) - ); - } - } - - public PropertyChangeSupport getPropertyChangeSupport() { - return propertyChangeSupport; - } - - public static UnsignedIntegerFourBytes getDefaultInstanceID() { - return new UnsignedIntegerFourBytes(0); - } - - @UpnpAction(out = @UpnpOutputArgument(name = "CurrentPresetNameList", stateVariable = "PresetNameList")) - public String listPresets(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws RenderingControlException { - return PresetName.FactoryDefaults.toString(); - } - - @UpnpAction - public void selectPreset(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "PresetName") String presetName) throws RenderingControlException { - } - - @UpnpAction(out = @UpnpOutputArgument(name = "CurrentMute", stateVariable = "Mute")) - public abstract boolean getMute(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Channel") String channelName) throws RenderingControlException; - - @UpnpAction - public abstract void setMute(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Channel") String channelName, - @UpnpInputArgument(name = "DesiredMute", stateVariable = "Mute") boolean desiredMute) throws RenderingControlException; - - @UpnpAction(out = @UpnpOutputArgument(name = "CurrentVolume", stateVariable = "Volume")) - public abstract UnsignedIntegerTwoBytes getVolume(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Channel") String channelName) throws RenderingControlException; - - @UpnpAction - public abstract void setVolume(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Channel") String channelName, - @UpnpInputArgument(name = "DesiredVolume", stateVariable = "Volume") UnsignedIntegerTwoBytes desiredVolume) throws RenderingControlException; - - @UpnpAction(out = @UpnpOutputArgument(name = "CurrentVolume", stateVariable = "VolumeDB")) - public Integer getVolumeDB(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Channel") String channelName) throws RenderingControlException { - return 0; - } - - @UpnpAction - public void setVolumeDB(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Channel") String channelName, - @UpnpInputArgument(name = "DesiredVolume", stateVariable = "VolumeDB") Integer desiredVolumeDB) throws RenderingControlException { - /* - VolumeDB volumeDB = new VolumeDB(); - volumeDB.setChannel(channelName); - volumeDB.setVal(new BigInteger(desiredVolumeDB.toString())); - */ - } - - @UpnpAction(out = { - @UpnpOutputArgument(name = "MinValue", stateVariable = "VolumeDB", getterName = "getMinValue"), - @UpnpOutputArgument(name = "MaxValue", stateVariable = "VolumeDB", getterName = "getMaxValue") - }) - public VolumeDBRange getVolumeDBRange(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Channel") String channelName) throws RenderingControlException { - return new VolumeDBRange(0, 0); - } - - @UpnpAction(out = @UpnpOutputArgument(name = "CurrentLoudness", stateVariable = "Loudness")) - public boolean getLoudness(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Channel") String channelName) throws RenderingControlException { - return false; - } - - @UpnpAction - public void setLoudness(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, - @UpnpInputArgument(name = "Channel") String channelName, - @UpnpInputArgument(name = "DesiredLoudness", stateVariable = "Loudness") boolean desiredLoudness) throws RenderingControlException { -/* - Loudness loudness = new Loudness(); - loudness.setChannel(channelName); - loudness.setVal(desiredLoudness); -*/ - } - - protected abstract Channel[] getCurrentChannels(); - - protected Channel getChannel(String channelName) throws RenderingControlException { - try { - return Channel.valueOf(channelName); - } catch (IllegalArgumentException ex) { - throw new RenderingControlException(ErrorCode.ARGUMENT_VALUE_INVALID, "Unsupported audio channel: " + channelName); - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/RenderingControlErrorCode.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/RenderingControlErrorCode.java deleted file mode 100644 index 03b96dd..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/RenderingControlErrorCode.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol; - -/** - * - */ -public enum RenderingControlErrorCode { - - INVALID_PRESET_NAME(701, "The specified name is not a valid preset name"), - INVALID_INSTANCE_ID(702, "The specified instanceID is invalid for this RenderingControl"); - - private int code; - private String description; - - RenderingControlErrorCode(int code, String description) { - this.code = code; - this.description = description; - } - - public int getCode() { - return code; - } - - public String getDescription() { - return description; - } - - public static RenderingControlErrorCode getByCode(int code) { - for (RenderingControlErrorCode errorCode : RenderingControlErrorCode.values()) { - if (errorCode.getCode() == code) - return errorCode; - } - return null; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/RenderingControlException.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/RenderingControlException.java deleted file mode 100644 index 18fd0f0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/RenderingControlException.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol; - -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.types.ErrorCode; - -/** - * - */ -public class RenderingControlException extends ActionException { - - public RenderingControlException(int errorCode, String message) { - super(errorCode, message); - } - - public RenderingControlException(int errorCode, String message, Throwable cause) { - super(errorCode, message, cause); - } - - public RenderingControlException(ErrorCode errorCode, String message) { - super(errorCode, message); - } - - public RenderingControlException(ErrorCode errorCode) { - super(errorCode); - } - - public RenderingControlException(RenderingControlErrorCode errorCode, String message) { - super(errorCode.getCode(), errorCode.getDescription() + ". " + message + "."); - } - - public RenderingControlException(RenderingControlErrorCode errorCode) { - super(errorCode.getCode(), errorCode.getDescription()); - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/GetMute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/GetMute.java deleted file mode 100644 index 3f0bc9a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/GetMute.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.Channel; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class GetMute extends ActionCallback { - - private static Logger log = Logger.getLogger(GetMute.class.getName()); - - public GetMute(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - public GetMute(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("GetMute"))); - getActionInvocation().setInput("InstanceID", instanceId); - getActionInvocation().setInput("Channel", Channel.Master.toString()); - } - - public void success(ActionInvocation invocation) { - boolean currentMute = (Boolean) invocation.getOutput("CurrentMute").getValue(); - received(invocation, currentMute); - } - - public abstract void received(ActionInvocation actionInvocation, boolean currentMute); -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/GetVolume.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/GetVolume.java deleted file mode 100644 index 4059057..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/GetVolume.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.Channel; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class GetVolume extends ActionCallback { - - private static Logger log = Logger.getLogger(GetVolume.class.getName()); - - public GetVolume(Service service) { - this(new UnsignedIntegerFourBytes(0), service); - } - - public GetVolume(UnsignedIntegerFourBytes instanceId, Service service) { - super(new ActionInvocation(service.getAction("GetVolume"))); - getActionInvocation().setInput("InstanceID", instanceId); - getActionInvocation().setInput("Channel", Channel.Master.toString()); - } - - public void success(ActionInvocation invocation) { - boolean ok = true; - int currentVolume = 0; - try { - currentVolume = Integer.valueOf(invocation.getOutput("CurrentVolume").getValue().toString()); // UnsignedIntegerTwoBytes... - } catch (Exception ex) { - invocation.setFailure( - new ActionException(ErrorCode.ACTION_FAILED, "Can't parse ProtocolInfo response: " + ex, ex) - ); - failure(invocation, null); - ok = false; - } - if (ok) received(invocation, currentVolume); - } - - public abstract void received(ActionInvocation actionInvocation, int currentVolume); - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/SetMute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/SetMute.java deleted file mode 100644 index 0ea6ff2..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/SetMute.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.support.model.Channel; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class SetMute extends ActionCallback { - - private static Logger log = Logger.getLogger(SetMute.class.getName()); - - public SetMute(Service service, boolean desiredMute) { - this(new UnsignedIntegerFourBytes(0), service, desiredMute); - } - - public SetMute(UnsignedIntegerFourBytes instanceId, Service service, boolean desiredMute) { - super(new ActionInvocation(service.getAction("SetMute"))); - getActionInvocation().setInput("InstanceID", instanceId); - getActionInvocation().setInput("Channel", Channel.Master.toString()); - getActionInvocation().setInput("DesiredMute", desiredMute); - } - - @Override - public void success(ActionInvocation invocation) { - log.fine("Executed successfully"); - - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/SetVolume.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/SetVolume.java deleted file mode 100644 index ef6afb9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/callback/SetVolume.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.callback; - -import org.fourthline.cling.controlpoint.ActionCallback; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.meta.Service; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes; -import org.fourthline.cling.support.model.Channel; - -import java.util.logging.Logger; - -/** - * - * @author Christian Bauer - */ -public abstract class SetVolume extends ActionCallback { - - private static Logger log = Logger.getLogger(SetVolume.class.getName()); - - public SetVolume(Service service, long newVolume) { - this(new UnsignedIntegerFourBytes(0), service, newVolume); - } - - public SetVolume(UnsignedIntegerFourBytes instanceId, Service service, long newVolume) { - super(new ActionInvocation(service.getAction("SetVolume"))); - getActionInvocation().setInput("InstanceID", instanceId); - getActionInvocation().setInput("Channel", Channel.Master.toString()); - getActionInvocation().setInput("DesiredVolume", new UnsignedIntegerTwoBytes(newVolume)); - } - - @Override - public void success(ActionInvocation invocation) { - log.fine("Executed successfully"); - - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelLoudness.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelLoudness.java deleted file mode 100644 index 96b775f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelLoudness.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.lastchange; - -import org.fourthline.cling.support.model.Channel; - -/** - * @author Christian Bauer - */ -public class ChannelLoudness { - - protected Channel channel; - protected Boolean loudness; - - public ChannelLoudness(Channel channel, Boolean loudness) { - this.channel = channel; - this.loudness = loudness; - } - - public Channel getChannel() { - return channel; - } - - public Boolean getLoudness() { - return loudness; - } - - @Override - public String toString() { - return "Loudness: " + getLoudness() + " (" + getChannel() + ")"; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelMute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelMute.java deleted file mode 100644 index b7ec6fe..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelMute.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.lastchange; - -import org.fourthline.cling.support.model.Channel; - -/** - * @author Christian Bauer - */ -public class ChannelMute { - - protected Channel channel; - protected Boolean mute; - - public ChannelMute(Channel channel, Boolean mute) { - this.channel = channel; - this.mute = mute; - } - - public Channel getChannel() { - return channel; - } - - public Boolean getMute() { - return mute; - } - - @Override - public String toString() { - return "Mute: " + getMute() + " (" + getChannel() + ")"; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelVolume.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelVolume.java deleted file mode 100644 index f7e729c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelVolume.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.lastchange; - -import org.fourthline.cling.support.model.Channel; - -/** - * @author Christian Bauer - */ -public class ChannelVolume { - - protected Channel channel; - protected Integer volume; - - public ChannelVolume(Channel channel, Integer volume) { - this.channel = channel; - this.volume = volume; - } - - public Channel getChannel() { - return channel; - } - - public Integer getVolume() { - return volume; - } - - @Override - public String toString() { - return "Volume: " + getVolume() + " (" + getChannel() + ")"; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelVolumeDB.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelVolumeDB.java deleted file mode 100644 index 7cf219d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/ChannelVolumeDB.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.lastchange; - -import org.fourthline.cling.support.model.Channel; - -/** - * @author Christian Bauer - */ -public class ChannelVolumeDB { - - protected Channel channel; - protected Integer volumeDB; - - public ChannelVolumeDB(Channel channel, Integer volumeDB) { - this.channel = channel; - this.volumeDB = volumeDB; - } - - public Channel getChannel() { - return channel; - } - - public Integer getVolumeDB() { - return volumeDB; - } - - @Override - public String toString() { - return "VolumeDB: " + getVolumeDB() + " (" + getChannel() + ")"; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelLoudness.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelLoudness.java deleted file mode 100644 index 9ed6540..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelLoudness.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.lastchange; - -import org.fourthline.cling.model.types.BooleanDatatype; -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.support.lastchange.EventedValue; -import org.fourthline.cling.support.model.Channel; -import org.fourthline.cling.support.shared.AbstractMap; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class EventedValueChannelLoudness extends EventedValue { - - public EventedValueChannelLoudness(ChannelLoudness value) { - super(value); - } - - public EventedValueChannelLoudness(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected ChannelLoudness valueOf(Map.Entry[] attributes) throws InvalidValueException { - Channel channel = null; - Boolean loudness = null; - for (Map.Entry attribute : attributes) { - if (attribute.getKey().equals("channel")) - channel = Channel.valueOf(attribute.getValue()); - if (attribute.getKey().equals("val")) - loudness = new BooleanDatatype().valueOf(attribute.getValue()); - } - return channel != null && loudness != null ? new ChannelLoudness(channel, loudness) : null; - } - - @Override - public Map.Entry[] getAttributes() { - return new Map.Entry[]{ - new AbstractMap.SimpleEntry<>( - "val", - new BooleanDatatype().getString(getValue().getLoudness()) - ), - new AbstractMap.SimpleEntry<>( - "channel", - getValue().getChannel().name() - ) - }; - } - - @Override - public String toString() { - return getValue().toString(); - } - - @Override - protected Datatype getDatatype() { - return null; // Not needed - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelMute.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelMute.java deleted file mode 100644 index 80d56f4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelMute.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.lastchange; - -import org.fourthline.cling.model.types.BooleanDatatype; -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.support.lastchange.EventedValue; -import org.fourthline.cling.support.model.Channel; -import org.fourthline.cling.support.shared.AbstractMap; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class EventedValueChannelMute extends EventedValue { - - public EventedValueChannelMute(ChannelMute value) { - super(value); - } - - public EventedValueChannelMute(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected ChannelMute valueOf(Map.Entry[] attributes) throws InvalidValueException { - Channel channel = null; - Boolean mute = null; - for (Map.Entry attribute : attributes) { - if (attribute.getKey().equals("channel")) - channel = Channel.valueOf(attribute.getValue()); - if (attribute.getKey().equals("val")) - mute = new BooleanDatatype().valueOf(attribute.getValue()); - } - return channel != null && mute != null ? new ChannelMute(channel, mute) : null; - } - - @Override - public Map.Entry[] getAttributes() { - return new Map.Entry[]{ - new AbstractMap.SimpleEntry<>( - "val", - new BooleanDatatype().getString(getValue().getMute()) - ), - new AbstractMap.SimpleEntry<>( - "channel", - getValue().getChannel().name() - ) - }; - } - - @Override - public String toString() { - return getValue().toString(); - } - - @Override - protected Datatype getDatatype() { - return null; // Not needed - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelVolume.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelVolume.java deleted file mode 100644 index f39b985..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelVolume.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.lastchange; - -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes; -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytesDatatype; -import org.fourthline.cling.support.lastchange.EventedValue; -import org.fourthline.cling.support.model.Channel; -import org.fourthline.cling.support.shared.AbstractMap; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class EventedValueChannelVolume extends EventedValue { - - public EventedValueChannelVolume(ChannelVolume value) { - super(value); - } - - public EventedValueChannelVolume(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected ChannelVolume valueOf(Map.Entry[] attributes) throws InvalidValueException { - Channel channel = null; - Integer volume = null; - for (Map.Entry attribute : attributes) { - if (attribute.getKey().equals("channel")) - channel = Channel.valueOf(attribute.getValue()); - if (attribute.getKey().equals("val")) - volume = (new UnsignedIntegerTwoBytesDatatype() - .valueOf(attribute.getValue())) - .getValue().intValue(); // Java is fun! - } - return channel != null && volume != null ? new ChannelVolume(channel, volume) : null; - } - - @Override - public Map.Entry[] getAttributes() { - return new Map.Entry[]{ - new AbstractMap.SimpleEntry<>( - "val", - new UnsignedIntegerTwoBytesDatatype().getString( - new UnsignedIntegerTwoBytes(getValue().getVolume()) - ) - ), - new AbstractMap.SimpleEntry<>( - "channel", - getValue().getChannel().name() - ) - }; - } - - @Override - public String toString() { - return getValue().toString(); - } - - @Override - protected Datatype getDatatype() { - return null; // Not needed - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelVolumeDB.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelVolumeDB.java deleted file mode 100644 index 77e8080..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/EventedValueChannelVolumeDB.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.lastchange; - -import org.fourthline.cling.model.types.Datatype; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes; -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytesDatatype; -import org.fourthline.cling.support.lastchange.EventedValue; -import org.fourthline.cling.support.model.Channel; -import org.fourthline.cling.support.shared.AbstractMap; - -import java.util.Map; - -/** - * @author Christian Bauer - */ -public class EventedValueChannelVolumeDB extends EventedValue { - - public EventedValueChannelVolumeDB(ChannelVolumeDB value) { - super(value); - } - - public EventedValueChannelVolumeDB(Map.Entry[] attributes) { - super(attributes); - } - - @Override - protected ChannelVolumeDB valueOf(Map.Entry[] attributes) throws InvalidValueException { - Channel channel = null; - Integer volumeDB = null; - for (Map.Entry attribute : attributes) { - if (attribute.getKey().equals("channel")) - channel = Channel.valueOf(attribute.getValue()); - if (attribute.getKey().equals("val")) - volumeDB = (new UnsignedIntegerTwoBytesDatatype() - .valueOf(attribute.getValue())) - .getValue().intValue(); // Java is fun! - } - return channel != null && volumeDB != null ? new ChannelVolumeDB(channel, volumeDB) : null; - } - - @Override - public Map.Entry[] getAttributes() { - return new Map.Entry[]{ - new AbstractMap.SimpleEntry<>( - "val", - new UnsignedIntegerTwoBytesDatatype().getString( - new UnsignedIntegerTwoBytes(getValue().getVolumeDB()) - ) - ), - new AbstractMap.SimpleEntry<>( - "channel", - getValue().getChannel().name() - ) - }; - } - - @Override - public String toString() { - return getValue().toString(); - } - - @Override - protected Datatype getDatatype() { - return null; // Not needed - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/RenderingControlLastChangeParser.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/RenderingControlLastChangeParser.java deleted file mode 100644 index 3dc415c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/RenderingControlLastChangeParser.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.lastchange; - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.support.lastchange.EventedValue; -import org.fourthline.cling.support.lastchange.LastChangeParser; - -import javax.xml.transform.Source; -import javax.xml.transform.stream.StreamSource; -import java.util.Set; - -/** - * @author Christian Bauer - */ -public class RenderingControlLastChangeParser extends LastChangeParser { - - public static final String NAMESPACE_URI = "urn:schemas-upnp-org:metadata-1-0/RCS/"; - public static final String SCHEMA_RESOURCE = "org/fourthline/cling/support/renderingcontrol/metadata-1.0-rcs.xsd"; - - @Override - protected String getNamespace() { - return NAMESPACE_URI; - } - - @Override - protected Source[] getSchemaSources() { - // TODO: Android 2.2 has a broken SchemaFactory, we can't validate - // http://code.google.com/p/android/issues/detail?id=9491&q=schemafactory&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars - if (!ModelUtil.ANDROID_RUNTIME) { - return new Source[]{new StreamSource( - Thread.currentThread().getContextClassLoader().getResourceAsStream(SCHEMA_RESOURCE) - )}; - } - return null; - } - - @Override - protected Set> getEventedVariables() { - return RenderingControlVariable.ALL; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/RenderingControlVariable.java b/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/RenderingControlVariable.java deleted file mode 100644 index 4772dfb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/renderingcontrol/lastchange/RenderingControlVariable.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.renderingcontrol.lastchange; - -import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes; -import org.fourthline.cling.support.lastchange.EventedValue; -import org.fourthline.cling.support.lastchange.EventedValueShort; -import org.fourthline.cling.support.lastchange.EventedValueString; -import org.fourthline.cling.support.lastchange.EventedValueUnsignedIntegerTwoBytes; - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * @author Christian Bauer - */ -public class RenderingControlVariable { - - public static Set> ALL = new HashSet>() {{ - add(PresetNameList.class); - add(Brightness.class); - add(Contrast.class); - add(Sharpness.class); - add(RedVideoGain.class); - add(BlueVideoGain.class); - add(GreenVideoGain.class); - add(RedVideoBlackLevel.class); - add(BlueVideoBlackLevel.class); - add(GreenVideoBlackLevel.class); - add(ColorTemperature.class); - add(HorizontalKeystone.class); - add(VerticalKeystone.class); - add(Mute.class); - add(VolumeDB.class); - add(Volume.class); - add(Loudness.class); - }}; - - public static class PresetNameList extends EventedValueString { - public PresetNameList(String s) { - super(s); - } - - public PresetNameList(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class Brightness extends EventedValueUnsignedIntegerTwoBytes { - public Brightness(UnsignedIntegerTwoBytes value) { - super(value); - } - - public Brightness(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class Contrast extends EventedValueUnsignedIntegerTwoBytes { - public Contrast(UnsignedIntegerTwoBytes value) { - super(value); - } - - public Contrast(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class Sharpness extends EventedValueUnsignedIntegerTwoBytes { - public Sharpness(UnsignedIntegerTwoBytes value) { - super(value); - } - - public Sharpness(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class RedVideoGain extends EventedValueUnsignedIntegerTwoBytes { - public RedVideoGain(UnsignedIntegerTwoBytes value) { - super(value); - } - - public RedVideoGain(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class BlueVideoGain extends EventedValueUnsignedIntegerTwoBytes { - public BlueVideoGain(UnsignedIntegerTwoBytes value) { - super(value); - } - - public BlueVideoGain(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class GreenVideoGain extends EventedValueUnsignedIntegerTwoBytes { - public GreenVideoGain(UnsignedIntegerTwoBytes value) { - super(value); - } - - public GreenVideoGain(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class RedVideoBlackLevel extends EventedValueUnsignedIntegerTwoBytes { - public RedVideoBlackLevel(UnsignedIntegerTwoBytes value) { - super(value); - } - - public RedVideoBlackLevel(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class BlueVideoBlackLevel extends EventedValueUnsignedIntegerTwoBytes { - public BlueVideoBlackLevel(UnsignedIntegerTwoBytes value) { - super(value); - } - - public BlueVideoBlackLevel(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class GreenVideoBlackLevel extends EventedValueUnsignedIntegerTwoBytes { - public GreenVideoBlackLevel(UnsignedIntegerTwoBytes value) { - super(value); - } - - public GreenVideoBlackLevel(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class ColorTemperature extends EventedValueUnsignedIntegerTwoBytes { - public ColorTemperature(UnsignedIntegerTwoBytes value) { - super(value); - } - - public ColorTemperature(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class HorizontalKeystone extends EventedValueShort { - public HorizontalKeystone(Short value) { - super(value); - } - - public HorizontalKeystone(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class VerticalKeystone extends EventedValueShort { - public VerticalKeystone(Short value) { - super(value); - } - - public VerticalKeystone(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class Mute extends EventedValueChannelMute { - public Mute(ChannelMute value) { - super(value); - } - - public Mute(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class VolumeDB extends EventedValueChannelVolumeDB { - public VolumeDB(ChannelVolumeDB value) { - super(value); - } - - public VolumeDB(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class Volume extends EventedValueChannelVolume { - public Volume(ChannelVolume value) { - super(value); - } - - public Volume(Map.Entry[] attributes) { - super(attributes); - } - } - - public static class Loudness extends EventedValueChannelLoudness { - public Loudness(ChannelLoudness value) { - super(value); - } - - public Loudness(Map.Entry[] attributes) { - super(attributes); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/AWTExceptionHandler.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/AWTExceptionHandler.java deleted file mode 100644 index d50104b..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/AWTExceptionHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -/** - * @author Christian Bauer - */ -public class AWTExceptionHandler { - - public void handle(Throwable ex) { - System.err.println("============= The application encountered an unrecoverable error, exiting... ============="); - ex.printStackTrace(System.err); - System.err.println("=========================================================================================="); - System.exit(1); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/AbstractMap.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/AbstractMap.java deleted file mode 100644 index d7188eb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/AbstractMap.java +++ /dev/null @@ -1,506 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -import java.io.Serializable; -import java.util.*; - -/** - * A base class for {@code Map} implementations. - * - *

Subclasses that permit new mappings to be added must override {@link - * #put}. - * - *

The default implementations of many methods are inefficient for large - * maps. For example in the default implementation, each call to {@link #get} - * performs a linear iteration of the entry set. Subclasses should override such - * methods to improve their performance. - * - * @since 1.2 - */ -public abstract class AbstractMap implements Map { - - // Lazily initialized key set. - Set keySet; - - Collection valuesCollection; - - /** - * An immutable key-value mapping. Despite the name, this class is non-final - * and its subclasses may be mutable. - * - * @since 1.6 - */ - public static class SimpleImmutableEntry - implements Map.Entry, Serializable { - private static final long serialVersionUID = 7138329143949025153L; - - private final K key; - private final V value; - - public SimpleImmutableEntry(K theKey, V theValue) { - key = theKey; - value = theValue; - } - - /** - * Constructs an instance with the key and value of {@code copyFrom}. - */ - public SimpleImmutableEntry(Map.Entry copyFrom) { - key = copyFrom.getKey(); - value = copyFrom.getValue(); - } - - public K getKey() { - return key; - } - - public V getValue() { - return value; - } - - /** - * This base implementation throws {@code UnsupportedOperationException} - * always. - */ - public V setValue(V object) { - throw new UnsupportedOperationException(); - } - - @Override public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof Map.Entry) { - Map.Entry entry = (Map.Entry) object; - return (key == null ? entry.getKey() == null : key.equals(entry - .getKey())) - && (value == null ? entry.getValue() == null : value - .equals(entry.getValue())); - } - return false; - } - - @Override public int hashCode() { - return (key == null ? 0 : key.hashCode()) - ^ (value == null ? 0 : value.hashCode()); - } - - @Override public String toString() { - return key + "=" + value; - } - } - - /** - * A key-value mapping with mutable values. - * - * @since 1.6 - */ - public static class SimpleEntry - implements Map.Entry, Serializable { - private static final long serialVersionUID = -8499721149061103585L; - - private final K key; - private V value; - - public SimpleEntry(K theKey, V theValue) { - key = theKey; - value = theValue; - } - - /** - * Constructs an instance with the key and value of {@code copyFrom}. - */ - public SimpleEntry(Map.Entry copyFrom) { - key = copyFrom.getKey(); - value = copyFrom.getValue(); - } - - public K getKey() { - return key; - } - - public V getValue() { - return value; - } - - public V setValue(V object) { - V result = value; - value = object; - return result; - } - - @Override public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof Map.Entry) { - Map.Entry entry = (Map.Entry) object; - return (key == null ? entry.getKey() == null : key.equals(entry - .getKey())) - && (value == null ? entry.getValue() == null : value - .equals(entry.getValue())); - } - return false; - } - - @Override public int hashCode() { - return (key == null ? 0 : key.hashCode()) - ^ (value == null ? 0 : value.hashCode()); - } - - @Override public String toString() { - return key + "=" + value; - } - } - - protected AbstractMap() { - super(); - } - - /** - * {@inheritDoc} - * - *

This implementation calls {@code entrySet().clear()}. - */ - public void clear() { - entrySet().clear(); - } - - /** - * {@inheritDoc} - * - *

This implementation iterates its key set, looking for a key that - * {@code key} equals. - */ - public boolean containsKey(Object key) { - Iterator> it = entrySet().iterator(); - if (key != null) { - while (it.hasNext()) { - if (key.equals(it.next().getKey())) { - return true; - } - } - } else { - while (it.hasNext()) { - if (it.next().getKey() == null) { - return true; - } - } - } - return false; - } - - /** - * {@inheritDoc} - * - *

This implementation iterates its entry set, looking for an entry with - * a value that {@code value} equals. - */ - public boolean containsValue(Object value) { - Iterator> it = entrySet().iterator(); - if (value != null) { - while (it.hasNext()) { - if (value.equals(it.next().getValue())) { - return true; - } - } - } else { - while (it.hasNext()) { - if (it.next().getValue() == null) { - return true; - } - } - } - return false; - } - - public abstract Set> entrySet(); - - /** - * {@inheritDoc} - * - *

This implementation first checks the structure of {@code object}. If - * it is not a map or of a different size, this returns false. Otherwise it - * iterates its own entry set, looking up each entry's key in {@code - * object}. If any value does not equal the other map's value for the same - * key, this returns false. Otherwise it returns true. - */ - @Override public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof Map) { - Map map = (Map) object; - if (size() != map.size()) { - return false; - } - - try { - for (Entry entry : entrySet()) { - K key = entry.getKey(); - V mine = entry.getValue(); - Object theirs = map.get(key); - if (mine == null) { - if (theirs != null || !map.containsKey(key)) { - return false; - } - } else if (!mine.equals(theirs)) { - return false; - } - } - } catch (NullPointerException ignored) { - return false; - } catch (ClassCastException ignored) { - return false; - } - return true; - } - return false; - } - - /** - * {@inheritDoc} - * - *

This implementation iterates its entry set, looking for an entry with - * a key that {@code key} equals. - */ - public V get(Object key) { - Iterator> it = entrySet().iterator(); - if (key != null) { - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (key.equals(entry.getKey())) { - return entry.getValue(); - } - } - } else { - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (entry.getKey() == null) { - return entry.getValue(); - } - } - } - return null; - } - - /** - * {@inheritDoc} - * - *

This implementation iterates its entry set, summing the hashcodes of - * its entries. - */ - @Override public int hashCode() { - int result = 0; - Iterator> it = entrySet().iterator(); - while (it.hasNext()) { - result += it.next().hashCode(); - } - return result; - } - - /** - * {@inheritDoc} - * - *

This implementation compares {@code size()} to 0. - */ - public boolean isEmpty() { - return size() == 0; - } - - /** - * {@inheritDoc} - * - *

This implementation returns a view that calls through this to map. Its - * iterator transforms this map's entry set iterator to return keys. - */ - public Set keySet() { - if (keySet == null) { - keySet = new AbstractSet() { - @Override public boolean contains(Object object) { - return containsKey(object); - } - - @Override public int size() { - return AbstractMap.this.size(); - } - - @Override public Iterator iterator() { - return new Iterator() { - Iterator> setIterator = entrySet().iterator(); - - public boolean hasNext() { - return setIterator.hasNext(); - } - - public K next() { - return setIterator.next().getKey(); - } - - public void remove() { - setIterator.remove(); - } - }; - } - }; - } - return keySet; - } - - /** - * {@inheritDoc} - * - *

This base implementation throws {@code UnsupportedOperationException}. - */ - public V put(K key, V value) { - throw new UnsupportedOperationException(); - } - - /** - * {@inheritDoc} - * - *

This implementation iterates through {@code map}'s entry set, calling - * {@code put()} for each. - */ - public void putAll(Map map) { - for (Map.Entry entry : map.entrySet()) { - put(entry.getKey(), entry.getValue()); - } - } - - /** - * {@inheritDoc} - * - *

This implementation iterates its entry set, removing the entry with - * a key that {@code key} equals. - */ - public V remove(Object key) { - Iterator> it = entrySet().iterator(); - if (key != null) { - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (key.equals(entry.getKey())) { - it.remove(); - return entry.getValue(); - } - } - } else { - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (entry.getKey() == null) { - it.remove(); - return entry.getValue(); - } - } - } - return null; - } - - /** - * {@inheritDoc} - * - *

This implementation returns its entry set's size. - */ - public int size() { - return entrySet().size(); - } - - /** - * {@inheritDoc} - * - *

This implementation composes a string by iterating its entry set. If - * this map contains itself as a key or a value, the string "(this Map)" - * will appear in its place. - */ - @Override public String toString() { - if (isEmpty()) { - return "{}"; - } - - StringBuilder buffer = new StringBuilder(size() * 28); - buffer.append('{'); - Iterator> it = entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - Object key = entry.getKey(); - if (key != this) { - buffer.append(key); - } else { - buffer.append("(this Map)"); - } - buffer.append('='); - Object value = entry.getValue(); - if (value != this) { - buffer.append(value); - } else { - buffer.append("(this Map)"); - } - if (it.hasNext()) { - buffer.append(", "); - } - } - buffer.append('}'); - return buffer.toString(); - } - - /** - * {@inheritDoc} - * - *

This implementation returns a view that calls through this to map. Its - * iterator transforms this map's entry set iterator to return values. - */ - public Collection values() { - if (valuesCollection == null) { - valuesCollection = new AbstractCollection() { - @Override public int size() { - return AbstractMap.this.size(); - } - - @Override public boolean contains(Object object) { - return containsValue(object); - } - - @Override public Iterator iterator() { - return new Iterator() { - Iterator> setIterator = entrySet().iterator(); - - public boolean hasNext() { - return setIterator.hasNext(); - } - - public V next() { - return setIterator.next().getValue(); - } - - public void remove() { - setIterator.remove(); - } - }; - } - }; - } - return valuesCollection; - } - - @SuppressWarnings("unchecked") - @Override protected Object clone() throws CloneNotSupportedException { - AbstractMap result = (AbstractMap) super.clone(); - result.keySet = null; - result.valuesCollection = null; - return result; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/CenterWindow.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/CenterWindow.java deleted file mode 100644 index 0a915ac..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/CenterWindow.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -import java.awt.Window; - -/** - * @author Christian Bauer - */ -public class CenterWindow { - - protected Window window; - - public CenterWindow(Window window) { - this.window = window; - } - - public Window getWindow() { - return window; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/CoreLogCategories.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/CoreLogCategories.java deleted file mode 100644 index bfe4fe0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/CoreLogCategories.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -import org.seamless.swing.logging.LogCategory; - -import java.util.ArrayList; -import java.util.logging.Level; - -/** - * @author Christian Bauer - */ -public class CoreLogCategories extends ArrayList { - - public CoreLogCategories() { - super(10); - - add(new LogCategory("Network", new LogCategory.Group[]{ - - new LogCategory.Group( - "UDP communication", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.transport.spi.DatagramIO.class.getName(), Level.FINE), - new LogCategory.LoggerLevel(org.fourthline.cling.transport.spi.MulticastReceiver.class.getName(), Level.FINE), - } - ), - - new LogCategory.Group( - "UDP datagram processing and content", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.transport.spi.DatagramProcessor.class.getName(), Level.FINER) - } - ), - - new LogCategory.Group( - "TCP communication", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.transport.spi.UpnpStream.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.transport.spi.StreamServer.class.getName(), Level.FINE), - new LogCategory.LoggerLevel(org.fourthline.cling.transport.spi.StreamClient.class.getName(), Level.FINE), - } - ), - - new LogCategory.Group( - "SOAP action message processing and content", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.transport.spi.SOAPActionProcessor.class.getName(), Level.FINER) - } - ), - - new LogCategory.Group( - "GENA event message processing and content", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.transport.spi.GENAEventProcessor.class.getName(), Level.FINER) - } - ), - - new LogCategory.Group( - "HTTP header processing", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.model.message.UpnpHeaders.class.getName(), Level.FINER) - } - ), - })); - - - add(new LogCategory("UPnP Protocol", new LogCategory.Group[]{ - - new LogCategory.Group( - "Discovery (Notification & Search)", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.ProtocolFactory.class.getName(), Level.FINER), - new LogCategory.LoggerLevel("org.fourthline.cling.protocol.async", Level.FINER) - } - ), - - new LogCategory.Group( - "Description", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.ProtocolFactory.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.RetrieveRemoteDescriptors.class.getName(), Level.FINE), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.sync.ReceivingRetrieval.class.getName(), Level.FINE), - new LogCategory.LoggerLevel(org.fourthline.cling.binding.xml.DeviceDescriptorBinder.class.getName(), Level.FINE), - new LogCategory.LoggerLevel(org.fourthline.cling.binding.xml.ServiceDescriptorBinder.class.getName(), Level.FINE), - } - ), - - new LogCategory.Group( - "Control", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.ProtocolFactory.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.sync.ReceivingAction.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.sync.SendingAction.class.getName(), Level.FINER), - } - ), - - new LogCategory.Group( - "GENA ", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel("org.fourthline.cling.model.gena", Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.ProtocolFactory.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.sync.ReceivingEvent.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.sync.ReceivingSubscribe.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.sync.ReceivingUnsubscribe.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.sync.SendingEvent.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.sync.SendingSubscribe.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.sync.SendingUnsubscribe.class.getName(), Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.protocol.sync.SendingRenewal.class.getName(), Level.FINER), - } - ), - })); - - add(new LogCategory("Core", new LogCategory.Group[]{ - - new LogCategory.Group( - "Router", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.transport.Router.class.getName(), Level.FINER) - } - ), - - new LogCategory.Group( - "Registry", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel(org.fourthline.cling.registry.Registry.class.getName(), Level.FINER), - } - ), - - new LogCategory.Group( - "Local service binding & invocation", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel("org.fourthline.cling.binding.annotations", Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.model.meta.LocalService.class.getName(), Level.FINER), - new LogCategory.LoggerLevel("org.fourthline.cling.model.action", Level.FINER), - new LogCategory.LoggerLevel("org.fourthline.cling.model.state", Level.FINER), - new LogCategory.LoggerLevel(org.fourthline.cling.model.DefaultServiceManager.class.getName(), Level.FINER) - } - ), - - new LogCategory.Group( - "Control Point interaction", - new LogCategory.LoggerLevel[]{ - new LogCategory.LoggerLevel("org.fourthline.cling.controlpoint", Level.FINER), - } - ), - })); - - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/Main.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/Main.java deleted file mode 100644 index d845647..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/Main.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -import org.fourthline.cling.support.shared.log.LogView; -import org.seamless.util.logging.LoggingUtil; -import org.seamless.swing.Application; -import org.seamless.swing.logging.LogMessage; -import org.seamless.swing.logging.LoggingHandler; -import org.seamless.util.OS; - -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; -import java.util.logging.LogManager; - -/** - * @author Christian Bauer - */ -public abstract class Main implements ShutdownHandler, Thread.UncaughtExceptionHandler { - - @Inject - LogView.Presenter logPresenter; - - final protected JFrame errorWindow = new JFrame(); - - // In addition to the JUL-configured handler, show log messages in the UI - final protected LoggingHandler loggingHandler = - new LoggingHandler() { - @Override - protected void log(LogMessage msg) { - logPresenter.pushMessage(msg); - } - }; - - protected boolean isRegularShutdown; - - public void init() { - - try { - // Platform specific setup - if (OS.checkForMac()) - NewPlatformApple.setup(this, getAppName()); - - // Some UI stuff (of course, why would the OS L&F be the default -- too easy?!) - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - - } catch (Exception ex) { - // Ignore... - } - - // Exception handler - errorWindow.setPreferredSize(new Dimension(900, 400)); - errorWindow.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent windowEvent) { - errorWindow.dispose(); - } - }); - Thread.setDefaultUncaughtExceptionHandler(this); - - // Shutdown behavior - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - if (!isRegularShutdown) { // Don't run the hook if everything is already stopped - shutdown(); - } - } - }); - - // Wire logging UI into JUL, don't reset JUL root logger but - // add our handler if there is a JUL config file - if (System.getProperty("java.util.logging.config.file") == null) { - LoggingUtil.resetRootHandler(loggingHandler); - } else { - LogManager.getLogManager().getLogger("").addHandler(loggingHandler); - } - } - - @Override - public void shutdown() { - isRegularShutdown = true; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - errorWindow.dispose(); - } - }); - } - - @Override - public void uncaughtException(Thread thread, final Throwable throwable) { - - System.err.println("In thread '" + thread + "' uncaught exception: " + throwable); - throwable.printStackTrace(System.err); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - errorWindow.getContentPane().removeAll(); - - JTextArea textArea = new JTextArea(); - textArea.setEditable(false); - StringBuilder text = new StringBuilder(); - - text.append("An exceptional error occurred!\nYou can try to continue or exit the application.\n\n"); - text.append("Please tell us about this here:\nhttp://www.4thline.org/projects/mailinglists-cling.html\n\n"); - text.append("-------------------------------------------------------------------------------------------------------------\n\n"); - Writer stackTrace = new StringWriter(); - throwable.printStackTrace(new PrintWriter(stackTrace)); - text.append(stackTrace.toString()); - - textArea.setText(text.toString()); - JScrollPane pane = new JScrollPane(textArea); - errorWindow.getContentPane().add(pane, BorderLayout.CENTER); - - JButton exitButton = new JButton("Exit Application"); - exitButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - System.exit(1); - } - }); - - errorWindow.getContentPane().add(exitButton, BorderLayout.SOUTH); - - errorWindow.pack(); - Application.center(errorWindow); - textArea.setCaretPosition(0); - - errorWindow.setVisible(true); - } - }); - } - - protected void removeLoggingHandler() { - LogManager.getLogManager().getLogger("").removeHandler(loggingHandler); - } - - abstract protected String getAppName(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/MainController.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/MainController.java deleted file mode 100644 index 40074ab..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/MainController.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -import org.fourthline.cling.UpnpService; -import org.seamless.util.logging.LoggingUtil; -import org.seamless.swing.AbstractController; -import org.seamless.swing.Application; -import org.seamless.swing.logging.LogCategory; -import org.seamless.swing.logging.LogController; -import org.seamless.swing.logging.LogMessage; -import org.seamless.swing.logging.LoggingHandler; - -import javax.swing.BorderFactory; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JWindow; -import javax.swing.UIManager; -import java.awt.Dimension; -import java.awt.Frame; -import java.util.List; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogManager; - -/** - * @author Christian Bauer - */ -public abstract class MainController extends AbstractController { - - // Dependencies - final private LogController logController; - - // View - final private JPanel logPanel; - - public MainController(JFrame view, List logCategories) { - super(view); - - // Some UI stuff (of course, why would the OS L&F be the default -- too easy?!) - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (Exception ex) { - System.out.println("Unable to load native look and feel: " + ex.toString()); - } - - // Exception handler - System.setProperty("sun.awt.exception.handler", AWTExceptionHandler.class.getName()); - - // Shutdown behavior - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - if (getUpnpService() != null) - getUpnpService().shutdown(); - } - }); - - // Logging UI - logController = new LogController(this, logCategories) { - @Override - protected void expand(LogMessage logMessage) { - fireEventGlobal( - new TextExpandEvent(logMessage.getMessage()) - ); - } - - @Override - protected Frame getParentWindow() { - return MainController.this.getView(); - } - }; - logPanel = logController.getView(); - logPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); - - // Wire UI into JUL - // Don't reset JUL root logger but add if there is a JUL config file) - Handler handler = new LoggingHandler() { - protected void log(LogMessage msg) { - logController.pushMessage(msg); - } - }; - if (System.getProperty("java.util.logging.config.file") == null) { - LoggingUtil.resetRootHandler(handler); - } else { - LogManager.getLogManager().getLogger("").addHandler(handler); - } - } - - public LogController getLogController() { - return logController; - } - - public JPanel getLogPanel() { - return logPanel; - } - - public void log(Level level, String msg) { - log(new LogMessage(level, msg)); - } - - public void log(LogMessage message) { - getLogController().pushMessage(message); - } - - @Override - public void dispose() { - super.dispose(); - ShutdownWindow.INSTANCE.setVisible(true); - new Thread() { - @Override - public void run() { - System.exit(0); - } - }.start(); - } - - public static class ShutdownWindow extends JWindow { - final public static JWindow INSTANCE = new ShutdownWindow(); - - protected ShutdownWindow() { - JLabel shutdownLabel = new JLabel("Shutting down, please wait..."); - shutdownLabel.setHorizontalAlignment(JLabel.CENTER); - getContentPane().add(shutdownLabel); - setPreferredSize(new Dimension(300, 30)); - pack(); - Application.center(this); - } - } - - public abstract UpnpService getUpnpService(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/NewPlatformApple.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/NewPlatformApple.java deleted file mode 100644 index 0b42bd3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/NewPlatformApple.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -/** - * @author Christian Bauer - */ -public class NewPlatformApple { - - public static void setup(final ShutdownHandler shutdownHandler, String appName) throws Exception { - - System.setProperty("apple.laf.useScreenMenuBar", "true"); - System.setProperty("com.apple.mrj.application.apple.menu.about.name", appName); - System.setProperty("apple.awt.showGrowBox", "true"); - - // Use reflection to avoid compile-time dependency - Class appClass = Class.forName("com.apple.eawt.Application"); - Object application = appClass.newInstance(); - Class listenerClass = Class.forName("com.apple.eawt.ApplicationListener"); - Method addAppListmethod = appClass.getDeclaredMethod("addApplicationListener", listenerClass); - - // creating and adding a custom adapter/listener to the Application - Class adapterClass = Class.forName("com.apple.eawt.ApplicationAdapter"); - Object listener = AppListenerProxy.newInstance(adapterClass.newInstance(), shutdownHandler); - addAppListmethod.invoke(application, listener); - } - - static class AppListenerProxy implements InvocationHandler { - - private ShutdownHandler shutdownHandler; - private Object object; - - public static Object newInstance(Object obj, ShutdownHandler shutdownHandler) { - return Proxy.newProxyInstance( - obj.getClass().getClassLoader(), - obj.getClass().getInterfaces(), - new AppListenerProxy(obj, shutdownHandler) - ); - } - - private AppListenerProxy(Object obj, ShutdownHandler shutdownHandler) { - this.object = obj; - this.shutdownHandler = shutdownHandler; - } - - public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { - Object result = null; - try { - if ("handleQuit".equals(m.getName())) { - if (shutdownHandler != null) { - shutdownHandler.shutdown(); - } - } else { - result = m.invoke(object, args); - } - } catch (Exception e) { - // Ignore - } - return result; - } - - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/PlatformApple.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/PlatformApple.java deleted file mode 100644 index b34b047..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/PlatformApple.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -import org.seamless.swing.Controller; - -import javax.swing.JFrame; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -/** - * @author Christian Bauer - */ -public class PlatformApple { - - public static void setup(final Controller appController, String appName) throws Exception { - - System.setProperty("apple.laf.useScreenMenuBar", "true"); - System.setProperty("com.apple.mrj.application.apple.menu.about.name", appName); - System.setProperty("apple.awt.showGrowBox", "true"); - - // Use reflection to avoid compile-time dependency - Class appClass = Class.forName("com.apple.eawt.Application"); - Object application = appClass.newInstance(); - Class listenerClass = Class.forName("com.apple.eawt.ApplicationListener"); - Method addAppListmethod = appClass.getDeclaredMethod("addApplicationListener", listenerClass); - - // creating and adding a custom adapter/listener to the Application - Class adapterClass = Class.forName("com.apple.eawt.ApplicationAdapter"); - Object listener = AppListenerProxy.newInstance(adapterClass.newInstance(), appController); - addAppListmethod.invoke(application, listener); - } - - static class AppListenerProxy implements InvocationHandler { - - private Controller appController; - private Object object; - - public static Object newInstance(Object obj, Controller appController) { - return Proxy.newProxyInstance( - obj.getClass().getClassLoader(), - obj.getClass().getInterfaces(), - new AppListenerProxy(obj, appController) - ); - } - - private AppListenerProxy(Object obj, Controller appController) { - this.object = obj; - this.appController = appController; - } - - public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { - Object result = null; - try { - if ("handleQuit".equals(m.getName())) { - if (appController != null) { - appController.dispose(); - appController.getView().dispose(); - } - } else { - result = m.invoke(object, args); - } - } catch (Exception e) { - // Ignore - } - return result; - } - - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/ShutdownHandler.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/ShutdownHandler.java deleted file mode 100644 index c1aca19..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/ShutdownHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -/** - * @author Christian Bauer - */ -public interface ShutdownHandler { - - void shutdown(); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpand.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpand.java deleted file mode 100644 index 83fee34..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpand.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -/** - * @author Christian Bauer - */ -public class TextExpand { - - public String text; - - public TextExpand(String text) { - this.text = text; - } - - public String getText() { - return text; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpandDialog.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpandDialog.java deleted file mode 100644 index 56846b2..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpandDialog.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -import org.fourthline.cling.model.ModelUtil; -import org.seamless.swing.Application; -import org.seamless.xml.DOM; -import org.seamless.xml.DOMParser; -import org.w3c.dom.Document; - -import javax.swing.JDialog; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import java.awt.Dimension; -import java.awt.Frame; -import java.util.logging.Logger; - -/** - * @author Christian Bauer - */ -public class TextExpandDialog extends JDialog { - - // TODO: Make this a plugin SPI and let the plugin impl decide how text should be detected and rendered - - private static Logger log = Logger.getLogger(TextExpandDialog.class.getName()); - - public TextExpandDialog(Frame frame, String text) { - super(frame); - setResizable(true); - - JTextArea textArea = new JTextArea(); - JScrollPane textPane = new JScrollPane(textArea); - textPane.setPreferredSize(new Dimension(500, 400)); - add(textPane); - - String pretty; - if (text.startsWith("<") && text.endsWith(">")) { - try { - pretty = new DOMParser() { - @Override - protected DOM createDOM(Document document) { - return null; - } - }.print(text, 2, false); - } catch (Exception ex) { - log.severe("Error pretty printing XML: " + ex.toString()); - pretty = text; - } - } else if (text.startsWith("http-get")) { - pretty = ModelUtil.commaToNewline(text); - } else { - pretty = text; - } - - textArea.setEditable(false); - textArea.setText(pretty); - - pack(); - Application.center(this, getOwner()); - setVisible(true); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpandEvent.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpandEvent.java deleted file mode 100644 index 476af00..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/TextExpandEvent.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -import org.seamless.swing.DefaultEvent; - - -public class TextExpandEvent extends DefaultEvent { - - public TextExpandEvent(String s) { - super(s); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/View.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/View.java deleted file mode 100644 index 5288ae7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/View.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared; - -import java.awt.Component; - -/** - * @author Christian Bauer - */ -public interface View

{ - - Component asUIComponent(); - - void setPresenter(P presenter); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/LogView.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/LogView.java deleted file mode 100644 index 4024b74..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/LogView.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared.log; - -import org.seamless.swing.logging.LogCategory; -import org.seamless.swing.logging.LogMessage; -import org.fourthline.cling.support.shared.View; - -import java.util.List; - -/** - * @author Christian Bauer - */ -public interface LogView extends View { - - public interface Presenter { - - void init(); - - void onExpand(LogMessage logMessage); - - void pushMessage(LogMessage logMessage); - } - - public interface LogCategories extends List { - } - - void pushMessage(LogMessage logMessage); - - void dispose(); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/impl/LogPresenter.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/impl/LogPresenter.java deleted file mode 100644 index 71e5acb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/impl/LogPresenter.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared.log.impl; - -import org.fourthline.cling.support.shared.TextExpand; -import org.fourthline.cling.support.shared.log.LogView; -import org.seamless.swing.logging.LogMessage; - -import javax.annotation.PreDestroy; -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.event.Event; -import javax.inject.Inject; -import javax.swing.SwingUtilities; - -/** - * @author Christian Bauer - */ -@ApplicationScoped -public class LogPresenter implements LogView.Presenter { - - @Inject - protected LogView view; - - @Inject - protected Event textExpandEvent; - - public void init() { - view.setPresenter(this); - } - - @Override - public void onExpand(LogMessage logMessage) { - textExpandEvent.fire(new TextExpand(logMessage.getMessage())); - } - - @PreDestroy - public void destroy() { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - view.dispose(); - } - }); - } - - @Override - public void pushMessage(final LogMessage message) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - view.pushMessage(message); - } - }); - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/impl/LogViewImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/impl/LogViewImpl.java deleted file mode 100644 index 56188ef..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/shared/log/impl/LogViewImpl.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.shared.log.impl; - -import org.fourthline.cling.support.shared.CenterWindow; -import org.fourthline.cling.support.shared.log.LogView; -import org.seamless.swing.Application; -import org.seamless.swing.logging.LogCategorySelector; -import org.seamless.swing.logging.LogController; -import org.seamless.swing.logging.LogMessage; -import org.seamless.swing.logging.LogTableCellRenderer; -import org.seamless.swing.logging.LogTableModel; - -import javax.annotation.PostConstruct; -import javax.enterprise.event.Event; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.JToolBar; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Christian Bauer - */ -@Singleton -public class LogViewImpl extends JPanel implements LogView { - - @Inject - protected LogCategories logCategories; - - @Inject - protected Event centerWindowEvent; - - protected LogCategorySelector logCategorySelector; - protected JTable logTable; - protected LogTableModel logTableModel; - - final protected JToolBar toolBar = new JToolBar(); - - final protected JButton configureButton = - new JButton("Options...", Application.createImageIcon(LogController.class, "img/configure.png")); - - final protected JButton clearButton = - new JButton("Clear Log", Application.createImageIcon(LogController.class, "img/removetext.png")); - - final protected JButton copyButton = - new JButton("Copy", Application.createImageIcon(LogController.class, "img/copyclipboard.png")); - - final protected JButton expandButton = - new JButton("Expand", Application.createImageIcon(LogController.class, "img/viewtext.png")); - - final protected JButton pauseButton = - new JButton("Pause/Continue Log", Application.createImageIcon(LogController.class, "img/pause.png")); - - final protected JLabel pauseLabel = new JLabel(" (Active)"); - - final protected JComboBox expirationComboBox = new JComboBox(LogController.Expiration.values()); - - protected Presenter presenter; - - @PostConstruct - public void init() { - setLayout(new BorderLayout()); - - LogController.Expiration defaultExpiration = getDefaultExpiration(); - - logCategorySelector = new LogCategorySelector(logCategories); - - logTableModel = new LogTableModel(defaultExpiration.getSeconds()); - logTable = new JTable(logTableModel); - - logTable.setDefaultRenderer( - LogMessage.class, - new LogTableCellRenderer() { - // TODO: These should be injected - protected ImageIcon getWarnErrorIcon() { - return LogViewImpl.this.getWarnErrorIcon(); - } - - protected ImageIcon getDebugIcon() { - return LogViewImpl.this.getDebugIcon(); - } - - protected ImageIcon getTraceIcon() { - return LogViewImpl.this.getTraceIcon(); - } - - protected ImageIcon getInfoIcon() { - return LogViewImpl.this.getInfoIcon(); - } - }); - - logTable.setCellSelectionEnabled(false); - logTable.setRowSelectionAllowed(true); - logTable.getSelectionModel().addListSelectionListener( - new ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { - - if (e.getValueIsAdjusting()) return; - - if (e.getSource() == logTable.getSelectionModel()) { - int[] rows = logTable.getSelectedRows(); - - if (rows == null || rows.length == 0) { - copyButton.setEnabled(false); - expandButton.setEnabled(false); - } else if (rows.length == 1) { - copyButton.setEnabled(true); - LogMessage msg = (LogMessage) logTableModel.getValueAt(rows[0], 0); - // TODO: This setting should be injected - if (msg.getMessage().length() > getExpandMessageCharacterLimit()) { - expandButton.setEnabled(true); - } else { - expandButton.setEnabled(false); - } - } else { - copyButton.setEnabled(true); - expandButton.setEnabled(false); - } - } - } - } - ); - - adjustTableUI(); - initializeToolBar(defaultExpiration); - - setPreferredSize(new Dimension(250, 100)); - setMinimumSize(new Dimension(250, 50)); - add(new JScrollPane(logTable), BorderLayout.CENTER); - add(toolBar, BorderLayout.SOUTH); - } - - @Override - public Component asUIComponent() { - return this; - } - - @Override - public void setPresenter(Presenter presenter) { - this.presenter = presenter; - } - - @Override - public void pushMessage(LogMessage logMessage) { - logTableModel.pushMessage(logMessage); - - // Scroll to bottom if nothing is selected - if (!logTableModel.isPaused()) { - logTable.scrollRectToVisible( - logTable.getCellRect(logTableModel.getRowCount() - 1, 0, true) - ); - } - } - - @Override - public void dispose() { - logCategorySelector.dispose(); - } - - protected void adjustTableUI() { - logTable.setFocusable(false); - logTable.setRowHeight(18); - logTable.getTableHeader().setReorderingAllowed(false); - logTable.setBorder(BorderFactory.createEmptyBorder()); - - logTable.getColumnModel().getColumn(0).setMinWidth(30); - logTable.getColumnModel().getColumn(0).setMaxWidth(30); - logTable.getColumnModel().getColumn(0).setResizable(false); - - - logTable.getColumnModel().getColumn(1).setMinWidth(90); - logTable.getColumnModel().getColumn(1).setMaxWidth(90); - logTable.getColumnModel().getColumn(1).setResizable(false); - - logTable.getColumnModel().getColumn(2).setMinWidth(110); - logTable.getColumnModel().getColumn(2).setMaxWidth(250); - - logTable.getColumnModel().getColumn(3).setPreferredWidth(150); - logTable.getColumnModel().getColumn(3).setMaxWidth(400); - - logTable.getColumnModel().getColumn(4).setPreferredWidth(600); - } - - protected void initializeToolBar(LogController.Expiration expiration) { - configureButton.setFocusable(false); - configureButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - centerWindowEvent.fire(new CenterWindow(logCategorySelector)); - logCategorySelector.setVisible(!logCategorySelector.isVisible()); - } - }); - - clearButton.setFocusable(false); - clearButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - logTableModel.clearMessages(); - } - }); - - copyButton.setFocusable(false); - copyButton.setEnabled(false); - copyButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - StringBuilder sb = new StringBuilder(); - List messages = getSelectedMessages(); - for (LogMessage message : messages) { - sb.append(message.toString()).append("\n"); - } - Application.copyToClipboard(sb.toString()); - } - }); - - expandButton.setFocusable(false); - expandButton.setEnabled(false); - expandButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - List messages = getSelectedMessages(); - if (messages.size() != 1) return; - presenter.onExpand(messages.get(0)); - } - }); - - pauseButton.setFocusable(false); - pauseButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - logTableModel.setPaused(!logTableModel.isPaused()); - if (logTableModel.isPaused()) { - pauseLabel.setText(" (Paused)"); - } else { - pauseLabel.setText(" (Active)"); - } - } - }); - - expirationComboBox.setSelectedItem(expiration); - expirationComboBox.setMaximumSize(new Dimension(100, 32)); - expirationComboBox.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - JComboBox cb = (JComboBox) e.getSource(); - LogController.Expiration expiration = (LogController.Expiration) cb.getSelectedItem(); - logTableModel.setMaxAgeSeconds(expiration.getSeconds()); - } - }); - - toolBar.setFloatable(false); - toolBar.add(copyButton); - toolBar.add(expandButton); - toolBar.add(Box.createHorizontalGlue()); - toolBar.add(configureButton); - toolBar.add(clearButton); - toolBar.add(pauseButton); - toolBar.add(pauseLabel); - toolBar.add(Box.createHorizontalGlue()); - toolBar.add(new JLabel("Clear after:")); - toolBar.add(expirationComboBox); - } - - protected LogController.Expiration getDefaultExpiration() { - return LogController.Expiration.SIXTY_SECONDS; - } - - protected ImageIcon getWarnErrorIcon() { - return Application.createImageIcon(LogController.class, "img/warn.png"); - } - - protected ImageIcon getDebugIcon() { - return Application.createImageIcon(LogController.class, "img/debug.png"); - } - - protected ImageIcon getTraceIcon() { - return Application.createImageIcon(LogController.class, "img/trace.png"); - } - - protected ImageIcon getInfoIcon() { - return Application.createImageIcon(LogController.class, "img/info.png"); - } - - protected int getExpandMessageCharacterLimit() { - return 100; - } - - protected List getSelectedMessages() { - List messages = new ArrayList<>(); - for (int row : logTable.getSelectedRows()) { - messages.add((LogMessage) logTableModel.getValueAt(row, 0)); - } - return messages; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/support/xmicrosoft/AbstractMediaReceiverRegistrarService.java b/clinglibrary/src/main/java/org/fourthline/cling/support/xmicrosoft/AbstractMediaReceiverRegistrarService.java deleted file mode 100644 index a635dcf..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/support/xmicrosoft/AbstractMediaReceiverRegistrarService.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.support.xmicrosoft; - -import org.fourthline.cling.binding.annotations.UpnpAction; -import org.fourthline.cling.binding.annotations.UpnpInputArgument; -import org.fourthline.cling.binding.annotations.UpnpOutputArgument; -import org.fourthline.cling.binding.annotations.UpnpService; -import org.fourthline.cling.binding.annotations.UpnpServiceId; -import org.fourthline.cling.binding.annotations.UpnpServiceType; -import org.fourthline.cling.binding.annotations.UpnpStateVariable; -import org.fourthline.cling.binding.annotations.UpnpStateVariables; -import org.fourthline.cling.model.types.UnsignedIntegerFourBytes; - -import java.beans.PropertyChangeSupport; - -/** - * Basic implementation of service required by MSFT devices such as XBox 360. - * - * @author Mario Franco - */ -@UpnpService( - serviceId = @UpnpServiceId( - namespace = "microsoft.com", - value = "X_MS_MediaReceiverRegistrar" - ), - serviceType = @UpnpServiceType( - namespace = "microsoft.com", - value = "X_MS_MediaReceiverRegistrar", - version = 1 - ) -) -@UpnpStateVariables( - { - @UpnpStateVariable(name = "A_ARG_TYPE_DeviceID", - sendEvents = false, - datatype = "string"), - @UpnpStateVariable(name = "A_ARG_TYPE_Result", - sendEvents = false, - datatype = "int"), - @UpnpStateVariable(name = "A_ARG_TYPE_RegistrationReqMsg", - sendEvents = false, - datatype = "bin.base64"), - @UpnpStateVariable(name = "A_ARG_TYPE_RegistrationRespMsg", - sendEvents = false, - datatype = "bin.base64") - } -) -public abstract class AbstractMediaReceiverRegistrarService { - - final protected PropertyChangeSupport propertyChangeSupport; - - @UpnpStateVariable(eventMinimumDelta = 1) - private UnsignedIntegerFourBytes authorizationGrantedUpdateID = new UnsignedIntegerFourBytes(0); - - @UpnpStateVariable(eventMinimumDelta = 1) - private UnsignedIntegerFourBytes authorizationDeniedUpdateID = new UnsignedIntegerFourBytes(0); - - @UpnpStateVariable - private UnsignedIntegerFourBytes validationSucceededUpdateID = new UnsignedIntegerFourBytes(0); - - @UpnpStateVariable - private UnsignedIntegerFourBytes validationRevokedUpdateID = new UnsignedIntegerFourBytes(0); - - protected AbstractMediaReceiverRegistrarService() { - this(null); - } - - protected AbstractMediaReceiverRegistrarService(PropertyChangeSupport propertyChangeSupport) { - this.propertyChangeSupport = propertyChangeSupport != null ? propertyChangeSupport : new PropertyChangeSupport(this); - } - - public PropertyChangeSupport getPropertyChangeSupport() { - return propertyChangeSupport; - } - - - @UpnpAction(out = @UpnpOutputArgument(name = "AuthorizationGrantedUpdateID")) - public UnsignedIntegerFourBytes getAuthorizationGrantedUpdateID() { - return authorizationGrantedUpdateID; - } - - @UpnpAction(out = @UpnpOutputArgument(name = "AuthorizationDeniedUpdateID")) - public UnsignedIntegerFourBytes getAuthorizationDeniedUpdateID() { - return authorizationDeniedUpdateID; - } - - @UpnpAction(out = @UpnpOutputArgument(name = "ValidationSucceededUpdateID")) - public UnsignedIntegerFourBytes getValidationSucceededUpdateID() { - return validationSucceededUpdateID; - } - - @UpnpAction(out = @UpnpOutputArgument(name = "ValidationRevokedUpdateID")) - public UnsignedIntegerFourBytes getValidationRevokedUpdateID() { - return validationRevokedUpdateID; - } - - @UpnpAction(out = { - @UpnpOutputArgument(name = "Result", - stateVariable = "A_ARG_TYPE_Result") - }) - public int isAuthorized(@UpnpInputArgument(name = "DeviceID", - stateVariable = "A_ARG_TYPE_DeviceID") - String deviceID) { - return 1; - } - - @UpnpAction(out = { - @UpnpOutputArgument(name = "Result", - stateVariable = "A_ARG_TYPE_Result") - }) - public int isValidated(@UpnpInputArgument(name = "DeviceID", - stateVariable = "A_ARG_TYPE_DeviceID") - String deviceID) { - return 1; - } - - @UpnpAction(out = { - @UpnpOutputArgument(name = "RegistrationRespMsg", - stateVariable = "A_ARG_TYPE_RegistrationRespMsg") - }) - public byte[] registerDevice(@UpnpInputArgument(name = "RegistrationReqMsg", - stateVariable = "A_ARG_TYPE_RegistrationReqMsg") - byte[] registrationReqMsg) { - return new byte[]{}; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/DisableRouter.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/DisableRouter.java deleted file mode 100644 index cd2b4cf..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/DisableRouter.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport; - -/** - * @author Christian Bauer - */ -public class DisableRouter { -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/EnableRouter.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/EnableRouter.java deleted file mode 100644 index 9dc25ba..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/EnableRouter.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport; - -/** - * @author Christian Bauer - */ -public class EnableRouter { -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/Router.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/Router.java deleted file mode 100644 index 1619dea..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/Router.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport; - -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.model.NetworkAddress; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.OutgoingDatagramMessage; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.transport.spi.InitializationException; -import org.fourthline.cling.transport.spi.UpnpStream; - -import java.net.InetAddress; -import java.util.List; - -/** - * Interface of the network transport layer. - *

- * Encapsulates the transport layer and provides methods to the upper layers for - * sending UPnP stream (HTTP) {@link org.fourthline.cling.model.message.StreamRequestMessage}s, - * sending (UDP) datagram {@link org.fourthline.cling.model.message.OutgoingDatagramMessage}s, - * as well as broadcasting bytes to all LAN participants. - *

- *

- * A router also maintains listening sockets and services, for incoming UDP unicast/multicast - * {@link org.fourthline.cling.model.message.IncomingDatagramMessage} and TCP - * {@link org.fourthline.cling.transport.spi.UpnpStream}s. An implementation of this interface - * handles these messages, e.g. by selecting and executing the right protocol. - *

- *

- * An implementation must be thread-safe, and can be accessed concurrently. If the Router is - * disabled, it doesn't listen on the network for incoming messages and does not send outgoing - * messages. - *

- * - * @see org.fourthline.cling.protocol.ProtocolFactory - * - * @author Christian Bauer - */ -public interface Router { - - /** - * @return The configuration used by this router. - */ - public UpnpServiceConfiguration getConfiguration(); - - /** - * @return The protocol factory used by this router. - */ - public ProtocolFactory getProtocolFactory(); - - /** - * Starts all sockets and listening threads for datagrams and streams. - * - * @return true if the router was enabled. false if it's already running. - */ - boolean enable() throws RouterException; - - /** - * Unbinds all sockets and stops all listening threads for datagrams and streams. - * - * @return true if the router was disabled. false if it wasn't running. - */ - boolean disable() throws RouterException; - - /** - * Disables the router and releases all other resources. - */ - void shutdown() throws RouterException ; - - /** - * - * @return true if the router is currently enabled. - */ - boolean isEnabled() throws RouterException; - - /** - * Called by the {@link #enable()} method before it returns. - * - * @param ex The cause of the failure. - * @throws InitializationException if the exception was not recoverable. - */ - void handleStartFailure(InitializationException ex) throws InitializationException; - - /** - * @param preferredAddress A preferred stream server bound address or null. - * @return An empty list if no stream server is currently active, otherwise a single network - * address if the preferred address is active, or a list of all active bound - * stream servers. - */ - public List getActiveStreamServers(InetAddress preferredAddress) throws RouterException; - - /** - *

- * This method is called internally by the transport layer when a datagram, either unicast or - * multicast, has been received. An implementation of this interface has to handle the received - * message, e.g. selecting and executing a UPnP protocol. This method should not block until - * the execution completes, the calling thread should be free to handle the next reception as - * soon as possible. - *

- * @param msg The received datagram message. - */ - public void received(IncomingDatagramMessage msg); - - /** - *

- * This method is called internally by the transport layer when a TCP stream connection has - * been made and a response has to be returned to the sender. An implementation of this interface - * has to handle the received stream connection and return a response, e.g. selecting and executing - * a UPnP protocol. This method should not block until the execution completes, the calling thread - * should be free to process the next reception as soon as possible. Typically this means starting - * a new thread of execution in this method. - *

- * @param stream - */ - public void received(UpnpStream stream); - - /** - *

- * Call this method to send a UDP datagram message. - *

- * @param msg The UDP datagram message to send. - * @throws RouterException if a recoverable error, such as thread interruption, occurs. - */ - public void send(OutgoingDatagramMessage msg) throws RouterException; - - /** - *

- * Call this method to send a TCP (HTTP) stream message. - *

- * @param msg The TCP (HTTP) stream message to send. - * @return The response received from the server. - * @throws RouterException if a recoverable error, such as thread interruption, occurs. - */ - public StreamResponseMessage send(StreamRequestMessage msg) throws RouterException; - - /** - *

- * Call this method to broadcast a UDP message to all hosts on the network. - *

- * @param bytes The byte payload of the UDP datagram. - * @throws RouterException if a recoverable error, such as thread interruption, occurs. - */ - public void broadcast(byte[] bytes) throws RouterException; - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/RouterException.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/RouterException.java deleted file mode 100644 index 1c7a47f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/RouterException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.transport; - -/** - * Thrown by the {@link Router} if a non-fatal recoverable exception occurred. - *

- * This exception is thrown if the calling thread wasn't able to obtain - * exclusive read/write access on the router. - *

- *

- * This exception is also thrown when you interrupt the thread calling the - * router. In such a case, the cause of this is an InterruptedException. - *

- * - * @author Christian Bauer - */ -public class RouterException extends Exception { - - public RouterException() { - super(); - } - - public RouterException(String s) { - super(s); - } - - public RouterException(String s, Throwable throwable) { - super(s, throwable); - } - - public RouterException(Throwable throwable) { - super(throwable); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/RouterImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/RouterImpl.java deleted file mode 100644 index ad9a9b7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/RouterImpl.java +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport; - -import org.fourthline.cling.UpnpServiceConfiguration; -import org.fourthline.cling.model.NetworkAddress; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.OutgoingDatagramMessage; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.protocol.ProtocolCreationException; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.protocol.ReceivingAsync; -import org.fourthline.cling.transport.spi.DatagramIO; -import org.fourthline.cling.transport.spi.InitializationException; -import org.fourthline.cling.transport.spi.MulticastReceiver; -import org.fourthline.cling.transport.spi.NetworkAddressFactory; -import org.fourthline.cling.transport.spi.NoNetworkException; -import org.fourthline.cling.transport.spi.StreamClient; -import org.fourthline.cling.transport.spi.StreamServer; -import org.fourthline.cling.transport.spi.UpnpStream; -import org.seamless.util.Exceptions; - -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.event.Observes; -import javax.enterprise.inject.Default; -import javax.inject.Inject; -import java.net.BindException; -import java.net.DatagramPacket; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Default implementation of network message router. - *

- * Initializes and starts listening for data on the network when enabled. - *

- * - * @author Christian Bauer - */ -@ApplicationScoped -public class RouterImpl implements Router { - - private static Logger log = Logger.getLogger(Router.class.getName()); - - protected UpnpServiceConfiguration configuration; - protected ProtocolFactory protocolFactory; - - protected volatile boolean enabled; - protected ReentrantReadWriteLock routerLock = new ReentrantReadWriteLock(true); - protected Lock readLock = routerLock.readLock(); - protected Lock writeLock = routerLock.writeLock(); - - // These are created/destroyed when the router is enabled/disabled - protected NetworkAddressFactory networkAddressFactory; - protected StreamClient streamClient; - protected final Map multicastReceivers = new HashMap<>(); - protected final Map datagramIOs = new HashMap<>(); - protected final Map streamServers = new HashMap<>(); - - protected RouterImpl() { - } - - /** - * @param configuration The configuration used by this router. - * @param protocolFactory The protocol factory used by this router. - */ - @Inject - public RouterImpl(UpnpServiceConfiguration configuration, ProtocolFactory protocolFactory) { - log.info("Creating Router: " + getClass().getName()); - this.configuration = configuration; - this.protocolFactory = protocolFactory; - } - - public boolean enable(@Observes @Default EnableRouter event) throws RouterException { - return enable(); - } - - public boolean disable(@Observes @Default DisableRouter event) throws RouterException { - return disable(); - } - - public UpnpServiceConfiguration getConfiguration() { - return configuration; - } - - public ProtocolFactory getProtocolFactory() { - return protocolFactory; - } - - /** - * Initializes listening services: First an instance of {@link org.fourthline.cling.transport.spi.MulticastReceiver} - * is bound to each network interface. Then an instance of {@link org.fourthline.cling.transport.spi.DatagramIO} and - * {@link org.fourthline.cling.transport.spi.StreamServer} is bound to each bind address returned by the network - * address factory, respectively. There is only one instance of - * {@link org.fourthline.cling.transport.spi.StreamClient} created and managed by this router. - */ - @Override - public boolean enable() throws RouterException { - lock(writeLock); - try { - if (!enabled) { - try { - log.fine("Starting networking services..."); - networkAddressFactory = getConfiguration().createNetworkAddressFactory(); - - startInterfaceBasedTransports(networkAddressFactory.getNetworkInterfaces()); - startAddressBasedTransports(networkAddressFactory.getBindAddresses()); - - // The transports possibly removed some unusable network interfaces/addresses - if (!networkAddressFactory.hasUsableNetwork()) { - throw new NoNetworkException( - "No usable network interface and/or addresses available, check the log for errors." - ); - } - - // Start the HTTP client last, we don't even have to try if there is no network - streamClient = getConfiguration().createStreamClient(); - - enabled = true; - return true; - } catch (InitializationException ex) { - handleStartFailure(ex); - } - } - return false; - } finally { - unlock(writeLock); - } - } - - @Override - public boolean disable() throws RouterException { - lock(writeLock); - try { - if (enabled) { - log.fine("Disabling network services..."); - - if (streamClient != null) { - log.fine("Stopping stream client connection management/pool"); - streamClient.stop(); - streamClient = null; - } - - for (Map.Entry entry : streamServers.entrySet()) { - log.fine("Stopping stream server on address: " + entry.getKey()); - entry.getValue().stop(); - } - streamServers.clear(); - - for (Map.Entry entry : multicastReceivers.entrySet()) { - log.fine("Stopping multicast receiver on interface: " + entry.getKey().getDisplayName()); - entry.getValue().stop(); - } - multicastReceivers.clear(); - - for (Map.Entry entry : datagramIOs.entrySet()) { - log.fine("Stopping datagram I/O on address: " + entry.getKey()); - entry.getValue().stop(); - } - datagramIOs.clear(); - - networkAddressFactory = null; - enabled = false; - return true; - } - return false; - } finally { - unlock(writeLock); - } - } - - @Override - public void shutdown() throws RouterException { - disable(); - } - - @Override - public boolean isEnabled() { - return enabled; - } - - @Override - public void handleStartFailure(InitializationException ex) throws InitializationException { - if (ex instanceof NoNetworkException) { - log.info("Unable to initialize network router, no network found."); - } else { - log.severe("Unable to initialize network router: " + ex); - log.severe("Cause: " + Exceptions.unwrap(ex)); - } - } - - public List getActiveStreamServers(InetAddress preferredAddress) throws RouterException { - lock(readLock); - try { - if (enabled && streamServers.size() > 0) { - List streamServerAddresses = new ArrayList<>(); - - StreamServer preferredServer; - if (preferredAddress != null && - (preferredServer = streamServers.get(preferredAddress)) != null) { - streamServerAddresses.add( - new NetworkAddress( - preferredAddress, - preferredServer.getPort(), - networkAddressFactory.getHardwareAddress(preferredAddress) - - ) - ); - return streamServerAddresses; - } - - for (Map.Entry entry : streamServers.entrySet()) { - byte[] hardwareAddress = networkAddressFactory.getHardwareAddress(entry.getKey()); - streamServerAddresses.add( - new NetworkAddress(entry.getKey(), entry.getValue().getPort(), hardwareAddress) - ); - } - return streamServerAddresses; - } else { - return Collections.EMPTY_LIST; - } - } finally { - unlock(readLock); - } - } - - /** - * Obtains the asynchronous protocol {@code Executor} and runs the protocol created - * by the {@link org.fourthline.cling.protocol.ProtocolFactory} for the given message. - *

- * If the factory doesn't create a protocol, the message is dropped immediately without - * creating another thread or consuming further resources. This means we can filter the - * datagrams in the protocol factory and e.g. completely disable discovery or only - * allow notification message from some known services we'd like to work with. - *

- * - * @param msg The received datagram message. - */ - public void received(IncomingDatagramMessage msg) { - if (!enabled) { - log.fine("Router disabled, ignoring incoming message: " + msg); - return; - } - try { - ReceivingAsync protocol = getProtocolFactory().createReceivingAsync(msg); - if (protocol == null) { - if (log.isLoggable(Level.FINEST)) - log.finest("No protocol, ignoring received message: " + msg); - return; - } - if (log.isLoggable(Level.FINE)) - log.fine("Received asynchronous message: " + msg); - getConfiguration().getAsyncProtocolExecutor().execute(protocol); - } catch (ProtocolCreationException ex) { - log.warning("Handling received datagram failed - " + Exceptions.unwrap(ex).toString()); - } - } - - /** - * Obtains the synchronous protocol {@code Executor} and runs the - * {@link org.fourthline.cling.transport.spi.UpnpStream} directly. - * - * @param stream The received {@link org.fourthline.cling.transport.spi.UpnpStream}. - */ - public void received(UpnpStream stream) { - if (!enabled) { - log.fine("Router disabled, ignoring incoming: " + stream); - return; - } - log.fine("Received synchronous stream: " + stream); - getConfiguration().getSyncProtocolExecutorService().execute(stream); - } - - /** - * Sends the UDP datagram on all bound {@link org.fourthline.cling.transport.spi.DatagramIO}s. - * - * @param msg The UDP datagram message to send. - */ - public void send(OutgoingDatagramMessage msg) throws RouterException { - lock(readLock); - try { - if (enabled) { - for (DatagramIO datagramIO : datagramIOs.values()) { - datagramIO.send(msg); - } - } else { - log.fine("Router disabled, not sending datagram: " + msg); - } - } finally { - unlock(readLock); - } - } - - /** - * Sends the TCP stream request with the {@link org.fourthline.cling.transport.spi.StreamClient}. - * - * @param msg The TCP (HTTP) stream message to send. - * @return The return value of the {@link org.fourthline.cling.transport.spi.StreamClient#sendRequest(StreamRequestMessage)} - * method or null if no StreamClient is available. - */ - public StreamResponseMessage send(StreamRequestMessage msg) throws RouterException { - lock(readLock); - try { - if (enabled) { - if (streamClient == null) { - log.fine("No StreamClient available, not sending: " + msg); - return null; - } - log.fine("Sending via TCP unicast stream: " + msg); - try { - return streamClient.sendRequest(msg); - } catch (InterruptedException ex) { - throw new RouterException("Sending stream request was interrupted", ex); - } - } else { - log.fine("Router disabled, not sending stream request: " + msg); - return null; - } - } finally { - unlock(readLock); - } - } - - /** - * Sends the given bytes as a broadcast on all bound {@link org.fourthline.cling.transport.spi.DatagramIO}s, - * using source port 9. - *

- * TODO: Support source port parameter - *

- * - * @param bytes The byte payload of the UDP datagram. - */ - public void broadcast(byte[] bytes) throws RouterException { - lock(readLock); - try { - if (enabled) { - for (Map.Entry entry : datagramIOs.entrySet()) { - InetAddress broadcast = networkAddressFactory.getBroadcastAddress(entry.getKey()); - if (broadcast != null) { - log.fine("Sending UDP datagram to broadcast address: " + broadcast.getHostAddress()); - DatagramPacket packet = new DatagramPacket(bytes, bytes.length, broadcast, 9); - entry.getValue().send(packet); - } - } - } else { - log.fine("Router disabled, not broadcasting bytes: " + bytes.length); - } - } finally { - unlock(readLock); - } - } - - protected void startInterfaceBasedTransports(Iterator interfaces) throws InitializationException { - while (interfaces.hasNext()) { - NetworkInterface networkInterface = interfaces.next(); - - // We only have the MulticastReceiver as an interface-based transport - MulticastReceiver multicastReceiver = getConfiguration().createMulticastReceiver(networkAddressFactory); - if (multicastReceiver == null) { - log.info("Configuration did not create a MulticastReceiver for: " + networkInterface); - } else { - try { - if (log.isLoggable(Level.FINE)) - log.fine("Init multicast receiver on interface: " + networkInterface.getDisplayName()); - multicastReceiver.init( - networkInterface, - this, - networkAddressFactory, - getConfiguration().getDatagramProcessor() - ); - - multicastReceivers.put(networkInterface, multicastReceiver); - } catch (InitializationException ex) { - /* TODO: What are some recoverable exceptions for this? - log.warning( - "Ignoring network interface '" - + networkInterface.getDisplayName() - + "' init failure of MulticastReceiver: " + ex.toString()); - if (log.isLoggable(Level.FINE)) - log.log(Level.FINE, "Initialization exception root cause", Exceptions.unwrap(ex)); - log.warning("Removing unusable interface " + interface); - it.remove(); - continue; // Don't need to try anything else on this interface - */ - throw ex; - } - } - } - - for (Map.Entry entry : multicastReceivers.entrySet()) { - if (log.isLoggable(Level.FINE)) - log.fine("Starting multicast receiver on interface: " + entry.getKey().getDisplayName()); - getConfiguration().getMulticastReceiverExecutor().execute(entry.getValue()); - } - } - - protected void startAddressBasedTransports(Iterator addresses) throws InitializationException { - while (addresses.hasNext()) { - InetAddress address = addresses.next(); - - // HTTP servers - StreamServer streamServer = getConfiguration().createStreamServer(networkAddressFactory); - if (streamServer == null) { - log.info("Configuration did not create a StreamServer for: " + address); - } else { - try { - if (log.isLoggable(Level.FINE)) - log.fine("Init stream server on address: " + address); - streamServer.init(address, this); - streamServers.put(address, streamServer); - } catch (InitializationException ex) { - // Try to recover - Throwable cause = Exceptions.unwrap(ex); - if (cause instanceof BindException) { - log.warning("Failed to init StreamServer: " + cause); - if (log.isLoggable(Level.FINE)) - log.log(Level.FINE, "Initialization exception root cause", cause); - log.warning("Removing unusable address: " + address); - addresses.remove(); - continue; // Don't try anything else with this address - } - throw ex; - } - } - - // Datagram I/O - DatagramIO datagramIO = getConfiguration().createDatagramIO(networkAddressFactory); - if (datagramIO == null) { - log.info("Configuration did not create a StreamServer for: " + address); - } else { - try { - if (log.isLoggable(Level.FINE)) - log.fine("Init datagram I/O on address: " + address); - datagramIO.init(address, this, getConfiguration().getDatagramProcessor()); - datagramIOs.put(address, datagramIO); - } catch (InitializationException ex) { - /* TODO: What are some recoverable exceptions for this? - Throwable cause = Exceptions.unwrap(ex); - if (cause instanceof BindException) { - log.warning("Failed to init datagram I/O: " + cause); - if (log.isLoggable(Level.FINE)) - log.log(Level.FINE, "Initialization exception root cause", cause); - log.warning("Removing unusable address: " + address); - addresses.remove(); - continue; // Don't try anything else with this address - } - */ - throw ex; - } - } - } - - for (Map.Entry entry : streamServers.entrySet()) { - if (log.isLoggable(Level.FINE)) - log.fine("Starting stream server on address: " + entry.getKey()); - getConfiguration().getStreamServerExecutorService().execute(entry.getValue()); - } - - for (Map.Entry entry : datagramIOs.entrySet()) { - if (log.isLoggable(Level.FINE)) - log.fine("Starting datagram I/O on address: " + entry.getKey()); - getConfiguration().getDatagramIOExecutor().execute(entry.getValue()); - } - } - - protected void lock(Lock lock, int timeoutMilliseconds) throws RouterException { - try { - log.finest("Trying to obtain lock with timeout milliseconds '" + timeoutMilliseconds + "': " + lock.getClass().getSimpleName()); - if (lock.tryLock(timeoutMilliseconds, TimeUnit.MILLISECONDS)) { - log.finest("Acquired router lock: " + lock.getClass().getSimpleName()); - } else { - throw new RouterException( - "Router wasn't available exclusively after waiting " + timeoutMilliseconds + "ms, lock failed: " - + lock.getClass().getSimpleName() - ); - } - } catch (InterruptedException ex) { - throw new RouterException( - "Interruption while waiting for exclusive access: " + lock.getClass().getSimpleName(), ex - ); - } - } - - protected void lock(Lock lock) throws RouterException { - lock(lock, getLockTimeoutMillis()); - } - - protected void unlock(Lock lock) { - log.finest("Releasing router lock: " + lock.getClass().getSimpleName()); - lock.unlock(); - } - - /** - * @return Defaults to 6 seconds, should be longer than it takes the router to be enabled/disabled. - */ - protected int getLockTimeoutMillis() { - return 6000; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletStreamServerConfigurationImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletStreamServerConfigurationImpl.java deleted file mode 100644 index afdc0e3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletStreamServerConfigurationImpl.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.transport.spi.ServletContainerAdapter; -import org.fourthline.cling.transport.spi.StreamServerConfiguration; - -/** - * Settings for the async Servlet 3.0 implementation. - *

- * If you are trying to integrate Cling with an existing/running servlet - * container, implement {@link org.fourthline.cling.transport.spi.ServletContainerAdapter}. - *

- * - * @author Christian Bauer - */ -public class AsyncServletStreamServerConfigurationImpl implements StreamServerConfiguration { - - protected ServletContainerAdapter servletContainerAdapter; - protected int listenPort = 0; - protected int asyncTimeoutSeconds = 60; - - /** - * Defaults to port '0', ephemeral. - */ - public AsyncServletStreamServerConfigurationImpl(ServletContainerAdapter servletContainerAdapter) { - this.servletContainerAdapter = servletContainerAdapter; - } - - public AsyncServletStreamServerConfigurationImpl(ServletContainerAdapter servletContainerAdapter, - int listenPort) { - this.servletContainerAdapter = servletContainerAdapter; - this.listenPort = listenPort; - } - - public AsyncServletStreamServerConfigurationImpl(ServletContainerAdapter servletContainerAdapter, - int listenPort, - int asyncTimeoutSeconds) { - this.servletContainerAdapter = servletContainerAdapter; - this.listenPort = listenPort; - this.asyncTimeoutSeconds = asyncTimeoutSeconds; - } - - /** - * @return Defaults to 0. - */ - public int getListenPort() { - return listenPort; - } - - public void setListenPort(int listenPort) { - this.listenPort = listenPort; - } - - /** - * The time in seconds this server wait for the {@link org.fourthline.cling.transport.Router} - * to execute a {@link org.fourthline.cling.transport.spi.UpnpStream}. - * - * @return The default of 60 seconds. - */ - public int getAsyncTimeoutSeconds() { - return asyncTimeoutSeconds; - } - - public void setAsyncTimeoutSeconds(int asyncTimeoutSeconds) { - this.asyncTimeoutSeconds = asyncTimeoutSeconds; - } - - public ServletContainerAdapter getServletContainerAdapter() { - return servletContainerAdapter; - } - - public void setServletContainerAdapter(ServletContainerAdapter servletContainerAdapter) { - this.servletContainerAdapter = servletContainerAdapter; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletStreamServerImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletStreamServerImpl.java deleted file mode 100644 index 7ed8936..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletStreamServerImpl.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.model.message.Connection; -import org.fourthline.cling.transport.Router; -import org.fourthline.cling.transport.spi.InitializationException; -import org.fourthline.cling.transport.spi.StreamServer; - -import javax.servlet.AsyncContext; -import javax.servlet.AsyncEvent; -import javax.servlet.AsyncListener; -import javax.servlet.Servlet; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Implementation based on Servlet 3.0 API. - * - * @author Christian Bauer - */ -public class AsyncServletStreamServerImpl implements StreamServer { - - final private static Logger log = Logger.getLogger(StreamServer.class.getName()); - - final protected AsyncServletStreamServerConfigurationImpl configuration; - protected int localPort; - protected String hostAddress; - - public AsyncServletStreamServerImpl(AsyncServletStreamServerConfigurationImpl configuration) { - this.configuration = configuration; - } - - public AsyncServletStreamServerConfigurationImpl getConfiguration() { - return configuration; - } - - synchronized public void init(InetAddress bindAddress, final Router router) throws InitializationException { - try { - if (log.isLoggable(Level.FINE)) - log.fine("Setting executor service on servlet container adapter"); - getConfiguration().getServletContainerAdapter().setExecutorService( - router.getConfiguration().getStreamServerExecutorService() - ); - - if (log.isLoggable(Level.FINE)) - log.fine("Adding connector: " + bindAddress + ":" + getConfiguration().getListenPort()); - hostAddress = bindAddress.getHostAddress(); - localPort = getConfiguration().getServletContainerAdapter().addConnector( - hostAddress, - getConfiguration().getListenPort() - ); - - String contextPath = router.getConfiguration().getNamespace().getBasePath().getPath(); - getConfiguration().getServletContainerAdapter().registerServlet(contextPath, createServlet(router)); - - } catch (Exception ex) { - throw new InitializationException("Could not initialize " + getClass().getSimpleName() + ": " + ex.toString(), ex); - } - } - - synchronized public int getPort() { - return this.localPort; - } - - synchronized public void stop() { - getConfiguration().getServletContainerAdapter().removeConnector(hostAddress, localPort); - } - - public void run() { - getConfiguration().getServletContainerAdapter().startIfNotRunning(); - } - - private int mCounter = 0; - - protected Servlet createServlet(final Router router) { - return new HttpServlet() { - @Override - protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - - final long startTime = System.currentTimeMillis(); - final int counter = mCounter++; - if (log.isLoggable(Level.FINE)) - log.fine(String.format("HttpServlet.service(): id: %3d, request URI: %s", counter, req.getRequestURI())); - - AsyncContext async = req.startAsync(); - async.setTimeout(getConfiguration().getAsyncTimeoutSeconds()*1000); - - async.addListener(new AsyncListener() { - - @Override - public void onTimeout(AsyncEvent arg0) throws IOException { - long duration = System.currentTimeMillis() - startTime; - if (log.isLoggable(Level.FINE)) - log.fine(String.format("AsyncListener.onTimeout(): id: %3d, duration: %,4d, request: %s", counter, duration, arg0.getSuppliedRequest())); - } - - - @Override - public void onStartAsync(AsyncEvent arg0) throws IOException { - if (log.isLoggable(Level.FINE)) - log.fine(String.format("AsyncListener.onStartAsync(): id: %3d, request: %s", counter, arg0.getSuppliedRequest())); - } - - - @Override - public void onError(AsyncEvent arg0) throws IOException { - long duration = System.currentTimeMillis() - startTime; - if (log.isLoggable(Level.FINE)) - log.fine(String.format("AsyncListener.onError(): id: %3d, duration: %,4d, response: %s", counter, duration, arg0.getSuppliedResponse())); - } - - - @Override - public void onComplete(AsyncEvent arg0) throws IOException { - long duration = System.currentTimeMillis() - startTime; - if (log.isLoggable(Level.FINE)) - log.fine(String.format("AsyncListener.onComplete(): id: %3d, duration: %,4d, response: %s", counter, duration, arg0.getSuppliedResponse())); - } - - }); - - AsyncServletUpnpStream stream = - new AsyncServletUpnpStream(router.getProtocolFactory(), async, req) { - @Override - protected Connection createConnection() { - return new AsyncServletConnection(getRequest()); - } - }; - - router.received(stream); - } - }; - } - - /** - * Override this method if you can check, at a low level, if the client connection is still open - * for the given request. This will likely require access to proprietary APIs of your servlet - * container to obtain the socket/channel for the given request. - * - * @return By default true. - */ - protected boolean isConnectionOpen(HttpServletRequest request) { - return true; - } - - protected class AsyncServletConnection implements Connection { - - protected HttpServletRequest request; - - public AsyncServletConnection(HttpServletRequest request) { - this.request = request; - } - - public HttpServletRequest getRequest() { - return request; - } - - @Override - public boolean isOpen() { - return AsyncServletStreamServerImpl.this.isConnectionOpen(getRequest()); - } - - @Override - public InetAddress getRemoteAddress() { - try { - return InetAddress.getByName(getRequest().getRemoteAddr()); - } catch (UnknownHostException ex) { - throw new RuntimeException(ex); - } - } - - @Override - public InetAddress getLocalAddress() { - try { - return InetAddress.getByName(getRequest().getLocalAddr()); - } catch (UnknownHostException ex) { - throw new RuntimeException(ex); - } - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletUpnpStream.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletUpnpStream.java deleted file mode 100644 index 2326ab3..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/AsyncServletUpnpStream.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.model.message.Connection; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.UpnpMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.transport.spi.UpnpStream; -import org.seamless.util.Exceptions; -import org.seamless.util.io.IO; - -import javax.servlet.AsyncContext; -import javax.servlet.AsyncEvent; -import javax.servlet.AsyncListener; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URI; -import java.util.Enumeration; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Implementation based on Servlet 3.0 API. - *

- * Concrete implementations must provide a connection wrapper, as this wrapper most likely has - * to access proprietary APIs to implement connection checking. - *

- * - * @author Christian Bauer - */ -public abstract class AsyncServletUpnpStream extends UpnpStream implements AsyncListener { - - final private static Logger log = Logger.getLogger(UpnpStream.class.getName()); - - final protected AsyncContext asyncContext; - final protected HttpServletRequest request; - - protected StreamResponseMessage responseMessage; - - public AsyncServletUpnpStream(ProtocolFactory protocolFactory, - AsyncContext asyncContext, - HttpServletRequest request) { - super(protocolFactory); - this.asyncContext = asyncContext; - this.request = request; - asyncContext.addListener(this); - } - - protected HttpServletRequest getRequest() { - return request; - } - - protected HttpServletResponse getResponse() { - ServletResponse response; - if ((response = asyncContext.getResponse()) == null) { - throw new IllegalStateException( - "Couldn't get response from asynchronous context, already timed out" - ); - } - return (HttpServletResponse) response; - } - - protected void complete() { - try { - asyncContext.complete(); - } catch (IllegalStateException ex) { - // If Jetty's connection, for whatever reason, is in an illegal state, this will be thrown - // and we can "probably" ignore it. The request is complete, no matter how it ended. - log.info("Error calling servlet container's AsyncContext#complete() method: " + ex); - } - } - - @Override - public void run() { - try { - StreamRequestMessage requestMessage = readRequestMessage(); - if (log.isLoggable(Level.FINER)) - log.finer("Processing new request message: " + requestMessage); - - responseMessage = process(requestMessage); - - if (responseMessage != null) { - if (log.isLoggable(Level.FINER)) - log.finer("Preparing HTTP response message: " + responseMessage); - writeResponseMessage(responseMessage); - } else { - // If it's null, it's 404 - if (log.isLoggable(Level.FINER)) - log.finer("Sending HTTP response status: " + HttpURLConnection.HTTP_NOT_FOUND); - getResponse().setStatus(HttpServletResponse.SC_NOT_FOUND); - } - - } catch (Throwable t) { - log.info("Exception occurred during UPnP stream processing: " + t); - if (log.isLoggable(Level.FINER)) { - log.log(Level.FINER, "Cause: " + Exceptions.unwrap(t), Exceptions.unwrap(t)); - } - if (!getResponse().isCommitted()) { - log.finer("Response hasn't been committed, returning INTERNAL SERVER ERROR to client"); - getResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } else { - log.info("Could not return INTERNAL SERVER ERROR to client, response was already committed"); - } - responseException(t); - } finally { - complete(); - } - } - - @Override - public void onStartAsync(AsyncEvent event) throws IOException { - // This is a completely useless callback, it will only be called on request.startAsync() which - // then immediately removes the listener... what were they thinking. - } - - @Override - public void onComplete(AsyncEvent event) throws IOException { - if (log.isLoggable(Level.FINER)) - log.finer("Completed asynchronous processing of HTTP request: " + event.getSuppliedRequest()); - responseSent(responseMessage); - } - - @Override - public void onTimeout(AsyncEvent event) throws IOException { - if (log.isLoggable(Level.FINER)) - log.finer("Asynchronous processing of HTTP request timed out: " + event.getSuppliedRequest()); - responseException(new Exception("Asynchronous request timed out")); - } - - @Override - public void onError(AsyncEvent event) throws IOException { - if (log.isLoggable(Level.FINER)) - log.finer("Asynchronous processing of HTTP request error: " + event.getThrowable()); - responseException(event.getThrowable()); - } - - protected StreamRequestMessage readRequestMessage() throws IOException { - // Extract what we need from the HTTP httpRequest - String requestMethod = getRequest().getMethod(); - String requestURI = getRequest().getRequestURI(); - - if (log.isLoggable(Level.FINER)) - log.finer("Processing HTTP request: " + requestMethod + " " + requestURI); - - StreamRequestMessage requestMessage; - try { - requestMessage = - new StreamRequestMessage( - UpnpRequest.Method.getByHttpName(requestMethod), - URI.create(requestURI) - ); - } catch (IllegalArgumentException ex) { - throw new RuntimeException("Invalid request URI: " + requestURI, ex); - } - - if (requestMessage.getOperation().getMethod().equals(UpnpRequest.Method.UNKNOWN)) { - throw new RuntimeException("Method not supported: " + requestMethod); - } - - // Connection wrapper - requestMessage.setConnection(createConnection()); - - // Headers - UpnpHeaders headers = new UpnpHeaders(); - Enumeration headerNames = getRequest().getHeaderNames(); - while (headerNames.hasMoreElements()) { - String headerName = headerNames.nextElement(); - Enumeration headerValues = getRequest().getHeaders(headerName); - while (headerValues.hasMoreElements()) { - String headerValue = headerValues.nextElement(); - headers.add(headerName, headerValue); - } - } - requestMessage.setHeaders(headers); - - // Body - byte[] bodyBytes; - InputStream is = null; - try { - is = getRequest().getInputStream(); - bodyBytes = IO.readBytes(is); - } finally { - if (is != null) - is.close(); - } - if (log.isLoggable(Level.FINER)) - log.finer("Reading request body bytes: " + bodyBytes.length); - - if (bodyBytes.length > 0 && requestMessage.isContentTypeMissingOrText()) { - - if (log.isLoggable(Level.FINER)) - log.finer("Request contains textual entity body, converting then setting string on message"); - requestMessage.setBodyCharacters(bodyBytes); - - } else if (bodyBytes.length > 0) { - - if (log.isLoggable(Level.FINER)) - log.finer("Request contains binary entity body, setting bytes on message"); - requestMessage.setBody(UpnpMessage.BodyType.BYTES, bodyBytes); - - } else { - if (log.isLoggable(Level.FINER)) - log.finer("Request did not contain entity body"); - } - - return requestMessage; - } - - protected void writeResponseMessage(StreamResponseMessage responseMessage) throws IOException { - if (log.isLoggable(Level.FINER)) - log.finer("Sending HTTP response status: " + responseMessage.getOperation().getStatusCode()); - - getResponse().setStatus(responseMessage.getOperation().getStatusCode()); - - // Headers - for (Map.Entry> entry : responseMessage.getHeaders().entrySet()) { - for (String value : entry.getValue()) { - getResponse().addHeader(entry.getKey(), value); - } - } - // The Date header is recommended in UDA - getResponse().setDateHeader("Date", System.currentTimeMillis()); - - // Body - byte[] responseBodyBytes = responseMessage.hasBody() ? responseMessage.getBodyBytes() : null; - int contentLength = responseBodyBytes != null ? responseBodyBytes.length : -1; - - if (contentLength > 0) { - getResponse().setContentLength(contentLength); - log.finer("Response message has body, writing bytes to stream..."); - IO.writeBytes(getResponse().getOutputStream(), responseBodyBytes); - } - } - - abstract protected Connection createConnection(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramIOConfigurationImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramIOConfigurationImpl.java deleted file mode 100644 index 9570d44..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramIOConfigurationImpl.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.transport.spi.DatagramIOConfiguration; - -/** - * Settings for the default implementation. - * - * @author Christian Bauer - */ -public class DatagramIOConfigurationImpl implements DatagramIOConfiguration { - - private int timeToLive = 4; - private int maxDatagramBytes = 640; - - /** - * Defaults to TTL of '4' and maximum datagram size of 640 bytes (512 per UDA 1.0, 128 byte header). - */ - public DatagramIOConfigurationImpl() { - } - - public DatagramIOConfigurationImpl(int timeToLive, int maxDatagramBytes) { - this.timeToLive = timeToLive; - this.maxDatagramBytes = maxDatagramBytes; - } - - public int getTimeToLive() { - return timeToLive; - } - - public void setTimeToLive(int timeToLive) { - this.timeToLive = timeToLive; - } - - public int getMaxDatagramBytes() { - return maxDatagramBytes; - } - - public void setMaxDatagramBytes(int maxDatagramBytes) { - this.maxDatagramBytes = maxDatagramBytes; - } -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramIOImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramIOImpl.java deleted file mode 100644 index 455bcf9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramIOImpl.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.model.message.OutgoingDatagramMessage; -import org.fourthline.cling.transport.Router; -import org.fourthline.cling.transport.spi.DatagramIO; -import org.fourthline.cling.transport.spi.DatagramProcessor; -import org.fourthline.cling.transport.spi.InitializationException; -import org.fourthline.cling.model.UnsupportedDataException; - -import java.net.DatagramPacket; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MulticastSocket; -import java.net.SocketException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Default implementation based on a single shared (receive/send) UDP MulticastSocket. - *

- * Although we do not receive multicast datagrams with this service, sending multicast - * datagrams with a configuration time-to-live requires a MulticastSocket. - *

- *

- * Thread-safety is guaranteed through synchronization of methods of this service and - * by the thread-safe underlying socket. - *

- * @author Christian Bauer - */ -public class DatagramIOImpl implements DatagramIO { - - private static Logger log = Logger.getLogger(DatagramIO.class.getName()); - - /* Implementation notes for unicast/multicast UDP: - - http://forums.sun.com/thread.jspa?threadID=771852 - http://mail.openjdk.java.net/pipermail/net-dev/2008-December/000497.html - https://jira.jboss.org/jira/browse/JGRP-978 - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4701650 - - */ - - final protected DatagramIOConfigurationImpl configuration; - - protected Router router; - protected DatagramProcessor datagramProcessor; - - protected InetSocketAddress localAddress; - protected MulticastSocket socket; // For sending unicast & multicast, and reveiving unicast - - public DatagramIOImpl(DatagramIOConfigurationImpl configuration) { - this.configuration = configuration; - } - - public DatagramIOConfigurationImpl getConfiguration() { - return configuration; - } - - synchronized public void init(InetAddress bindAddress, Router router, DatagramProcessor datagramProcessor) throws InitializationException { - - this.router = router; - this.datagramProcessor = datagramProcessor; - - try { - - // TODO: UPNP VIOLATION: The spec does not prohibit using the 1900 port here again, however, the - // Netgear ReadyNAS miniDLNA implementation will no longer answer if it has to send search response - // back via UDP unicast to port 1900... so we use an ephemeral port - log.info("Creating bound socket (for datagram input/output) on: " + bindAddress); - localAddress = new InetSocketAddress(bindAddress, 0); - socket = new MulticastSocket(localAddress); - socket.setTimeToLive(configuration.getTimeToLive()); - socket.setReceiveBufferSize(262144); // Keep a backlog of incoming datagrams if we are not fast enough - } catch (Exception ex) { - throw new InitializationException("Could not initialize " + getClass().getSimpleName() + ": " + ex); - } - } - - synchronized public void stop() { - if (socket != null && !socket.isClosed()) { - socket.close(); - } - } - - public void run() { - log.fine("Entering blocking receiving loop, listening for UDP datagrams on: " + socket.getLocalAddress()); - - while (true) { - - try { - byte[] buf = new byte[getConfiguration().getMaxDatagramBytes()]; - DatagramPacket datagram = new DatagramPacket(buf, buf.length); - - socket.receive(datagram); - - log.fine( - "UDP datagram received from: " - + datagram.getAddress().getHostAddress() - + ":" + datagram.getPort() - + " on: " + localAddress - ); - - - router.received(datagramProcessor.read(localAddress.getAddress(), datagram)); - - } catch (SocketException ex) { - log.fine("Socket closed"); - break; - } catch (UnsupportedDataException ex) { - log.info("Could not read datagram: " + ex.getMessage()); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - try { - if (!socket.isClosed()) { - log.fine("Closing unicast socket"); - socket.close(); - } - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - synchronized public void send(OutgoingDatagramMessage message) { - if (log.isLoggable(Level.FINE)) { - log.fine("Sending message from address: " + localAddress); - } - DatagramPacket packet = datagramProcessor.write(message); - - if (log.isLoggable(Level.FINE)) { - log.fine("Sending UDP datagram packet to: " + message.getDestinationAddress() + ":" + message.getDestinationPort()); - } - - send(packet); - } - - synchronized public void send(DatagramPacket datagram) { - if (log.isLoggable(Level.FINE)) { - log.fine("Sending message from address: " + localAddress); - } - - try { - socket.send(datagram); - } catch (SocketException ex) { - log.fine("Socket closed, aborting datagram send to: " + datagram.getAddress()); - } catch (RuntimeException ex) { - throw ex; - } catch (Exception ex) { - log.log(Level.SEVERE, "Exception sending datagram to: " + datagram.getAddress() + ": " + ex, ex); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramProcessorImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramProcessorImpl.java deleted file mode 100644 index 6aec239..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/DatagramProcessorImpl.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import java.util.logging.Logger; -import java.util.logging.Level; - -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.OutgoingDatagramMessage; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.UpnpOperation; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.transport.spi.DatagramProcessor; -import org.fourthline.cling.model.UnsupportedDataException; -import org.seamless.http.Headers; - -import java.io.ByteArrayInputStream; -import java.io.UnsupportedEncodingException; -import java.net.DatagramPacket; -import java.net.InetAddress; -import java.util.Locale; - -/** - * Default implementation. - * - * @author Christian Bauer - */ -public class DatagramProcessorImpl implements DatagramProcessor { - - private static Logger log = Logger.getLogger(DatagramProcessor.class.getName()); - - public IncomingDatagramMessage read(InetAddress receivedOnAddress, DatagramPacket datagram) throws UnsupportedDataException { - - try { - - if (log.isLoggable(Level.FINER)) { - log.finer("===================================== DATAGRAM BEGIN ============================================"); - log.finer(new String(datagram.getData(), "UTF-8")); - log.finer("-===================================== DATAGRAM END ============================================="); - } - - ByteArrayInputStream is = new ByteArrayInputStream(datagram.getData()); - - String[] startLine = Headers.readLine(is).split(" "); - if (startLine[0].startsWith("HTTP/1.")) { - return readResponseMessage(receivedOnAddress, datagram, is, Integer.valueOf(startLine[1]), startLine[2], startLine[0]); - } else { - return readRequestMessage(receivedOnAddress, datagram, is, startLine[0], startLine[2]); - } - - } catch (Exception ex) { - throw new UnsupportedDataException("Could not parse headers: " + ex, ex, datagram.getData()); - } - } - - public DatagramPacket write(OutgoingDatagramMessage message) throws UnsupportedDataException { - - StringBuilder statusLine = new StringBuilder(); - - UpnpOperation operation = message.getOperation(); - - if (operation instanceof UpnpRequest) { - - UpnpRequest requestOperation = (UpnpRequest) operation; - statusLine.append(requestOperation.getHttpMethodName()).append(" * "); - statusLine.append("HTTP/1.").append(operation.getHttpMinorVersion()).append("\r\n"); - - } else if (operation instanceof UpnpResponse) { - UpnpResponse responseOperation = (UpnpResponse) operation; - statusLine.append("HTTP/1.").append(operation.getHttpMinorVersion()).append(" "); - statusLine.append(responseOperation.getStatusCode()).append(" ").append(responseOperation.getStatusMessage()); - statusLine.append("\r\n"); - } else { - throw new UnsupportedDataException( - "Message operation is not request or response, don't know how to process: " + message - ); - } - - // UDA 1.0, 1.1.2: No body but message must have a blank line after header - StringBuilder messageData = new StringBuilder(); - messageData.append(statusLine); - - messageData.append(message.getHeaders().toString()).append("\r\n"); - - if (log.isLoggable(Level.FINER)) { - log.finer("Writing message data for: " + message); - log.finer("---------------------------------------------------------------------------------"); - log.finer(messageData.toString().substring(0, messageData.length() - 2)); // Don't print the blank lines - log.finer("---------------------------------------------------------------------------------"); - } - - try { - // According to HTTP 1.0 RFC, headers and their values are US-ASCII - // TODO: Probably should look into escaping rules, too - byte[] data = messageData.toString().getBytes("US-ASCII"); - - log.fine("Writing new datagram packet with " + data.length + " bytes for: " + message); - return new DatagramPacket(data, data.length, message.getDestinationAddress(), message.getDestinationPort()); - - } catch (UnsupportedEncodingException ex) { - throw new UnsupportedDataException( - "Can't convert message content to US-ASCII: " + ex.getMessage(), ex, messageData - ); - } - } - - protected IncomingDatagramMessage readRequestMessage(InetAddress receivedOnAddress, - DatagramPacket datagram, - ByteArrayInputStream is, - String requestMethod, - String httpProtocol) throws Exception { - - // Headers - UpnpHeaders headers = new UpnpHeaders(is); - - // Assemble message - IncomingDatagramMessage requestMessage; - UpnpRequest upnpRequest = new UpnpRequest(UpnpRequest.Method.getByHttpName(requestMethod)); - upnpRequest.setHttpMinorVersion(httpProtocol.toUpperCase(Locale.ROOT).equals("HTTP/1.1") ? 1 : 0); - requestMessage = new IncomingDatagramMessage(upnpRequest, datagram.getAddress(), datagram.getPort(), receivedOnAddress); - - requestMessage.setHeaders(headers); - - return requestMessage; - } - - protected IncomingDatagramMessage readResponseMessage(InetAddress receivedOnAddress, - DatagramPacket datagram, - ByteArrayInputStream is, - int statusCode, - String statusMessage, - String httpProtocol) throws Exception { - - // Headers - UpnpHeaders headers = new UpnpHeaders(is); - - // Assemble the message - IncomingDatagramMessage responseMessage; - UpnpResponse upnpResponse = new UpnpResponse(statusCode, statusMessage); - upnpResponse.setHttpMinorVersion(httpProtocol.toUpperCase(Locale.ROOT).equals("HTTP/1.1") ? 1 : 0); - responseMessage = new IncomingDatagramMessage(upnpResponse, datagram.getAddress(), datagram.getPort(), receivedOnAddress); - - responseMessage.setHeaders(headers); - - return responseMessage; - } - - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/FixedSunURLStreamHandler.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/FixedSunURLStreamHandler.java deleted file mode 100644 index eb9ba8e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/FixedSunURLStreamHandler.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.ProtocolException; -import java.net.Proxy; -import java.net.URL; -import java.net.URLStreamHandler; -import java.net.URLStreamHandlerFactory; -import java.util.logging.Logger; - -/** - * - * The SUNW morons restrict the JDK handlers to GET/POST/etc for "security" reasons. - *

- * They do not understand HTTP. This is the hilarious comment in their source: - *

- *

- * "This restriction will prevent people from using this class to experiment w/ new - * HTTP methods using java. But it should be placed for security - the request String - * could be arbitrarily long." - *

- * - * @author Christian Bauer - */ -public class FixedSunURLStreamHandler implements URLStreamHandlerFactory { - - final private static Logger log = Logger.getLogger(FixedSunURLStreamHandler.class.getName()); - - public URLStreamHandler createURLStreamHandler(String protocol) { - log.fine("Creating new URLStreamHandler for protocol: " + protocol); - if ("http".equals(protocol)) { - return new sun.net.www.protocol.http.Handler() { - - protected java.net.URLConnection openConnection(URL u) throws IOException { - return openConnection(u, null); - } - - protected java.net.URLConnection openConnection(URL u, Proxy p) throws IOException { - return new UpnpURLConnection(u, this); - } - }; - } else { - return null; - } - } - - static class UpnpURLConnection extends sun.net.www.protocol.http.HttpURLConnection { - - private static final String[] methods = { - "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", - "SUBSCRIBE", "UNSUBSCRIBE", "NOTIFY" - }; - - protected UpnpURLConnection(URL u, sun.net.www.protocol.http.Handler handler) throws IOException { - super(u, handler); - } - - public UpnpURLConnection(URL u, String host, int port) throws IOException { - super(u, host, port); - } - - public synchronized OutputStream getOutputStream() throws IOException { - OutputStream os; - String savedMethod = method; - // see if the method supports output - if (method.equals("PUT") || method.equals("POST") || method.equals("NOTIFY")) { - // fake the method so the superclass method sets its instance variables - method = "PUT"; - } else { - // use any method that doesn't support output, an exception will be - // raised by the superclass - method = "GET"; - } - os = super.getOutputStream(); - method = savedMethod; - return os; - } - - public void setRequestMethod(String method) throws ProtocolException { - if (connected) { - throw new ProtocolException("Cannot reset method once connected"); - } - for (String m : methods) { - if (m.equals(method)) { - this.method = method; - return; - } - } - throw new ProtocolException("Invalid UPnP HTTP method: " + method); - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/GENAEventProcessorImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/GENAEventProcessorImpl.java deleted file mode 100644 index 6ef7f35..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/GENAEventProcessorImpl.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.XMLUtil; -import org.fourthline.cling.model.message.UpnpMessage; -import org.fourthline.cling.model.message.gena.IncomingEventRequestMessage; -import org.fourthline.cling.model.message.gena.OutgoingEventRequestMessage; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.state.StateVariableValue; -import org.fourthline.cling.transport.spi.GENAEventProcessor; -import org.fourthline.cling.model.UnsupportedDataException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.FactoryConfigurationError; - -import java.io.StringReader; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Default implementation based on the W3C DOM XML processing API. - * - * @author Christian Bauer - */ -public class GENAEventProcessorImpl implements GENAEventProcessor, ErrorHandler { - - private static Logger log = Logger.getLogger(GENAEventProcessor.class.getName()); - - protected DocumentBuilderFactory createDocumentBuilderFactory() throws FactoryConfigurationError { - return DocumentBuilderFactory.newInstance(); - } - - public void writeBody(OutgoingEventRequestMessage requestMessage) throws UnsupportedDataException { - log.fine("Writing body of: " + requestMessage); - - try { - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - Document d = factory.newDocumentBuilder().newDocument(); - Element propertysetElement = writePropertysetElement(d); - - writeProperties(d, propertysetElement, requestMessage); - - requestMessage.setBody(UpnpMessage.BodyType.STRING, toString(d)); - - if (log.isLoggable(Level.FINER)) { - log.finer("===================================== GENA BODY BEGIN ============================================"); - log.finer(requestMessage.getBody().toString()); - log.finer("====================================== GENA BODY END ============================================="); - } - - } catch (Exception ex) { - throw new UnsupportedDataException("Can't transform message payload: " + ex.getMessage(), ex); - } - } - - public void readBody(IncomingEventRequestMessage requestMessage) throws UnsupportedDataException { - - log.fine("Reading body of: " + requestMessage); - if (log.isLoggable(Level.FINER)) { - log.finer("===================================== GENA BODY BEGIN ============================================"); - log.finer(requestMessage.getBody() != null ? requestMessage.getBody().toString() : "null"); - log.finer("-===================================== GENA BODY END ============================================"); - } - - String body = getMessageBody(requestMessage); - try { - - DocumentBuilderFactory factory = createDocumentBuilderFactory(); - factory.setNamespaceAware(true); - DocumentBuilder documentBuilder = factory.newDocumentBuilder(); - documentBuilder.setErrorHandler(this); - - Document d = documentBuilder.parse( - new InputSource(new StringReader(body)) - ); - - Element propertysetElement = readPropertysetElement(d); - - readProperties(propertysetElement, requestMessage); - - } catch (Exception ex) { - throw new UnsupportedDataException("Can't transform message payload: " + ex.getMessage(), ex, body); - } - } - - /* ##################################################################################################### */ - - protected Element writePropertysetElement(Document d) { - Element propertysetElement = d.createElementNS(Constants.NS_UPNP_EVENT_10, "e:propertyset"); - d.appendChild(propertysetElement); - return propertysetElement; - } - - protected Element readPropertysetElement(Document d) { - - Element propertysetElement = d.getDocumentElement(); - if (propertysetElement == null || !getUnprefixedNodeName(propertysetElement).equals("propertyset")) { - throw new RuntimeException("Root element was not 'propertyset'"); - } - return propertysetElement; - } - - /* ##################################################################################################### */ - - protected void writeProperties(Document d, Element propertysetElement, OutgoingEventRequestMessage message) { - for (StateVariableValue stateVariableValue : message.getStateVariableValues()) { - Element propertyElement = d.createElementNS(Constants.NS_UPNP_EVENT_10, "e:property"); - propertysetElement.appendChild(propertyElement); - XMLUtil.appendNewElement( - d, - propertyElement, - stateVariableValue.getStateVariable().getName(), - stateVariableValue.toString() - ); - } - } - - protected void readProperties(Element propertysetElement, IncomingEventRequestMessage message) { - NodeList propertysetElementChildren = propertysetElement.getChildNodes(); - - StateVariable[] stateVariables = message.getService().getStateVariables(); - - for (int i = 0; i < propertysetElementChildren.getLength(); i++) { - Node propertysetChild = propertysetElementChildren.item(i); - - if (propertysetChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (getUnprefixedNodeName(propertysetChild).equals("property")) { - - NodeList propertyChildren = propertysetChild.getChildNodes(); - - for (int j = 0; j < propertyChildren.getLength(); j++) { - Node propertyChild = propertyChildren.item(j); - - if (propertyChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - String stateVariableName = getUnprefixedNodeName(propertyChild); - for (StateVariable stateVariable : stateVariables) { - if (stateVariable.getName().equals(stateVariableName)) { - log.fine("Reading state variable value: " + stateVariableName); - String value = XMLUtil.getTextContent(propertyChild); - message.getStateVariableValues().add( - new StateVariableValue(stateVariable, value) - ); - break; - } - } - - } - } - } - } - - /* ##################################################################################################### */ - - protected String getMessageBody(UpnpMessage message) throws UnsupportedDataException { - if (!message.isBodyNonEmptyString()) - throw new UnsupportedDataException( - "Can't transform null or non-string/zero-length body of: " + message - ); - return message.getBodyString().trim(); - } - - protected String toString(Document d) throws Exception { - // Just to be safe, no newline at the end - String output = XMLUtil.documentToString(d); - while (output.endsWith("\n") || output.endsWith("\r")) { - output = output.substring(0, output.length() - 1); - } - - return output; - } - - protected String getUnprefixedNodeName(Node node) { - return node.getPrefix() != null - ? node.getNodeName().substring(node.getPrefix().length() + 1) - : node.getNodeName(); - } - - public void warning(SAXParseException e) throws SAXException { - log.warning(e.toString()); - } - - public void error(SAXParseException e) throws SAXException { - throw e; - } - - public void fatalError(SAXParseException e) throws SAXException { - throw e; - } -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/HttpExchangeUpnpStream.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/HttpExchangeUpnpStream.java deleted file mode 100644 index 99c65cb..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/HttpExchangeUpnpStream.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import com.sun.net.httpserver.HttpExchange; -import org.fourthline.cling.model.message.Connection; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.UpnpMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.transport.spi.UpnpStream; -import org.seamless.util.Exceptions; -import org.seamless.util.io.IO; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Default implementation based on the JDK 6.0 built-in HTTP Server. - *

- * Instantiated by a com.sun.net.httpserver.HttpHandler. - *

- * - * @author Christian Bauer - */ -public abstract class HttpExchangeUpnpStream extends UpnpStream { - - private static Logger log = Logger.getLogger(UpnpStream.class.getName()); - - private HttpExchange httpExchange; - - public HttpExchangeUpnpStream(ProtocolFactory protocolFactory, HttpExchange httpExchange) { - super(protocolFactory); - this.httpExchange = httpExchange; - } - - public HttpExchange getHttpExchange() { - return httpExchange; - } - - public void run() { - - try { - log.fine("Processing HTTP request: " + getHttpExchange().getRequestMethod() + " " + getHttpExchange().getRequestURI()); - - // Status - StreamRequestMessage requestMessage = - new StreamRequestMessage( - UpnpRequest.Method.getByHttpName(getHttpExchange().getRequestMethod()), - getHttpExchange().getRequestURI() - ); - - if (requestMessage.getOperation().getMethod().equals(UpnpRequest.Method.UNKNOWN)) { - log.fine("Method not supported by UPnP stack: " + getHttpExchange().getRequestMethod()); - throw new RuntimeException("Method not supported: " + getHttpExchange().getRequestMethod()); - } - - // Protocol - requestMessage.getOperation().setHttpMinorVersion( - getHttpExchange().getProtocol().toUpperCase(Locale.ROOT).equals("HTTP/1.1") ? 1 : 0 - ); - - log.fine("Created new request message: " + requestMessage); - - // Connection wrapper - requestMessage.setConnection(createConnection()); - - // Headers - requestMessage.setHeaders(new UpnpHeaders(getHttpExchange().getRequestHeaders())); - - // Body - byte[] bodyBytes; - InputStream is = null; - try { - is = getHttpExchange().getRequestBody(); - bodyBytes = IO.readBytes(is); - } finally { - if (is != null) - is.close(); - } - - log.fine("Reading request body bytes: " + bodyBytes.length); - - if (bodyBytes.length > 0 && requestMessage.isContentTypeMissingOrText()) { - - log.fine("Request contains textual entity body, converting then setting string on message"); - requestMessage.setBodyCharacters(bodyBytes); - - } else if (bodyBytes.length > 0) { - - log.fine("Request contains binary entity body, setting bytes on message"); - requestMessage.setBody(UpnpMessage.BodyType.BYTES, bodyBytes); - - } else { - log.fine("Request did not contain entity body"); - } - - // Process it - StreamResponseMessage responseMessage = process(requestMessage); - - // Return the response - if (responseMessage != null) { - log.fine("Preparing HTTP response message: " + responseMessage); - - // Headers - getHttpExchange().getResponseHeaders().putAll( - responseMessage.getHeaders() - ); - - // Body - byte[] responseBodyBytes = responseMessage.hasBody() ? responseMessage.getBodyBytes() : null; - int contentLength = responseBodyBytes != null ? responseBodyBytes.length : -1; - - log.fine("Sending HTTP response message: " + responseMessage + " with content length: " + contentLength); - getHttpExchange().sendResponseHeaders(responseMessage.getOperation().getStatusCode(), contentLength); - - if (contentLength > 0) { - log.fine("Response message has body, writing bytes to stream..."); - OutputStream os = null; - try { - os = getHttpExchange().getResponseBody(); - IO.writeBytes(os, responseBodyBytes); - os.flush(); - } finally { - if (os != null) - os.close(); - } - } - - } else { - // If it's null, it's 404, everything else needs a proper httpResponse - log.fine("Sending HTTP response status: " + HttpURLConnection.HTTP_NOT_FOUND); - getHttpExchange().sendResponseHeaders(HttpURLConnection.HTTP_NOT_FOUND, -1); - } - - responseSent(responseMessage); - - } catch (Throwable t) { - - // You definitely want to catch all Exceptions here, otherwise the server will - // simply close the socket and you get an "unexpected end of file" on the client. - // The same is true if you just rethrow an IOException - it is a mystery why it - // is declared then on the HttpHandler interface if it isn't handled in any - // way... so we always do error handling here. - - // TODO: We should only send an error if the problem was on our side - // You don't have to catch Throwable unless, like we do here in unit tests, - // you might run into Errors as well (assertions). - log.fine("Exception occured during UPnP stream processing: " + t); - if (log.isLoggable(Level.FINE)) { - log.log(Level.FINE, "Cause: " + Exceptions.unwrap(t), Exceptions.unwrap(t)); - } - try { - httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_INTERNAL_ERROR, -1); - } catch (IOException ex) { - log.warning("Couldn't send error response: " + ex); - } - - responseException(t); - } - } - - abstract protected Connection createConnection(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/MulticastReceiverConfigurationImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/MulticastReceiverConfigurationImpl.java deleted file mode 100644 index e7f36f7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/MulticastReceiverConfigurationImpl.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.transport.spi.MulticastReceiverConfiguration; - -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * Settings for the default implementation. - * - * @author Christian Bauer - */ -public class MulticastReceiverConfigurationImpl implements MulticastReceiverConfiguration { - - private InetAddress group; - private int port; - private int maxDatagramBytes; - - public MulticastReceiverConfigurationImpl(InetAddress group, int port, int maxDatagramBytes) { - this.group = group; - this.port = port; - this.maxDatagramBytes = maxDatagramBytes; - } - - /** - * Defaults to maximum datagram size of 640 bytes (512 per UDA 1.0, 128 byte header). - */ - public MulticastReceiverConfigurationImpl(InetAddress group, int port) { - this(group, port, 640); - } - - public MulticastReceiverConfigurationImpl(String group, int port, int maxDatagramBytes) throws UnknownHostException { - this(InetAddress.getByName(group), port, maxDatagramBytes); - } - - /** - * Defaults to maximum datagram size of 640 bytes (512 per UDA 1.0, 128 byte header). - */ - public MulticastReceiverConfigurationImpl(String group, int port) throws UnknownHostException { - this(InetAddress.getByName(group), port, 640); - } - - public InetAddress getGroup() { - return group; - } - - public void setGroup(InetAddress group) { - this.group = group; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public int getMaxDatagramBytes() { - return maxDatagramBytes; - } - - public void setMaxDatagramBytes(int maxDatagramBytes) { - this.maxDatagramBytes = maxDatagramBytes; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/MulticastReceiverImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/MulticastReceiverImpl.java deleted file mode 100644 index 4f4b1e8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/MulticastReceiverImpl.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.transport.Router; -import org.fourthline.cling.transport.spi.DatagramProcessor; -import org.fourthline.cling.transport.spi.InitializationException; -import org.fourthline.cling.transport.spi.MulticastReceiver; -import org.fourthline.cling.model.UnsupportedDataException; -import org.fourthline.cling.transport.spi.NetworkAddressFactory; - -import java.net.DatagramPacket; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MulticastSocket; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.logging.Logger; - -/** - * Default implementation based on a UDP MulticastSocket. - *

- * Thread-safety is guaranteed through synchronization of methods of this service and - * by the thread-safe underlying socket. - *

- * @author Christian Bauer - */ -public class MulticastReceiverImpl implements MulticastReceiver { - - private static Logger log = Logger.getLogger(MulticastReceiver.class.getName()); - - final protected MulticastReceiverConfigurationImpl configuration; - - protected Router router; - protected NetworkAddressFactory networkAddressFactory; - protected DatagramProcessor datagramProcessor; - - protected NetworkInterface multicastInterface; - protected InetSocketAddress multicastAddress; - protected MulticastSocket socket; - - public MulticastReceiverImpl(MulticastReceiverConfigurationImpl configuration) { - this.configuration = configuration; - } - - public MulticastReceiverConfigurationImpl getConfiguration() { - return configuration; - } - - synchronized public void init(NetworkInterface networkInterface, - Router router, - NetworkAddressFactory networkAddressFactory, - DatagramProcessor datagramProcessor) throws InitializationException { - - this.router = router; - this.networkAddressFactory = networkAddressFactory; - this.datagramProcessor = datagramProcessor; - this.multicastInterface = networkInterface; - - try { - - log.info("Creating wildcard socket (for receiving multicast datagrams) on port: " + configuration.getPort()); - multicastAddress = new InetSocketAddress(configuration.getGroup(), configuration.getPort()); - - socket = new MulticastSocket(configuration.getPort()); - socket.setReuseAddress(true); - socket.setReceiveBufferSize(32768); // Keep a backlog of incoming datagrams if we are not fast enough - - log.info("Joining multicast group: " + multicastAddress + " on network interface: " + multicastInterface.getDisplayName()); - socket.joinGroup(multicastAddress, multicastInterface); - - } catch (Exception ex) { - throw new InitializationException("Could not initialize " + getClass().getSimpleName() + ": " + ex); - } - } - - synchronized public void stop() { - if (socket != null && !socket.isClosed()) { - try { - log.fine("Leaving multicast group"); - socket.leaveGroup(multicastAddress, multicastInterface); - // Well this doesn't work and I have no idea why I get "java.net.SocketException: Can't assign requested address" - } catch (Exception ex) { - log.fine("Could not leave multicast group: " + ex); - } - // So... just close it and ignore the log messages - socket.close(); - } - } - - public void run() { - - log.fine("Entering blocking receiving loop, listening for UDP datagrams on: " + socket.getLocalAddress()); - while (true) { - - try { - byte[] buf = new byte[getConfiguration().getMaxDatagramBytes()]; - DatagramPacket datagram = new DatagramPacket(buf, buf.length); - - socket.receive(datagram); - - InetAddress receivedOnLocalAddress = - networkAddressFactory.getLocalAddress( - multicastInterface, - multicastAddress.getAddress() instanceof Inet6Address, - datagram.getAddress() - ); - - log.fine( - "UDP datagram received from: " + datagram.getAddress().getHostAddress() - + ":" + datagram.getPort() - + " on local interface: " + multicastInterface.getDisplayName() - + " and address: " + receivedOnLocalAddress.getHostAddress() - ); - - router.received(datagramProcessor.read(receivedOnLocalAddress, datagram)); - - } catch (SocketException ex) { - log.fine("Socket closed"); - break; - } catch (UnsupportedDataException ex) { - log.info("Could not read datagram: " + ex.getMessage()); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - try { - if (!socket.isClosed()) { - log.fine("Closing multicast socket"); - socket.close(); - } - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - -} - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/NetworkAddressFactoryImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/NetworkAddressFactoryImpl.java deleted file mode 100644 index 358a69a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/NetworkAddressFactoryImpl.java +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.transport.spi.InitializationException; -import org.fourthline.cling.transport.spi.NetworkAddressFactory; -import org.fourthline.cling.transport.spi.NoNetworkException; -import org.seamless.util.Iterators; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Default implementation of network interface and address configuration/discovery. - *

- * - * @author Christian Bauer - */ -public class NetworkAddressFactoryImpl implements NetworkAddressFactory { - - // Ephemeral port is the default - public static final int DEFAULT_TCP_HTTP_LISTEN_PORT = 0; - - private static Logger log = Logger.getLogger(NetworkAddressFactoryImpl.class.getName()); - - final protected Set useInterfaces = new HashSet<>(); - final protected Set useAddresses = new HashSet<>(); - - final protected List networkInterfaces = new ArrayList<>(); - final protected List bindAddresses = new ArrayList<>(); - - protected int streamListenPort; - - /** - * Defaults to an ephemeral port. - */ - public NetworkAddressFactoryImpl() throws InitializationException { - this(DEFAULT_TCP_HTTP_LISTEN_PORT); - } - - public NetworkAddressFactoryImpl(int streamListenPort) throws InitializationException { - - System.setProperty("java.net.preferIPv4Stack", "true"); - - String useInterfacesString = System.getProperty(SYSTEM_PROPERTY_NET_IFACES); - if (useInterfacesString != null) { - String[] userInterfacesStrings = useInterfacesString.split(","); - useInterfaces.addAll(Arrays.asList(userInterfacesStrings)); - } - - String useAddressesString = System.getProperty(SYSTEM_PROPERTY_NET_ADDRESSES); - if (useAddressesString != null) { - String[] useAddressesStrings = useAddressesString.split(","); - useAddresses.addAll(Arrays.asList(useAddressesStrings)); - } - - discoverNetworkInterfaces(); - discoverBindAddresses(); - - if ((networkInterfaces.size() == 0 || bindAddresses.size() == 0)) { - log.warning("No usable network interface or addresses found"); - if(requiresNetworkInterface()) { - throw new NoNetworkException( - "Could not discover any usable network interfaces and/or addresses" - ); - } - } - - this.streamListenPort = streamListenPort; - } - - /** - * @return true (the default) if a MissingNetworkInterfaceException should be thrown - */ - protected boolean requiresNetworkInterface() { - return true; - } - - public void logInterfaceInformation() { - synchronized (networkInterfaces) { - if(networkInterfaces.isEmpty()) { - log.info("No network interface to display!"); - return ; - } - for(NetworkInterface networkInterface : networkInterfaces) { - try { - logInterfaceInformation(networkInterface); - } catch (SocketException ex) { - log.log(Level.WARNING, "Exception while logging network interface information", ex); - } - } - } - } - - public InetAddress getMulticastGroup() { - try { - return InetAddress.getByName(Constants.IPV4_UPNP_MULTICAST_GROUP); - } catch (UnknownHostException ex) { - throw new RuntimeException(ex); - } - } - - public int getMulticastPort() { - return Constants.UPNP_MULTICAST_PORT; - } - - public int getStreamListenPort() { - return streamListenPort; - } - - public Iterator getNetworkInterfaces() { - return new Iterators.Synchronized(networkInterfaces) { - @Override - protected void synchronizedRemove(int index) { - synchronized (networkInterfaces) { - networkInterfaces.remove(index); - } - } - }; - } - - public Iterator getBindAddresses() { - return new Iterators.Synchronized(bindAddresses) { - @Override - protected void synchronizedRemove(int index) { - synchronized (bindAddresses) { - bindAddresses.remove(index); - } - } - }; - } - - public boolean hasUsableNetwork() { - return networkInterfaces.size() > 0 && bindAddresses.size() > 0; - } - - public byte[] getHardwareAddress(InetAddress inetAddress) { - try { - NetworkInterface iface = NetworkInterface.getByInetAddress(inetAddress); - return iface != null ? iface.getHardwareAddress() : null; - } catch (Throwable ex) { - log.log(Level.WARNING, "Cannot get hardware address for: " + inetAddress, ex); - // On Win32: java.lang.Error: IP Helper Library GetIpAddrTable function failed - - // On Android 4.0.3 NullPointerException with inetAddress != null - - // On Android "SocketException: No such device or address" when - // switching networks (mobile -> WiFi) - return null; - } - } - - public InetAddress getBroadcastAddress(InetAddress inetAddress) { - synchronized (networkInterfaces) { - for (NetworkInterface iface : networkInterfaces) { - for (InterfaceAddress interfaceAddress : getInterfaceAddresses(iface)) { - if (interfaceAddress != null && interfaceAddress.getAddress().equals(inetAddress)) { - return interfaceAddress.getBroadcast(); - } - } - } - } - return null; - } - - public Short getAddressNetworkPrefixLength(InetAddress inetAddress) { - synchronized (networkInterfaces) { - for (NetworkInterface iface : networkInterfaces) { - for (InterfaceAddress interfaceAddress : getInterfaceAddresses(iface)) { - if (interfaceAddress != null && interfaceAddress.getAddress().equals(inetAddress)) { - short prefix = interfaceAddress.getNetworkPrefixLength(); - if(prefix > 0 && prefix < 32) return prefix; // some network cards return -1 - return null; - } - } - } - } - return null; - } - - public InetAddress getLocalAddress(NetworkInterface networkInterface, boolean isIPv6, InetAddress remoteAddress) { - - // First try to find a local IP that is in the same subnet as the remote IP - InetAddress localIPInSubnet = getBindAddressInSubnetOf(remoteAddress); - if (localIPInSubnet != null) return localIPInSubnet; - - // There are two reasons why we end up here: - // - // - Windows Vista returns a 64 or 128 CIDR prefix if you ask it for the network prefix length of an IPv4 address! - // - // - We are dealing with genuine IPv6 addresses - // - // - Something is really wrong on the LAN and we received a multicast datagram from a source we can't reach via IP - log.finer("Could not find local bind address in same subnet as: " + remoteAddress.getHostAddress()); - - // Next, just take the given interface (which is really totally random) and get the first address that we like - for (InetAddress interfaceAddress: getInetAddresses(networkInterface)) { - if (isIPv6 && interfaceAddress instanceof Inet6Address) - return interfaceAddress; - if (!isIPv6 && interfaceAddress instanceof Inet4Address) - return interfaceAddress; - } - throw new IllegalStateException("Can't find any IPv4 or IPv6 address on interface: " + networkInterface.getDisplayName()); - } - - protected List getInterfaceAddresses(NetworkInterface networkInterface) { - return networkInterface.getInterfaceAddresses(); - } - - protected List getInetAddresses(NetworkInterface networkInterface) { - return Collections.list(networkInterface.getInetAddresses()); - } - - protected InetAddress getBindAddressInSubnetOf(InetAddress inetAddress) { - synchronized (networkInterfaces) { - for (NetworkInterface iface : networkInterfaces) { - for (InterfaceAddress ifaceAddress : getInterfaceAddresses(iface)) { - - synchronized (bindAddresses) { - if (ifaceAddress == null || !bindAddresses.contains(ifaceAddress.getAddress())) { - continue; - } - } - - if (isInSubnet( - inetAddress.getAddress(), - ifaceAddress.getAddress().getAddress(), - ifaceAddress.getNetworkPrefixLength()) - ) { - return ifaceAddress.getAddress(); - } - } - - } - } - return null; - } - - protected boolean isInSubnet(byte[] ip, byte[] network, short prefix) { - if (ip.length != network.length) { - return false; - } - - if (prefix / 8 > ip.length) { - return false; - } - - int i = 0; - while (prefix >= 8 && i < ip.length) { - if (ip[i] != network[i]) { - return false; - } - i++; - prefix -= 8; - } - if(i == ip.length) return true; - final byte mask = (byte) ~((1 << 8 - prefix) - 1); - - return (ip[i] & mask) == (network[i] & mask); - } - - protected void discoverNetworkInterfaces() throws InitializationException { - try { - - Enumeration interfaceEnumeration = NetworkInterface.getNetworkInterfaces(); - for (NetworkInterface iface : Collections.list(interfaceEnumeration)) { - //displayInterfaceInformation(iface); - - log.finer("Analyzing network interface: " + iface.getDisplayName()); - if (isUsableNetworkInterface(iface)) { - log.fine("Discovered usable network interface: " + iface.getDisplayName()); - synchronized (networkInterfaces) { - networkInterfaces.add(iface); - } - } else { - log.finer("Ignoring non-usable network interface: " + iface.getDisplayName()); - } - } - - } catch (Exception ex) { - throw new InitializationException("Could not not analyze local network interfaces: " + ex, ex); - } - } - - /** - * Validation of every discovered network interface. - *

- * Override this method to customize which network interfaces are used. - *

- *

- * The given implementation ignores interfaces which are - *

- *
    - *
  • loopback (yes, we do not bind to lo0)
  • - *
  • down
  • - *
  • have no bound IP addresses
  • - *
  • named "vmnet*" (OS X VMWare does not properly stop interfaces when it quits)
  • - *
  • named "vnic*" (OS X Parallels interfaces should be ignored as well)
  • - *
  • named "vboxnet*" (OS X Virtual Box interfaces should be ignored as well)
  • - *
  • named "*virtual*" (VirtualBox interfaces, for example
  • - *
  • named "ppp*"
  • - *
- * - * @param iface The interface to validate. - * @return True if the given interface matches all validation criteria. - * @throws Exception If any validation test failed with an un-recoverable error. - */ - protected boolean isUsableNetworkInterface(NetworkInterface iface) throws Exception { - if (!iface.isUp()) { - log.finer("Skipping network interface (down): " + iface.getDisplayName()); - return false; - } - - if (getInetAddresses(iface).size() == 0) { - log.finer("Skipping network interface without bound IP addresses: " + iface.getDisplayName()); - return false; - } - - if (iface.getName().toLowerCase(Locale.ROOT).startsWith("vmnet") || - (iface.getDisplayName() != null && iface.getDisplayName().toLowerCase(Locale.ROOT).contains("vmnet"))) { - log.finer("Skipping network interface (VMWare): " + iface.getDisplayName()); - return false; - } - - if (iface.getName().toLowerCase(Locale.ROOT).startsWith("vnic")) { - log.finer("Skipping network interface (Parallels): " + iface.getDisplayName()); - return false; - } - - if (iface.getName().toLowerCase(Locale.ROOT).startsWith("vboxnet")) { - log.finer("Skipping network interface (Virtual Box): " + iface.getDisplayName()); - return false; - } - - if (iface.getName().toLowerCase(Locale.ROOT).contains("virtual")) { - log.finer("Skipping network interface (named '*virtual*'): " + iface.getDisplayName()); - return false; - } - - if (iface.getName().toLowerCase(Locale.ROOT).startsWith("ppp")) { - log.finer("Skipping network interface (PPP): " + iface.getDisplayName()); - return false; - } - - if (iface.isLoopback()) { - log.finer("Skipping network interface (ignoring loopback): " + iface.getDisplayName()); - return false; - } - - if (useInterfaces.size() > 0 && !useInterfaces.contains(iface.getName())) { - log.finer("Skipping unwanted network interface (-D" + SYSTEM_PROPERTY_NET_IFACES + "): " + iface.getName()); - return false; - } - - if (!iface.supportsMulticast()) - log.warning("Network interface may not be multicast capable: " + iface.getDisplayName()); - - return true; - } - - protected void discoverBindAddresses() throws InitializationException { - try { - - synchronized (networkInterfaces) { - Iterator it = networkInterfaces.iterator(); - while (it.hasNext()) { - NetworkInterface networkInterface = it.next(); - - log.finer("Discovering addresses of interface: " + networkInterface.getDisplayName()); - int usableAddresses = 0; - for (InetAddress inetAddress : getInetAddresses(networkInterface)) { - if (inetAddress == null) { - log.warning("Network has a null address: " + networkInterface.getDisplayName()); - continue; - } - - if (isUsableAddress(networkInterface, inetAddress)) { - log.fine("Discovered usable network interface address: " + inetAddress.getHostAddress()); - usableAddresses++; - synchronized (bindAddresses) { - bindAddresses.add(inetAddress); - } - } else { - log.finer("Ignoring non-usable network interface address: " + inetAddress.getHostAddress()); - } - } - - if (usableAddresses == 0) { - log.finer("Network interface has no usable addresses, removing: " + networkInterface.getDisplayName()); - it.remove(); - } - } - } - - } catch (Exception ex) { - throw new InitializationException("Could not not analyze local network interfaces: " + ex, ex); - } - } - - /** - * Validation of every discovered local address. - *

- * Override this method to customize which network addresses are used. - *

- *

- * The given implementation ignores addresses which are - *

- *
    - *
  • not IPv4
  • - *
  • the local loopback (yes, we ignore 127.0.0.1)
  • - *
- * - * @param networkInterface The interface to validate. - * @param address The address of this interface to validate. - * @return True if the given address matches all validation criteria. - */ - protected boolean isUsableAddress(NetworkInterface networkInterface, InetAddress address) { - if (!(address instanceof Inet4Address)) { - log.finer("Skipping unsupported non-IPv4 address: " + address); - return false; - } - - if (address.isLoopbackAddress()) { - log.finer("Skipping loopback address: " + address); - return false; - } - - if (useAddresses.size() > 0 && !useAddresses.contains(address.getHostAddress())) { - log.finer("Skipping unwanted address: " + address); - return false; - } - - return true; - } - - protected void logInterfaceInformation(NetworkInterface networkInterface) throws SocketException { - log.info("---------------------------------------------------------------------------------"); - log.info(String.format("Interface display name: %s", networkInterface.getDisplayName())); - if (networkInterface.getParent() != null) - log.info(String.format("Parent Info: %s", networkInterface.getParent())); - log.info(String.format("Name: %s", networkInterface.getName())); - - Enumeration inetAddresses = networkInterface.getInetAddresses(); - - for (InetAddress inetAddress : Collections.list(inetAddresses)) { - log.info(String.format("InetAddress: %s", inetAddress)); - } - - List interfaceAddresses = networkInterface.getInterfaceAddresses(); - - for (InterfaceAddress interfaceAddress : interfaceAddresses) { - if (interfaceAddress == null) { - log.warning("Skipping null InterfaceAddress!"); - continue; - } - log.info(" Interface Address"); - log.info(" Address: " + interfaceAddress.getAddress()); - log.info(" Broadcast: " + interfaceAddress.getBroadcast()); - log.info(" Prefix length: " + interfaceAddress.getNetworkPrefixLength()); - } - - Enumeration subIfs = networkInterface.getSubInterfaces(); - - for (NetworkInterface subIf : Collections.list(subIfs)) { - if (subIf == null) { - log.warning("Skipping null NetworkInterface sub-interface"); - continue; - } - log.info(String.format("\tSub Interface Display name: %s", subIf.getDisplayName())); - log.info(String.format("\tSub Interface Name: %s", subIf.getName())); - } - log.info(String.format("Up? %s", networkInterface.isUp())); - log.info(String.format("Loopback? %s", networkInterface.isLoopback())); - log.info(String.format("PointToPoint? %s", networkInterface.isPointToPoint())); - log.info(String.format("Supports multicast? %s", networkInterface.supportsMulticast())); - log.info(String.format("Virtual? %s", networkInterface.isVirtual())); - log.info(String.format("Hardware address: %s", Arrays.toString(networkInterface.getHardwareAddress()))); - log.info(String.format("MTU: %s", networkInterface.getMTU())); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/PullGENAEventProcessorImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/PullGENAEventProcessorImpl.java deleted file mode 100644 index 845e610..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/PullGENAEventProcessorImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.fourthline.cling.model.message.gena.IncomingEventRequestMessage; -import org.fourthline.cling.model.meta.StateVariable; -import org.fourthline.cling.model.state.StateVariableValue; -import org.fourthline.cling.transport.spi.GENAEventProcessor; -import org.fourthline.cling.model.UnsupportedDataException; -import org.seamless.xml.XmlPullParserUtils; -import org.xmlpull.v1.XmlPullParser; - -import javax.enterprise.inject.Alternative; - -/** - * Implementation based on the Xml Pull Parser XML processing API. - *

- * This processor is more lenient with parsing, looking only for the required XML tags. - *

- *

- * To use this parser you need to install an implementation of the - * XMLPull API. - *

- * - * @author Michael Pujos - */ -@Alternative -public class PullGENAEventProcessorImpl extends GENAEventProcessorImpl { - - private static Logger log = Logger.getLogger(GENAEventProcessor.class.getName()); - - public void readBody(IncomingEventRequestMessage requestMessage) throws UnsupportedDataException { - log.fine("Reading body of: " + requestMessage); - if (log.isLoggable(Level.FINER)) { - log.finer("===================================== GENA BODY BEGIN ============================================"); - log.finer(requestMessage.getBody() != null ? requestMessage.getBody().toString() : null); - log.finer("-===================================== GENA BODY END ============================================"); - } - - String body = getMessageBody(requestMessage); - try { - XmlPullParser xpp = XmlPullParserUtils.createParser(body); - readProperties(xpp, requestMessage); - } catch (Exception ex) { - throw new UnsupportedDataException("Can't transform message payload: " + ex.getMessage(), ex, body); - } - } - - protected void readProperties(XmlPullParser xpp, IncomingEventRequestMessage message) throws Exception { - // We're inside the propertyset tag - StateVariable[] stateVariables = message.getService().getStateVariables(); - int event; - while((event = xpp.next()) != XmlPullParser.END_DOCUMENT) { - if(event != XmlPullParser.START_TAG) continue; - if(xpp.getName().equals("property")) { - readProperty(xpp, message, stateVariables); - } - } - } - - protected void readProperty(XmlPullParser xpp, IncomingEventRequestMessage message, StateVariable[] stateVariables) throws Exception { - // We're inside the property tag - int event ; - do { - event = xpp.next(); - if(event == XmlPullParser.START_TAG) { - - String stateVariableName = xpp.getName(); - for (StateVariable stateVariable : stateVariables) { - if (stateVariable.getName().equals(stateVariableName)) { - log.fine("Reading state variable value: " + stateVariableName); - String value = xpp.nextText(); - message.getStateVariableValues().add(new StateVariableValue(stateVariable, value)); - break; - } - } - } - } while(event != XmlPullParser.END_DOCUMENT && (event != XmlPullParser.END_TAG || !xpp.getName().equals("property"))); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/PullSOAPActionProcessorImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/PullSOAPActionProcessorImpl.java deleted file mode 100644 index 419f5db..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/PullSOAPActionProcessorImpl.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import java.util.*; -import java.util.logging.Logger; - -import org.fourthline.cling.model.action.ActionArgumentValue; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.message.control.ActionRequestMessage; -import org.fourthline.cling.model.message.control.ActionResponseMessage; -import org.fourthline.cling.model.meta.ActionArgument; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.transport.spi.SOAPActionProcessor; -import org.fourthline.cling.model.UnsupportedDataException; -import org.seamless.xml.XmlPullParserUtils; -import org.xmlpull.v1.XmlPullParser; - -import javax.enterprise.inject.Alternative; - -/** - * Implementation based on the Xml Pull Parser XML processing API. - *

- * This processor is more lenient with parsing, looking only for the required XML tags. - *

- *

- * To use this parser you need to install an implementation of the - * XMLPull API. - *

- * - * @author Michael Pujos - */ -@Alternative -public class PullSOAPActionProcessorImpl extends SOAPActionProcessorImpl { - - protected static Logger log = Logger.getLogger(SOAPActionProcessor.class.getName()); - - public void readBody(ActionRequestMessage requestMessage, ActionInvocation actionInvocation) throws UnsupportedDataException { - String body = getMessageBody(requestMessage); - try { - XmlPullParser xpp = XmlPullParserUtils.createParser(body); - readBodyRequest(xpp, requestMessage, actionInvocation); - } catch (Exception ex) { - throw new UnsupportedDataException("Can't transform message payload: " + ex, ex, body); - } - } - - public void readBody(ActionResponseMessage responseMsg, ActionInvocation actionInvocation) throws UnsupportedDataException { - String body = getMessageBody(responseMsg); - try { - XmlPullParser xpp = XmlPullParserUtils.createParser(body); - readBodyElement(xpp); - readBodyResponse(xpp, actionInvocation); - } catch (Exception ex) { - throw new UnsupportedDataException("Can't transform message payload: " + ex, ex, body); - } - } - - protected void readBodyElement(XmlPullParser xpp) throws Exception { - XmlPullParserUtils.searchTag(xpp, "Body"); - } - - protected void readBodyRequest(XmlPullParser xpp, ActionRequestMessage requestMessage, ActionInvocation actionInvocation) throws Exception { - XmlPullParserUtils.searchTag(xpp, actionInvocation.getAction().getName()); - readActionInputArguments(xpp, actionInvocation); - } - - protected void readBodyResponse(XmlPullParser xpp, ActionInvocation actionInvocation) throws Exception { - // We're in the "Body" tag - int event; - do { - event = xpp.next(); - if (event == XmlPullParser.START_TAG) { - if (xpp.getName().equals("Fault")) { - ActionException e = readFaultElement(xpp); - actionInvocation.setFailure(e); - return; - } else if (xpp.getName().equals(actionInvocation.getAction().getName() + "Response")) { - readActionOutputArguments(xpp, actionInvocation); - return; - } - } - - } - while (event != XmlPullParser.END_DOCUMENT && (event != XmlPullParser.END_TAG || !xpp.getName().equals("Body"))); - - throw new ActionException( - ErrorCode.ACTION_FAILED, - String.format("Action SOAP response do not contain %s element", - actionInvocation.getAction().getName() + "Response" - ) - ); - } - - protected void readActionInputArguments(XmlPullParser xpp, ActionInvocation actionInvocation) throws Exception { - actionInvocation.setInput(readArgumentValues(xpp, actionInvocation.getAction().getInputArguments())); - } - - protected void readActionOutputArguments(XmlPullParser xpp, ActionInvocation actionInvocation) throws Exception { - actionInvocation.setOutput(readArgumentValues(xpp, actionInvocation.getAction().getOutputArguments())); - } - - protected Map getMatchingNodes(XmlPullParser xpp, ActionArgument[] args) throws Exception { - - // This is a case-insensitive search! - List names = new ArrayList<>(); - for (ActionArgument argument : args) { - names.add(argument.getName().toUpperCase(Locale.ROOT)); - for (String alias : Arrays.asList(argument.getAliases())) { - names.add(alias.toUpperCase(Locale.ROOT)); - } - } - - Map matches = new HashMap<>(); - - String enclosingTag = xpp.getName(); - - int event; - do { - event = xpp.next(); - if(event == XmlPullParser.START_TAG && names.contains(xpp.getName().toUpperCase(Locale.ROOT))) { - matches.put(xpp.getName(), xpp.nextText()); - } - - } - while (event != XmlPullParser.END_DOCUMENT && (event != XmlPullParser.END_TAG || !xpp.getName().equals(enclosingTag))); - - if (matches.size() < args.length) { - throw new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, - "Invalid number of input or output arguments in XML message, expected " - + args.length + " but found " + matches.size() - ); - } - return matches; - } - - protected ActionArgumentValue[] readArgumentValues(XmlPullParser xpp, ActionArgument[] args) throws Exception { - // We're in the Response tag - Map matches = getMatchingNodes(xpp, args); - - ActionArgumentValue[] values = new ActionArgumentValue[args.length]; - - for (int i = 0; i < args.length; i++) { - - ActionArgument arg = args[i]; - String value = findActionArgumentValue(matches, arg); - if (value == null) { - throw new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, - "Could not find argument '" + arg.getName() + "' node"); - } - - log.fine("Reading action argument: " + arg.getName()); - values[i] = createValue(arg, value); - } - return values; - } - - protected String findActionArgumentValue(Map entries, ActionArgument arg) { - for (Map.Entry entry : entries.entrySet()) { - if (arg.isNameOrAlias(entry.getKey())) return entry.getValue(); - } - return null; - } - - protected ActionException readFaultElement(XmlPullParser xpp) throws Exception { - // We're in the "Fault" tag - - String errorCode = null; - String errorDescription = null; - - XmlPullParserUtils.searchTag(xpp, "UPnPError"); - - int event; - do { - event = xpp.next(); - if (event == XmlPullParser.START_TAG) { - String tag = xpp.getName(); - if (tag.equals("errorCode")) { - errorCode = xpp.nextText(); - } else if (tag.equals("errorDescription")) { - errorDescription = xpp.nextText(); - } - } - } - while (event != XmlPullParser.END_DOCUMENT && (event != XmlPullParser.END_TAG || !xpp.getName().equals("UPnPError"))); - - if (errorCode != null) { - try { - int numericCode = Integer.valueOf(errorCode); - ErrorCode standardErrorCode = ErrorCode.getByCode(numericCode); - if (standardErrorCode != null) { - log.fine("Reading fault element: " + standardErrorCode.getCode() + " - " + errorDescription); - return new ActionException(standardErrorCode, errorDescription, false); - } else { - log.fine("Reading fault element: " + numericCode + " - " + errorDescription); - return new ActionException(numericCode, errorDescription); - } - } catch (NumberFormatException ex) { - throw new RuntimeException("Error code was not a number"); - } - } - - throw new RuntimeException("Received fault element but no error code"); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/RecoveringGENAEventProcessorImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/RecoveringGENAEventProcessorImpl.java deleted file mode 100644 index 1697c7a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/RecoveringGENAEventProcessorImpl.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.model.UnsupportedDataException; -import org.fourthline.cling.model.XMLUtil; -import org.fourthline.cling.model.message.gena.IncomingEventRequestMessage; -import org.fourthline.cling.transport.spi.GENAEventProcessor; -import org.seamless.xml.XmlPullParserUtils; - -import javax.enterprise.inject.Alternative; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -/** - * Implementation based on the Xml Pull Parser XML processing API. - *

- * This processor extends {@link PullGENAEventProcessorImpl}, it will always - * first try to read messages regularly with the superclass' methods before - * trying to recover from a failure. - *

- *

- * When the superclass can't read the message, this processor will try to - * recover from broken XML by for example, detecting wrongly encoded XML entities, - * and working around other vendor-specific bugs caused by incompatible UPnP - * stacks in the wild. - *

- *

- * This processor will also return partial results, if at least a single - * state variable value could be recovered from the (broken) event XML. - *

- * - * @author Michael Pujos - */ -@Alternative -public class RecoveringGENAEventProcessorImpl extends PullGENAEventProcessorImpl { - - private static Logger log = Logger.getLogger(GENAEventProcessor.class.getName()); - - public void readBody(IncomingEventRequestMessage requestMessage) throws UnsupportedDataException { - try { - super.readBody(requestMessage); - } catch (UnsupportedDataException ex) { - - // Can't recover from this - if (!requestMessage.isBodyNonEmptyString()) - throw ex; - - log.warning("Trying to recover from invalid GENA XML event: " + ex); - - // Some properties may have been read at this point, so reset the list - requestMessage.getStateVariableValues().clear(); - - String body = getMessageBody(requestMessage); - - String fixedBody = fixXMLEncodedLastChange( - XmlPullParserUtils.fixXMLEntities(body) - ); - - try { - // Try again, if this fails, we are done... - requestMessage.setBody(fixedBody); - super.readBody(requestMessage); - } catch (UnsupportedDataException ex2) { - // Check if some properties were read - if (requestMessage.getStateVariableValues().isEmpty()) { - // Throw the initial exception containing unmodified XML - throw ex; - } - log.warning("Partial read of GENA event properties (probably due to truncated XML)"); - } - } - } - - protected String fixXMLEncodedLastChange(String xml) { - Pattern pattern = Pattern.compile("(.*)", Pattern.DOTALL); - Matcher matcher = pattern.matcher(xml); - - if (matcher.find() && matcher.groupCount() == 1) { - - String lastChange = matcher.group(1); - - if (XmlPullParserUtils.isNullOrEmpty(lastChange)) - return xml; - - lastChange = lastChange.trim(); - - String fixedLastChange = lastChange; - - if (lastChange.charAt(0) == '<') { - // TODO: UPNP VIOLATION: Orange Liveradio does not encode LastChange XML properly - fixedLastChange = XMLUtil.encodeText(fixedLastChange); - } else { - /* Doesn't work for Philips NP2900, there is complete garbage after the HTML - // TODO: UPNP VIOLATION: Philips NP2900 inserts garbage HTML, try to fix it - fixedLastChange = fixedLastChange.replaceAll("<", ""); - fixedLastChange = fixedLastChange.replaceAll(">", ""); - */ - } - - if (fixedLastChange.equals(lastChange)) { - return xml; - } - - return "" + - "" + - "" + - "" + - fixedLastChange + - "" + - "" + - ""; - } - return xml; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/RecoveringSOAPActionProcessorImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/RecoveringSOAPActionProcessorImpl.java deleted file mode 100644 index 3914cea..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/RecoveringSOAPActionProcessorImpl.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import java.util.logging.Logger; - -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.message.control.ActionRequestMessage; -import org.fourthline.cling.model.message.control.ActionResponseMessage; -import org.fourthline.cling.transport.spi.SOAPActionProcessor; -import org.fourthline.cling.model.UnsupportedDataException; -import org.seamless.xml.XmlPullParserUtils; - -import javax.enterprise.inject.Alternative; - -/** - * Implementation based on the Xml Pull Parser XML processing API. - *

- * This processor extends {@link PullSOAPActionProcessorImpl}, it will always - * first try to read messages regularly with the superclass' methods before - * trying to recover from a failure. - *

- *

- * When the superclass can't read the message, this processor will try to - * recover from broken XML by for example, detecting wrongly encoded XML entities, - * and working around other vendor-specific bugs caused by incompatible UPnP - * stacks in the wild. - *

- *

- * Additionally any {@link UnsupportedDataException} thrown while reading an - * XML message will be passed on to the - * {@link #handleInvalidMessage(org.fourthline.cling.model.action.ActionInvocation, org.fourthline.cling.model.UnsupportedDataException, org.fourthline.cling.model.UnsupportedDataException)} - * method for you to handle. The default implementation will simply throw the - * original exception from the first processing attempt. - *

- * - * @author Michael Pujos - */ -@Alternative -public class RecoveringSOAPActionProcessorImpl extends PullSOAPActionProcessorImpl { - - private static Logger log = Logger.getLogger(SOAPActionProcessor.class.getName()); - - public void readBody(ActionRequestMessage requestMessage, ActionInvocation actionInvocation) throws UnsupportedDataException { - try { - super.readBody(requestMessage, actionInvocation); - } catch (UnsupportedDataException ex) { - - // Can't recover from this - if (!requestMessage.isBodyNonEmptyString()) - throw ex; - - log.warning("Trying to recover from invalid SOAP XML request: " + ex); - String body = getMessageBody(requestMessage); - - // TODO: UPNP VIOLATION: TwonkyMobile sends unencoded '&' in SetAVTransportURI action calls: - // http://192.168.1.14:56923/content/12a470d854dbc6887e4103e3140783fd.wav?profile_id=0&convert=wav - String fixedBody = XmlPullParserUtils.fixXMLEntities(body); - - try { - // Try again, if this fails, we are done... - requestMessage.setBody(fixedBody); - super.readBody(requestMessage, actionInvocation); - } catch (UnsupportedDataException ex2) { - handleInvalidMessage(actionInvocation, ex, ex2); - } - } - } - - public void readBody(ActionResponseMessage responseMsg, ActionInvocation actionInvocation) throws UnsupportedDataException { - try { - super.readBody(responseMsg, actionInvocation); - } catch (UnsupportedDataException ex) { - - // Can't recover from this - if (!responseMsg.isBodyNonEmptyString()) - throw ex; - - log.warning("Trying to recover from invalid SOAP XML response: " + ex); - String body = getMessageBody(responseMsg); - - // TODO: UPNP VIOLATION: TwonkyMobile doesn't properly encode '&' - String fixedBody = XmlPullParserUtils.fixXMLEntities(body); - - // TODO: UPNP VIOLATION: YAMAHA NP-S2000 does not terminate XML with - // (at least for action GetPositionInfo) - if (fixedBody.endsWith(" - * Typically you want to log this problem or create an error report, and in any - * case, throw an {@link UnsupportedDataException} to notify the caller of the - * processor of this failure. - *

- *

- * You can access the invalid XML with - * {@link org.fourthline.cling.model.UnsupportedDataException#getData()}. - *

- * - * @param originalException The original exception throw by the first parsing attempt - * @param recoveringException The exception thrown after trying to fix the XML. - */ - protected void handleInvalidMessage(ActionInvocation actionInvocation, - UnsupportedDataException originalException, - UnsupportedDataException recoveringException) throws UnsupportedDataException { - throw originalException; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/SOAPActionProcessorImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/SOAPActionProcessorImpl.java deleted file mode 100644 index 3935f91..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/SOAPActionProcessorImpl.java +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.model.Constants; -import org.fourthline.cling.model.XMLUtil; -import org.fourthline.cling.model.action.ActionArgumentValue; -import org.fourthline.cling.model.action.ActionException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.message.control.ActionMessage; -import org.fourthline.cling.model.message.control.ActionRequestMessage; -import org.fourthline.cling.model.message.control.ActionResponseMessage; -import org.fourthline.cling.model.meta.ActionArgument; -import org.fourthline.cling.model.types.ErrorCode; -import org.fourthline.cling.model.types.InvalidValueException; -import org.fourthline.cling.transport.spi.SOAPActionProcessor; -import org.fourthline.cling.model.UnsupportedDataException; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.FactoryConfigurationError; - -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Default implementation based on the W3C DOM XML processing API. - * - * @author Christian Bauer - */ -public class SOAPActionProcessorImpl implements SOAPActionProcessor, ErrorHandler { - - private static Logger log = Logger.getLogger(SOAPActionProcessor.class.getName()); - - protected DocumentBuilderFactory createDocumentBuilderFactory() throws FactoryConfigurationError { - return DocumentBuilderFactory.newInstance(); - } - - public void writeBody(ActionRequestMessage requestMessage, ActionInvocation actionInvocation) throws UnsupportedDataException { - - log.fine("Writing body of " + requestMessage + " for: " + actionInvocation); - - try { - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - Document d = factory.newDocumentBuilder().newDocument(); - Element body = writeBodyElement(d); - - writeBodyRequest(d, body, requestMessage, actionInvocation); - - if (log.isLoggable(Level.FINER)) { - log.finer("===================================== SOAP BODY BEGIN ============================================"); - log.finer(requestMessage.getBodyString()); - log.finer("-===================================== SOAP BODY END ============================================"); - } - - } catch (Exception ex) { - throw new UnsupportedDataException("Can't transform message payload: " + ex, ex); - } - } - - public void writeBody(ActionResponseMessage responseMessage, ActionInvocation actionInvocation) throws UnsupportedDataException { - - log.fine("Writing body of " + responseMessage + " for: " + actionInvocation); - - try { - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - Document d = factory.newDocumentBuilder().newDocument(); - Element body = writeBodyElement(d); - - if (actionInvocation.getFailure() != null) { - writeBodyFailure(d, body, responseMessage, actionInvocation); - } else { - writeBodyResponse(d, body, responseMessage, actionInvocation); - } - - if (log.isLoggable(Level.FINER)) { - log.finer("===================================== SOAP BODY BEGIN ============================================"); - log.finer(responseMessage.getBodyString()); - log.finer("-===================================== SOAP BODY END ============================================"); - } - - } catch (Exception ex) { - throw new UnsupportedDataException("Can't transform message payload: " + ex, ex); - } - } - - public void readBody(ActionRequestMessage requestMessage, ActionInvocation actionInvocation) throws UnsupportedDataException { - - log.fine("Reading body of " + requestMessage + " for: " + actionInvocation); - if (log.isLoggable(Level.FINER)) { - log.finer("===================================== SOAP BODY BEGIN ============================================"); - log.finer(requestMessage.getBodyString()); - log.finer("-===================================== SOAP BODY END ============================================"); - } - - String body = getMessageBody(requestMessage); - try { - - DocumentBuilderFactory factory = createDocumentBuilderFactory(); - factory.setNamespaceAware(true); - DocumentBuilder documentBuilder = factory.newDocumentBuilder(); - documentBuilder.setErrorHandler(this); - - Document d = documentBuilder.parse(new InputSource(new StringReader(body))); - - Element bodyElement = readBodyElement(d); - - readBodyRequest(d, bodyElement, requestMessage, actionInvocation); - - } catch (Exception ex) { - throw new UnsupportedDataException("Can't transform message payload: " + ex, ex, body); - } - } - - public void readBody(ActionResponseMessage responseMsg, ActionInvocation actionInvocation) throws UnsupportedDataException { - - log.fine("Reading body of " + responseMsg + " for: " + actionInvocation); - if (log.isLoggable(Level.FINER)) { - log.finer("===================================== SOAP BODY BEGIN ============================================"); - log.finer(responseMsg.getBodyString()); - log.finer("-===================================== SOAP BODY END ============================================"); - } - - String body = getMessageBody(responseMsg); - try { - - DocumentBuilderFactory factory = createDocumentBuilderFactory(); - factory.setNamespaceAware(true); - DocumentBuilder documentBuilder = factory.newDocumentBuilder(); - documentBuilder.setErrorHandler(this); - - Document d = documentBuilder.parse(new InputSource(new StringReader(body))); - - Element bodyElement = readBodyElement(d); - - ActionException failure = readBodyFailure(d, bodyElement); - - if (failure == null) { - readBodyResponse(d, bodyElement, responseMsg, actionInvocation); - } else { - actionInvocation.setFailure(failure); - } - - } catch (Exception ex) { - throw new UnsupportedDataException("Can't transform message payload: " + ex, ex, body); - } - } - - /* ##################################################################################################### */ - - protected void writeBodyFailure(Document d, - Element bodyElement, - ActionResponseMessage message, - ActionInvocation actionInvocation) throws Exception { - - writeFaultElement(d, bodyElement, actionInvocation); - message.setBody(toString(d)); - } - - protected void writeBodyRequest(Document d, - Element bodyElement, - ActionRequestMessage message, - ActionInvocation actionInvocation) throws Exception { - - Element actionRequestElement = writeActionRequestElement(d, bodyElement, message, actionInvocation); - writeActionInputArguments(d, actionRequestElement, actionInvocation); - message.setBody(toString(d)); - - } - - protected void writeBodyResponse(Document d, - Element bodyElement, - ActionResponseMessage message, - ActionInvocation actionInvocation) throws Exception { - - Element actionResponseElement = writeActionResponseElement(d, bodyElement, message, actionInvocation); - writeActionOutputArguments(d, actionResponseElement, actionInvocation); - message.setBody(toString(d)); - } - - protected ActionException readBodyFailure(Document d, Element bodyElement) throws Exception { - return readFaultElement(bodyElement); - } - - protected void readBodyRequest(Document d, - Element bodyElement, - ActionRequestMessage message, - ActionInvocation actionInvocation) throws Exception { - - Element actionRequestElement = readActionRequestElement(bodyElement, message, actionInvocation); - readActionInputArguments(actionRequestElement, actionInvocation); - } - - protected void readBodyResponse(Document d, - Element bodyElement, - ActionResponseMessage message, - ActionInvocation actionInvocation) throws Exception { - - Element actionResponse = readActionResponseElement(bodyElement, actionInvocation); - readActionOutputArguments(actionResponse, actionInvocation); - } - - /* ##################################################################################################### */ - - protected Element writeBodyElement(Document d) { - - Element envelopeElement = d.createElementNS(Constants.SOAP_NS_ENVELOPE, "s:Envelope"); - Attr encodingStyleAttr = d.createAttributeNS(Constants.SOAP_NS_ENVELOPE, "s:encodingStyle"); - encodingStyleAttr.setValue(Constants.SOAP_URI_ENCODING_STYLE); - envelopeElement.setAttributeNode(encodingStyleAttr); - d.appendChild(envelopeElement); - - Element bodyElement = d.createElementNS(Constants.SOAP_NS_ENVELOPE, "s:Body"); - envelopeElement.appendChild(bodyElement); - - return bodyElement; - } - - protected Element readBodyElement(Document d) { - - Element envelopeElement = d.getDocumentElement(); - - if (envelopeElement == null || !getUnprefixedNodeName(envelopeElement).equals("Envelope")) { - throw new RuntimeException("Response root element was not 'Envelope'"); - } - - NodeList envelopeElementChildren = envelopeElement.getChildNodes(); - for (int i = 0; i < envelopeElementChildren.getLength(); i++) { - Node envelopeChild = envelopeElementChildren.item(i); - - if (envelopeChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (getUnprefixedNodeName(envelopeChild).equals("Body")) { - return (Element) envelopeChild; - } - } - - throw new RuntimeException("Response envelope did not contain 'Body' child element"); - } - - /* ##################################################################################################### */ - - protected Element writeActionRequestElement(Document d, - Element bodyElement, - ActionRequestMessage message, - ActionInvocation actionInvocation) { - - log.fine("Writing action request element: " + actionInvocation.getAction().getName()); - - Element actionRequestElement = d.createElementNS( - message.getActionNamespace(), - "u:" + actionInvocation.getAction().getName() - ); - bodyElement.appendChild(actionRequestElement); - - return actionRequestElement; - } - - protected Element readActionRequestElement(Element bodyElement, - ActionRequestMessage message, - ActionInvocation actionInvocation) { - NodeList bodyChildren = bodyElement.getChildNodes(); - - log.fine("Looking for action request element matching namespace:" + message.getActionNamespace()); - - for (int i = 0; i < bodyChildren.getLength(); i++) { - Node bodyChild = bodyChildren.item(i); - - if (bodyChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - String unprefixedName = getUnprefixedNodeName(bodyChild); - if (unprefixedName.equals(actionInvocation.getAction().getName())) { - if (bodyChild.getNamespaceURI() == null - || !bodyChild.getNamespaceURI().equals(message.getActionNamespace())) - throw new UnsupportedDataException( - "Illegal or missing namespace on action request element: " + bodyChild - ); - log.fine("Reading action request element: " + unprefixedName); - return (Element) bodyChild; - } - } - throw new UnsupportedDataException( - "Could not read action request element matching namespace: " + message.getActionNamespace() - ); - } - - /* ##################################################################################################### */ - - protected Element writeActionResponseElement(Document d, - Element bodyElement, - ActionResponseMessage message, - ActionInvocation actionInvocation) { - - log.fine("Writing action response element: " + actionInvocation.getAction().getName()); - Element actionResponseElement = d.createElementNS( - message.getActionNamespace(), - "u:" + actionInvocation.getAction().getName() + "Response" - ); - bodyElement.appendChild(actionResponseElement); - - return actionResponseElement; - } - - protected Element readActionResponseElement(Element bodyElement, ActionInvocation actionInvocation) { - NodeList bodyChildren = bodyElement.getChildNodes(); - - for (int i = 0; i < bodyChildren.getLength(); i++) { - Node bodyChild = bodyChildren.item(i); - - if (bodyChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (getUnprefixedNodeName(bodyChild).equals(actionInvocation.getAction().getName() + "Response")) { - log.fine("Reading action response element: " + getUnprefixedNodeName(bodyChild)); - return (Element) bodyChild; - } - } - log.fine("Could not read action response element"); - return null; - } - - /* ##################################################################################################### */ - - protected void writeActionInputArguments(Document d, - Element actionRequestElement, - ActionInvocation actionInvocation) { - - for (ActionArgument argument : actionInvocation.getAction().getInputArguments()) { - log.fine("Writing action input argument: " + argument.getName()); - String value = actionInvocation.getInput(argument) != null ? actionInvocation.getInput(argument).toString() : ""; - XMLUtil.appendNewElement(d, actionRequestElement, argument.getName(), value); - } - } - - public void readActionInputArguments(Element actionRequestElement, - ActionInvocation actionInvocation) throws ActionException { - actionInvocation.setInput( - readArgumentValues( - actionRequestElement.getChildNodes(), - actionInvocation.getAction().getInputArguments() - ) - ); - } - - /* ##################################################################################################### */ - - protected void writeActionOutputArguments(Document d, - Element actionResponseElement, - ActionInvocation actionInvocation) { - - for (ActionArgument argument : actionInvocation.getAction().getOutputArguments()) { - log.fine("Writing action output argument: " + argument.getName()); - String value = actionInvocation.getOutput(argument) != null ? actionInvocation.getOutput(argument).toString() : ""; - XMLUtil.appendNewElement(d, actionResponseElement, argument.getName(), value); - } - } - - protected void readActionOutputArguments(Element actionResponseElement, - ActionInvocation actionInvocation) throws ActionException { - - actionInvocation.setOutput( - readArgumentValues( - actionResponseElement.getChildNodes(), - actionInvocation.getAction().getOutputArguments() - ) - ); - } - - /* ##################################################################################################### */ - - protected void writeFaultElement(Document d, Element bodyElement, ActionInvocation actionInvocation) { - - Element faultElement = d.createElementNS(Constants.SOAP_NS_ENVELOPE, "s:Fault"); - bodyElement.appendChild(faultElement); - - // This stuff is really completely arbitrary nonsense... let's hope they fired the guy who decided this - XMLUtil.appendNewElement(d, faultElement, "faultcode", "s:Client"); - XMLUtil.appendNewElement(d, faultElement, "faultstring", "UPnPError"); - - Element detailElement = d.createElement("detail"); - faultElement.appendChild(detailElement); - - Element upnpErrorElement = d.createElementNS(Constants.NS_UPNP_CONTROL_10, "UPnPError"); - detailElement.appendChild(upnpErrorElement); - - int errorCode = actionInvocation.getFailure().getErrorCode(); - String errorDescription = actionInvocation.getFailure().getMessage(); - - log.fine("Writing fault element: " + errorCode + " - " + errorDescription); - - XMLUtil.appendNewElement(d, upnpErrorElement, "errorCode", Integer.toString(errorCode)); - XMLUtil.appendNewElement(d, upnpErrorElement, "errorDescription", errorDescription); - - } - - protected ActionException readFaultElement(Element bodyElement) { - - boolean receivedFaultElement = false; - String errorCode = null; - String errorDescription = null; - - NodeList bodyChildren = bodyElement.getChildNodes(); - - for (int i = 0; i < bodyChildren.getLength(); i++) { - Node bodyChild = bodyChildren.item(i); - - if (bodyChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (getUnprefixedNodeName(bodyChild).equals("Fault")) { - - receivedFaultElement = true; - - NodeList faultChildren = bodyChild.getChildNodes(); - - for (int j = 0; j < faultChildren.getLength(); j++) { - Node faultChild = faultChildren.item(j); - - if (faultChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (getUnprefixedNodeName(faultChild).equals("detail")) { - - NodeList detailChildren = faultChild.getChildNodes(); - for (int x = 0; x < detailChildren.getLength(); x++) { - Node detailChild = detailChildren.item(x); - - if (detailChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (getUnprefixedNodeName(detailChild).equals("UPnPError")) { - - NodeList errorChildren = detailChild.getChildNodes(); - for (int y = 0; y < errorChildren.getLength(); y++) { - Node errorChild = errorChildren.item(y); - - if (errorChild.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (getUnprefixedNodeName(errorChild).equals("errorCode")) - errorCode = XMLUtil.getTextContent(errorChild); - - if (getUnprefixedNodeName(errorChild).equals("errorDescription")) - errorDescription = XMLUtil.getTextContent(errorChild); - } - } - } - } - } - } - } - - if (errorCode != null) { - try { - int numericCode = Integer.valueOf(errorCode); - ErrorCode standardErrorCode = ErrorCode.getByCode(numericCode); - if (standardErrorCode != null) { - log.fine("Reading fault element: " + standardErrorCode.getCode() + " - " + errorDescription); - return new ActionException(standardErrorCode, errorDescription, false); - } else { - log.fine("Reading fault element: " + numericCode + " - " + errorDescription); - return new ActionException(numericCode, errorDescription); - } - } catch (NumberFormatException ex) { - throw new RuntimeException("Error code was not a number"); - } - } else if (receivedFaultElement) { - throw new RuntimeException("Received fault element but no error code"); - } - return null; - } - - - /* ##################################################################################################### */ - - protected String getMessageBody(ActionMessage message) throws UnsupportedDataException { - if (!message.isBodyNonEmptyString()) - throw new UnsupportedDataException( - "Can't transform null or non-string/zero-length body of: " + message - ); - return message.getBodyString().trim(); - } - - protected String toString(Document d) throws Exception { - // Just to be safe, no newline at the end - String output = XMLUtil.documentToString(d); - while (output.endsWith("\n") || output.endsWith("\r")) { - output = output.substring(0, output.length() - 1); - } - - return output; - } - - protected String getUnprefixedNodeName(Node node) { - return node.getPrefix() != null - ? node.getNodeName().substring(node.getPrefix().length() + 1) - : node.getNodeName(); - } - - /** - * The UPnP spec says that action arguments must be in the order as declared - * by the service. This method however is lenient, the action argument nodes - * in the XML can be in any order, as long as they are all there everything - * is OK. - */ - protected ActionArgumentValue[] readArgumentValues(NodeList nodeList, ActionArgument[] args) - throws ActionException { - - List nodes = getMatchingNodes(nodeList, args); - - ActionArgumentValue[] values = new ActionArgumentValue[args.length]; - - for (int i = 0; i < args.length; i++) { - - ActionArgument arg = args[i]; - Node node = findActionArgumentNode(nodes, arg); - if(node == null) { - throw new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, - "Could not find argument '" + arg.getName() + "' node"); - } - log.fine("Reading action argument: " + arg.getName()); - String value = XMLUtil.getTextContent(node); - values[i] = createValue(arg, value); - } - return values; - } - - /** - * Finds all element nodes in the list that match any argument name or argument - * alias, throws {@link ActionException} if not all arguments were found. - */ - protected List getMatchingNodes(NodeList nodeList, ActionArgument[] args) throws ActionException { - - List names = new ArrayList<>(); - for (ActionArgument argument : args) { - names.add(argument.getName()); - names.addAll(Arrays.asList(argument.getAliases())); - } - - List matches = new ArrayList<>(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node child = nodeList.item(i); - - if (child.getNodeType() != Node.ELEMENT_NODE) - continue; - - if (names.contains(getUnprefixedNodeName(child))) - matches.add(child); - } - - if (matches.size() < args.length) { - throw new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, - "Invalid number of input or output arguments in XML message, expected " + args.length + " but found " + matches.size() - ); - } - return matches; - } - - /** - * Creates an instance of {@link ActionArgumentValue} and wraps an - * {@link InvalidValueException} as an {@link ActionException} with the - * appropriate {@link ErrorCode}. - */ - protected ActionArgumentValue createValue(ActionArgument arg, String value) throws ActionException { - try { - return new ActionArgumentValue(arg, value); - } catch (InvalidValueException ex) { - throw new ActionException( - ErrorCode.ARGUMENT_VALUE_INVALID, - "Wrong type or invalid value for '" + arg.getName() + "': " + ex.getMessage(), - ex - ); - } - } - - /** - * Returns the node with the same unprefixed name as the action argument - * name/alias or null. - */ - protected Node findActionArgumentNode(List nodes, ActionArgument arg) { - for(Node node : nodes) { - if(arg.isNameOrAlias(getUnprefixedNodeName(node))) return node; - } - return null; - } - - public void warning(SAXParseException e) throws SAXException { - log.warning(e.toString()); - } - - public void error(SAXParseException e) throws SAXException { - throw e; - } - - public void fatalError(SAXParseException e) throws SAXException { - throw e; - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamClientConfigurationImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamClientConfigurationImpl.java deleted file mode 100644 index cd58002..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamClientConfigurationImpl.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.transport.spi.AbstractStreamClientConfiguration; - -import java.util.concurrent.ExecutorService; - -/** - * Settings for the default implementation. - * - * @author Christian Bauer - */ -public class StreamClientConfigurationImpl extends AbstractStreamClientConfiguration { - - private boolean usePersistentConnections = false; - - public StreamClientConfigurationImpl(ExecutorService timeoutExecutorService) { - super(timeoutExecutorService); - } - - public StreamClientConfigurationImpl(ExecutorService timeoutExecutorService, int timeoutSeconds) { - super(timeoutExecutorService, timeoutSeconds); - } - - /** - * Defaults to false, avoiding obscure bugs in the JDK. - */ - public boolean isUsePersistentConnections() { - return usePersistentConnections; - } - - public void setUsePersistentConnections(boolean usePersistentConnections) { - this.usePersistentConnections = usePersistentConnections; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamClientImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamClientImpl.java deleted file mode 100644 index 10d67db..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamClientImpl.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.model.ModelUtil; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.UpnpMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.transport.spi.InitializationException; -import org.fourthline.cling.transport.spi.StreamClient; -import org.seamless.http.Headers; -import org.seamless.util.Exceptions; -import org.seamless.util.URIUtil; -import org.seamless.util.io.IO; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.ProtocolException; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.net.URLStreamHandlerFactory; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Default implementation based on the JDK's HttpURLConnection. - *

- * This class works around a serious design issue in the SUN JDK, so it will not work on any JDK that - * doesn't offer the sun.net.www.protocol.http.HttpURLConnection implementation. - *

- *

- * This implementation DOES NOT WORK on Android. Read the Cling manual for - * alternatives for Android. - *

- *

- * This implementation DOES NOT support Cling's server-side heartbeat for connection checking. - * Any data returned by a server has to be "valid HTTP", checked in Sun's HttpClient with: - *

- * {@code ret = b[0] == 'H' && b[1] == 'T' && b[2] == 'T' && b[3] == 'P' && b[4] == '/' && b[5] == '1' && b[6] == '.';} - *

- * Hence, if you are using this client, don't call Cling's - * {@link org.fourthline.cling.model.profile.RemoteClientInfo#isRequestCancelled()} function on your - * server to send a heartbeat to the client! - *

- * - * @author Christian Bauer - */ -public class StreamClientImpl implements StreamClient { - - final static String HACK_STREAM_HANDLER_SYSTEM_PROPERTY = "hackStreamHandlerProperty"; - - final private static Logger log = Logger.getLogger(StreamClient.class.getName()); - - final protected StreamClientConfigurationImpl configuration; - - public StreamClientImpl(StreamClientConfigurationImpl configuration) throws InitializationException { - this.configuration = configuration; - - if (ModelUtil.ANDROID_EMULATOR || ModelUtil.ANDROID_RUNTIME) { - /* - See the fantastic PERMITTED_USER_METHODS here: - - https://android.googlesource.com/platform/libcore/+/android-4.0.1_r1.2/luni/src/main/java/java/net/HttpURLConnection.java - - We'd have to basically copy the whole Android code, and have a dependency on - libcore.*, and do much more hacking to allow more HTTP methods. This is the same - problem we are hacking below for the JDK but at least there we don't have a - dependency issue for compiling Cling. These guys all suck, there is no list - of "permitted" HTTP methods. HttpURLConnection and the whole stream handler - factory stuff is the worst Java API ever created. - */ - throw new InitializationException( - "This client does not work on Android. The design of HttpURLConnection is broken, we " - + "can not add additional 'permitted' HTTP methods. Read the Cling manual." - ); - } - - log.fine("Using persistent HTTP stream client connections: " + configuration.isUsePersistentConnections()); - System.setProperty("http.keepAlive", Boolean.toString(configuration.isUsePersistentConnections())); - - // Hack the environment to allow additional HTTP methods - if (System.getProperty(HACK_STREAM_HANDLER_SYSTEM_PROPERTY) == null) { - log.fine("Setting custom static URLStreamHandlerFactory to work around bad JDK defaults"); - try { - // Use reflection to avoid dependency on sun.net package so this class at least - // loads on Android, even if it doesn't work... - URL.setURLStreamHandlerFactory( - (URLStreamHandlerFactory) Class.forName( - "org.fourthline.cling.transport.impl.FixedSunURLStreamHandler" - ).newInstance() - ); - } catch (Throwable t) { - throw new InitializationException( - "Failed to set modified URLStreamHandlerFactory in this environment." - + " Can't use bundled default client based on HTTPURLConnection, see manual." - ); - } - System.setProperty(HACK_STREAM_HANDLER_SYSTEM_PROPERTY, "alreadyWorkedAroundTheEvilJDK"); - } - } - - @Override - public StreamClientConfigurationImpl getConfiguration() { - return configuration; - } - - @Override - public StreamResponseMessage sendRequest(StreamRequestMessage requestMessage) { - - final UpnpRequest requestOperation = requestMessage.getOperation(); - log.fine("Preparing HTTP request message with method '" + requestOperation.getHttpMethodName() + "': " + requestMessage); - - URL url = URIUtil.toURL(requestOperation.getURI()); - - HttpURLConnection urlConnection = null; - InputStream inputStream; - try { - - urlConnection = (HttpURLConnection) url.openConnection(); - - urlConnection.setRequestMethod(requestOperation.getHttpMethodName()); - - // Use the built-in expiration, we can't cancel HttpURLConnection - urlConnection.setReadTimeout(configuration.getTimeoutSeconds() * 1000); - urlConnection.setConnectTimeout(configuration.getTimeoutSeconds() * 1000); - - applyRequestProperties(urlConnection, requestMessage); - applyRequestBody(urlConnection, requestMessage); - - log.fine("Sending HTTP request: " + requestMessage); - inputStream = urlConnection.getInputStream(); - return createResponse(urlConnection, inputStream); - - } catch (ProtocolException ex) { - log.log(Level.WARNING, "HTTP request failed: " + requestMessage, Exceptions.unwrap(ex)); - return null; - } catch (IOException ex) { - - if (urlConnection == null) { - log.log(Level.WARNING, "HTTP request failed: " + requestMessage, Exceptions.unwrap(ex)); - return null; - } - - if (ex instanceof SocketTimeoutException) { - log.info( - "Timeout of " + getConfiguration().getTimeoutSeconds() - + " seconds while waiting for HTTP request to complete, aborting: " + requestMessage - ); - return null; - } - - if (log.isLoggable(Level.FINE)) - log.fine("Exception occurred, trying to read the error stream: " + Exceptions.unwrap(ex)); - try { - inputStream = urlConnection.getErrorStream(); - return createResponse(urlConnection, inputStream); - } catch (Exception errorEx) { - if (log.isLoggable(Level.FINE)) - log.fine("Could not read error stream: " + errorEx); - return null; - } - } catch (Exception ex) { - log.log(Level.WARNING, "HTTP request failed: " + requestMessage, Exceptions.unwrap(ex)); - return null; - - } finally { - - if (urlConnection != null) { - // Release any idle persistent connection, or "indicate that we don't want to use this server for a while" - urlConnection.disconnect(); - } - } - } - - @Override - public void stop() { - // NOOP - } - - protected void applyRequestProperties(HttpURLConnection urlConnection, StreamRequestMessage requestMessage) { - - urlConnection.setInstanceFollowRedirects(false); // Defaults to true but not needed here - - // HttpURLConnection always adds a "Host" header - - // HttpURLConnection always adds an "Accept" header (not needed but shouldn't hurt) - - // Add the default user agent if not already set on the message - if (!requestMessage.getHeaders().containsKey(UpnpHeader.Type.USER_AGENT)) { - urlConnection.setRequestProperty( - UpnpHeader.Type.USER_AGENT.getHttpName(), - getConfiguration().getUserAgentValue(requestMessage.getUdaMajorVersion(), requestMessage.getUdaMinorVersion()) - ); - } - - // Other headers - applyHeaders(urlConnection, requestMessage.getHeaders()); - } - - protected void applyHeaders(HttpURLConnection urlConnection, Headers headers) { - log.fine("Writing headers on HttpURLConnection: " + headers.size()); - for (Map.Entry> entry : headers.entrySet()) { - for (String v : entry.getValue()) { - String headerName = entry.getKey(); - log.fine("Setting header '" + headerName + "': " + v); - urlConnection.setRequestProperty(headerName, v); - } - } - } - - protected void applyRequestBody(HttpURLConnection urlConnection, StreamRequestMessage requestMessage) throws IOException { - - if (requestMessage.hasBody()) { - urlConnection.setDoOutput(true); - } else { - urlConnection.setDoOutput(false); - return; - } - - if (requestMessage.getBodyType().equals(UpnpMessage.BodyType.STRING)) { - IO.writeUTF8(urlConnection.getOutputStream(), requestMessage.getBodyString()); - } else if (requestMessage.getBodyType().equals(UpnpMessage.BodyType.BYTES)) { - IO.writeBytes(urlConnection.getOutputStream(), requestMessage.getBodyBytes()); - } - urlConnection.getOutputStream().flush(); - } - - protected StreamResponseMessage createResponse(HttpURLConnection urlConnection, InputStream inputStream) throws Exception { - - if (urlConnection.getResponseCode() == -1) { - log.warning("Received an invalid HTTP response: " + urlConnection.getURL()); - log.warning("Is your Cling-based server sending connection heartbeats with " + - "RemoteClientInfo#isRequestCancelled? This client can't handle " + - "heartbeats, read the manual."); - return null; - } - - // Status - UpnpResponse responseOperation = new UpnpResponse(urlConnection.getResponseCode(), urlConnection.getResponseMessage()); - - log.fine("Received response: " + responseOperation); - - // Message - StreamResponseMessage responseMessage = new StreamResponseMessage(responseOperation); - - // Headers - responseMessage.setHeaders(new UpnpHeaders(urlConnection.getHeaderFields())); - - // Body - byte[] bodyBytes = null; - InputStream is = null; - try { - is = inputStream; - if (inputStream != null) bodyBytes = IO.readBytes(is); - } finally { - if (is != null) - is.close(); - } - - if (bodyBytes != null && bodyBytes.length > 0 && responseMessage.isContentTypeMissingOrText()) { - - log.fine("Response contains textual entity body, converting then setting string on message"); - responseMessage.setBodyCharacters(bodyBytes); - - } else if (bodyBytes != null && bodyBytes.length > 0) { - - log.fine("Response contains binary entity body, setting bytes on message"); - responseMessage.setBody(UpnpMessage.BodyType.BYTES, bodyBytes); - - } else { - log.fine("Response did not contain entity body"); - } - - log.fine("Response message complete: " + responseMessage); - return responseMessage; - } - -} - - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamServerConfigurationImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamServerConfigurationImpl.java deleted file mode 100644 index 27e0a86..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamServerConfigurationImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import org.fourthline.cling.transport.spi.StreamServerConfiguration; - -/** - * Settings for the default implementation. - * - * @author Christian Bauer - */ -public class StreamServerConfigurationImpl implements StreamServerConfiguration { - - private int listenPort; - private int tcpConnectionBacklog; - - /** - * Defaults to port '0', ephemeral. - */ - public StreamServerConfigurationImpl() { - } - - public StreamServerConfigurationImpl(int listenPort) { - this.listenPort = listenPort; - } - - public int getListenPort() { - return listenPort; - } - - public void setListenPort(int listenPort) { - this.listenPort = listenPort; - } - - /** - * @return Maximum number of queued incoming connections to allow on the listening socket, - * default is system default. - */ - public int getTcpConnectionBacklog() { - return tcpConnectionBacklog; - } - - public void setTcpConnectionBacklog(int tcpConnectionBacklog) { - this.tcpConnectionBacklog = tcpConnectionBacklog; - } - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamServerImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamServerImpl.java deleted file mode 100644 index 0a7d493..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/StreamServerImpl.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl; - -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpServer; -import org.fourthline.cling.model.message.Connection; -import org.fourthline.cling.transport.Router; -import org.fourthline.cling.transport.spi.InitializationException; -import org.fourthline.cling.transport.spi.StreamServer; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.logging.Logger; - -/** - * Implementation based on the built-in SUN JDK 6.0 HTTP Server. - *

- * See the - * documentation of the SUN JDK 6.0 HTTP Server. - *

- *

- * This implementation DOES NOT WORK on Android. Read the Cling manual for - * alternatives for Android. - *

- *

- * This implementation does not support connection alive checking, as we can't send - * heartbeats to the client. We don't have access to the raw socket with the Sun API. - *

- * - * @author Christian Bauer - */ -public class StreamServerImpl implements StreamServer { - - private static Logger log = Logger.getLogger(StreamServer.class.getName()); - - final protected StreamServerConfigurationImpl configuration; - protected HttpServer server; - - public StreamServerImpl(StreamServerConfigurationImpl configuration) { - this.configuration = configuration; - } - - synchronized public void init(InetAddress bindAddress, Router router) throws InitializationException { - try { - InetSocketAddress socketAddress = new InetSocketAddress(bindAddress, configuration.getListenPort()); - - server = HttpServer.create(socketAddress, configuration.getTcpConnectionBacklog()); - server.createContext("/", new RequestHttpHandler(router)); - - log.info("Created server (for receiving TCP streams) on: " + server.getAddress()); - - } catch (Exception ex) { - throw new InitializationException("Could not initialize " + getClass().getSimpleName() + ": " + ex.toString(), ex); - } - } - - synchronized public int getPort() { - return server.getAddress().getPort(); - } - - public StreamServerConfigurationImpl getConfiguration() { - return configuration; - } - - synchronized public void run() { - log.fine("Starting StreamServer..."); - // Starts a new thread but inherits the properties of the calling thread - server.start(); - } - - synchronized public void stop() { - log.fine("Stopping StreamServer..."); - if (server != null) server.stop(1); - } - - protected class RequestHttpHandler implements HttpHandler { - - private final Router router; - - public RequestHttpHandler(Router router) { - this.router = router; - } - - // This is executed in the request receiving thread! - public void handle(final HttpExchange httpExchange) throws IOException { - // And we pass control to the service, which will (hopefully) start a new thread immediately so we can - // continue the receiving thread ASAP - log.fine("Received HTTP exchange: " + httpExchange.getRequestMethod() + " " + httpExchange.getRequestURI()); - router.received( - new HttpExchangeUpnpStream(router.getProtocolFactory(), httpExchange) { - @Override - protected Connection createConnection() { - return new HttpServerConnection(httpExchange); - } - } - ); - } - } - - /** - * Logs a warning and returns true, we can't access the socket using the awful JDK webserver API. - *

- * Override this method if you know how to do it. - *

- */ - protected boolean isConnectionOpen(HttpExchange exchange) { - log.warning("Can't check client connection, socket access impossible on JDK webserver!"); - return true; - } - - protected class HttpServerConnection implements Connection { - - protected HttpExchange exchange; - - public HttpServerConnection(HttpExchange exchange) { - this.exchange = exchange; - } - - @Override - public boolean isOpen() { - return isConnectionOpen(exchange); - } - - @Override - public InetAddress getRemoteAddress() { - return exchange.getRemoteAddress() != null - ? exchange.getRemoteAddress().getAddress() - : null; - } - - @Override - public InetAddress getLocalAddress() { - return exchange.getLocalAddress() != null - ? exchange.getLocalAddress().getAddress() - : null; - } - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/JettyServletContainer.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/JettyServletContainer.java deleted file mode 100644 index 2e60e9c..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/JettyServletContainer.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl.jetty; - -import org.eclipse.jetty.server.AbstractHttpConnection; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.bio.SocketConnector; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.thread.ExecutorThreadPool; -import org.fourthline.cling.transport.spi.ServletContainerAdapter; - -import javax.servlet.Servlet; -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.net.Socket; -import java.util.concurrent.ExecutorService; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * A singleton wrapper of a org.eclipse.jetty.server.Server. - *

- * This {@link org.fourthline.cling.transport.spi.ServletContainerAdapter} starts - * a Jetty 8 instance on its own and stops it. Only one single context and servlet - * is registered, to handle UPnP requests. - *

- *

- * This implementation works on Android, dependencies are jetty-server - * and jetty-servlet Maven modules. - *

- * - * @author Christian Bauer - */ -public class JettyServletContainer implements ServletContainerAdapter { - - final private static Logger log = Logger.getLogger(JettyServletContainer.class.getName()); - - // Singleton - public static final JettyServletContainer INSTANCE = new JettyServletContainer(); - private JettyServletContainer() { - resetServer(); - } - - protected Server server; - - @Override - synchronized public void setExecutorService(ExecutorService executorService) { - if (INSTANCE.server.getThreadPool() == null) { - INSTANCE.server.setThreadPool(new ExecutorThreadPool(executorService) { - @Override - protected void doStop() throws Exception { - // Do nothing, don't shut down the Cling ExecutorService when Jetty stops! - } - }); - } - } - - @Override - synchronized public int addConnector(String host, int port) throws IOException { - SocketConnector connector = new SocketConnector(); - connector.setHost(host); - connector.setPort(port); - - // Open immediately so we can get the assigned local port - connector.open(); - - // Only add if open() succeeded - server.addConnector(connector); - - // stats the connector if the server is started (server starts all connectors when started) - if (server.isStarted()) { - try { - connector.start(); - } catch (Exception ex) { - log.severe("Couldn't start connector: " + connector + " " + ex); - throw new RuntimeException(ex); - } - } - return connector.getLocalPort(); - } - - @Override - synchronized public void removeConnector(String host, int port) { - Connector[] connectors = server.getConnectors(); - for (Connector connector : connectors) { - if (connector.getHost().equals(host) && connector.getLocalPort() == port) { - if (connector.isStarted() || connector.isStarting()) { - try { - connector.stop(); - } catch (Exception ex) { - log.severe("Couldn't stop connector: " + connector + " " + ex); - throw new RuntimeException(ex); - } - } - server.removeConnector(connector); - if (connectors.length == 1) { - log.info("No more connectors, stopping Jetty server"); - stopIfRunning(); - } - break; - } - } - } - - @Override - synchronized public void registerServlet(String contextPath, Servlet servlet) { - if (server.getHandler() != null) { - return; - } - log.info("Registering UPnP servlet under context path: " + contextPath); - ServletContextHandler servletHandler = - new ServletContextHandler(ServletContextHandler.NO_SESSIONS); - if (contextPath != null && contextPath.length() > 0) - servletHandler.setContextPath(contextPath); - ServletHolder s = new ServletHolder(servlet); - servletHandler.addServlet(s, "/*"); - server.setHandler(servletHandler); - } - - @Override - synchronized public void startIfNotRunning() { - if (!server.isStarted() && !server.isStarting()) { - log.info("Starting Jetty server... "); - try { - server.start(); - } catch (Exception ex) { - log.severe("Couldn't start Jetty server: " + ex); - throw new RuntimeException(ex); - } - } - } - - @Override - synchronized public void stopIfRunning() { - if (!server.isStopped() && !server.isStopping()) { - log.info("Stopping Jetty server..."); - try { - server.stop(); - } catch (Exception ex) { - log.severe("Couldn't stop Jetty server: " + ex); - throw new RuntimeException(ex); - } finally { - resetServer(); - } - } - } - - protected void resetServer() { - server = new Server(); // Has its own QueuedThreadPool - server.setGracefulShutdown(1000); // Let's wait a second for ongoing transfers to complete - } - - /** - * Casts the request to a Jetty API and tries to write a space character to the output stream of the socket. - *

- * This space character might confuse the HTTP client. The Cling transports for Jetty Client and - * Apache HttpClient have been tested to work with space characters. Unfortunately, Sun JDK's - * HttpURLConnection does not gracefully handle any garbage in the HTTP request! - *

- */ - public static boolean isConnectionOpen(HttpServletRequest request) { - return isConnectionOpen(request, " ".getBytes()); - } - - public static boolean isConnectionOpen(HttpServletRequest request, byte[] heartbeat) { - Request jettyRequest = (Request)request; - AbstractHttpConnection connection = jettyRequest.getConnection(); - Socket socket = (Socket)connection.getEndPoint().getTransport(); - if (log.isLoggable(Level.FINE)) - log.fine("Checking if client connection is still open: " + socket.getRemoteSocketAddress()); - try { - socket.getOutputStream().write(heartbeat); - socket.getOutputStream().flush(); - return true; - } catch (IOException ex) { - if (log.isLoggable(Level.FINE)) - log.fine("Client connection has been closed: " + socket.getRemoteSocketAddress()); - return false; - } - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/StreamClientConfigurationImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/StreamClientConfigurationImpl.java deleted file mode 100644 index 95a7678..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/StreamClientConfigurationImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl.jetty; - -import org.fourthline.cling.transport.spi.AbstractStreamClientConfiguration; - -import java.util.concurrent.ExecutorService; - -/** - * Settings for the Jetty 8 implementation. - * - * @author Christian Bauer - */ -public class StreamClientConfigurationImpl extends AbstractStreamClientConfiguration { - - public StreamClientConfigurationImpl(ExecutorService timeoutExecutorService) { - super(timeoutExecutorService); - } - - public StreamClientConfigurationImpl(ExecutorService timeoutExecutorService, int timeoutSeconds) { - super(timeoutExecutorService, timeoutSeconds); - } - - /** - * @return By default 0. - */ - public int getRequestRetryCount() { - return 0; - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/StreamClientImpl.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/StreamClientImpl.java deleted file mode 100644 index 9f3a29e..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/impl/jetty/StreamClientImpl.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.impl.jetty; - -import org.eclipse.jetty.client.ContentExchange; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpExchange; -import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpHeaders; -import org.eclipse.jetty.io.ByteArrayBuffer; -import org.eclipse.jetty.util.thread.ExecutorThreadPool; -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpHeaders; -import org.fourthline.cling.model.message.UpnpMessage; -import org.fourthline.cling.model.message.UpnpRequest; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.model.message.header.ContentTypeHeader; -import org.fourthline.cling.model.message.header.UpnpHeader; -import org.fourthline.cling.transport.spi.AbstractStreamClient; -import org.fourthline.cling.transport.spi.InitializationException; -import org.fourthline.cling.transport.spi.StreamClient; -import org.seamless.util.Exceptions; -import org.seamless.util.MimeType; - -import java.io.UnsupportedEncodingException; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Implementation based on Jetty 8 client API. - *

- * This implementation works on Android, dependencies are the jetty-client - * Maven module. - *

- * - * @author Christian Bauer - */ -public class StreamClientImpl extends AbstractStreamClient { - - final private static Logger log = Logger.getLogger(StreamClient.class.getName()); - - final protected StreamClientConfigurationImpl configuration; - final protected HttpClient client; - - public StreamClientImpl(StreamClientConfigurationImpl configuration) throws InitializationException { - this.configuration = configuration; - - log.info("Starting Jetty HttpClient..."); - client = new HttpClient(); - - // Jetty client needs threads for its internal expiration routines, which we don't need but - // can't disable, so let's abuse the request executor service for this - client.setThreadPool( - new ExecutorThreadPool(getConfiguration().getRequestExecutorService()) { - @Override - protected void doStop() throws Exception { - // Do nothing, don't shut down the Cling ExecutorService when Jetty stops! - } - } - ); - - // These are some safety settings, we should never run into these timeouts as we - // do our own expiration checking - client.setTimeout((configuration.getTimeoutSeconds()+5) * 1000); - client.setConnectTimeout((configuration.getTimeoutSeconds()+5) * 1000); - - client.setMaxRetries(configuration.getRequestRetryCount()); - - try { - client.start(); - } catch (Exception ex) { - throw new InitializationException( - "Could not start Jetty HTTP client: " + ex, ex - ); - } - } - - @Override - public StreamClientConfigurationImpl getConfiguration() { - return configuration; - } - - @Override - protected HttpContentExchange createRequest(StreamRequestMessage requestMessage) { - return new HttpContentExchange(getConfiguration(), client, requestMessage); - } - - @Override - protected Callable createCallable(final StreamRequestMessage requestMessage, - final HttpContentExchange exchange) { - return new Callable() { - public StreamResponseMessage call() throws Exception { - - if (log.isLoggable(Level.FINE)) - log.fine("Sending HTTP request: " + requestMessage); - - client.send(exchange); - int exchangeState = exchange.waitForDone(); - - if (exchangeState == HttpExchange.STATUS_COMPLETED) { - try { - return exchange.createResponse(); - } catch (Throwable t) { - log.log(Level.WARNING, "Error reading response: " + requestMessage, Exceptions.unwrap(t)); - return null; - } - } else if (exchangeState == HttpExchange.STATUS_CANCELLED) { - // That's ok, happens when we abort the exchange after timeout - return null; - } else if (exchangeState == HttpExchange.STATUS_EXCEPTED) { - // The warnings of the "excepted" condition are logged in HttpContentExchange - return null; - } else { - log.warning("Unhandled HTTP exchange status: " + exchangeState); - return null; - } - } - }; - } - - @Override - protected void abort(HttpContentExchange exchange) { - exchange.cancel(); - } - - @Override - protected boolean logExecutionException(Throwable t) { - return false; - } - - @Override - public void stop() { - try { - client.stop(); - } catch (Exception ex) { - log.info("Error stopping HTTP client: " + ex); - } - } - - static public class HttpContentExchange extends ContentExchange { - - final protected StreamClientConfigurationImpl configuration; - final protected HttpClient client; - final protected StreamRequestMessage requestMessage; - - protected Throwable exception; - - public HttpContentExchange(StreamClientConfigurationImpl configuration, - HttpClient client, - StreamRequestMessage requestMessage) { - super(true); - this.configuration = configuration; - this.client = client; - this.requestMessage = requestMessage; - applyRequestURLMethod(); - applyRequestHeaders(); - applyRequestBody(); - } - - @Override - protected void onConnectionFailed(Throwable t) { - log.log(Level.WARNING, "HTTP connection failed: " + requestMessage, Exceptions.unwrap(t)); - } - - @Override - protected void onException(Throwable t) { - log.log(Level.WARNING, "HTTP request failed: " + requestMessage, Exceptions.unwrap(t)); - } - - public StreamClientConfigurationImpl getConfiguration() { - return configuration; - } - - public StreamRequestMessage getRequestMessage() { - return requestMessage; - } - - protected void applyRequestURLMethod() { - final UpnpRequest requestOperation = getRequestMessage().getOperation(); - if (log.isLoggable(Level.FINE)) - log.fine( - "Preparing HTTP request message with method '" - + requestOperation.getHttpMethodName() - + "': " + getRequestMessage() - ); - - setURL(requestOperation.getURI().toString()); - setMethod(requestOperation.getHttpMethodName()); - } - - protected void applyRequestHeaders() { - // Headers - UpnpHeaders headers = getRequestMessage().getHeaders(); - if (log.isLoggable(Level.FINE)) - log.fine("Writing headers on HttpContentExchange: " + headers.size()); - // TODO Always add the Host header - // TODO: ? setRequestHeader(UpnpHeader.Type.HOST.getHttpName(), ); - // Add the default user agent if not already set on the message - if (!headers.containsKey(UpnpHeader.Type.USER_AGENT)) { - setRequestHeader( - UpnpHeader.Type.USER_AGENT.getHttpName(), - getConfiguration().getUserAgentValue( - getRequestMessage().getUdaMajorVersion(), - getRequestMessage().getUdaMinorVersion()) - ); - } - for (Map.Entry> entry : headers.entrySet()) { - for (String v : entry.getValue()) { - String headerName = entry.getKey(); - if (log.isLoggable(Level.FINE)) - log.fine("Setting header '" + headerName + "': " + v); - addRequestHeader(headerName, v); - } - } - } - - protected void applyRequestBody() { - // Body - if (getRequestMessage().hasBody()) { - if (getRequestMessage().getBodyType() == UpnpMessage.BodyType.STRING) { - if (log.isLoggable(Level.FINE)) - log.fine("Writing textual request body: " + getRequestMessage()); - - MimeType contentType = - getRequestMessage().getContentTypeHeader() != null - ? getRequestMessage().getContentTypeHeader().getValue() - : ContentTypeHeader.DEFAULT_CONTENT_TYPE_UTF8; - - String charset = - getRequestMessage().getContentTypeCharset() != null - ? getRequestMessage().getContentTypeCharset() - : "UTF-8"; - - setRequestContentType(contentType.toString()); - ByteArrayBuffer buffer; - try { - buffer = new ByteArrayBuffer(getRequestMessage().getBodyString(), charset); - } catch (UnsupportedEncodingException ex) { - throw new RuntimeException("Unsupported character encoding: " + charset, ex); - } - setRequestHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(buffer.length())); - setRequestContent(buffer); - - } else { - if (log.isLoggable(Level.FINE)) - log.fine("Writing binary request body: " + getRequestMessage()); - - if (getRequestMessage().getContentTypeHeader() == null) - throw new RuntimeException( - "Missing content type header in request message: " + requestMessage - ); - MimeType contentType = getRequestMessage().getContentTypeHeader().getValue(); - - setRequestContentType(contentType.toString()); - ByteArrayBuffer buffer; - buffer = new ByteArrayBuffer(getRequestMessage().getBodyBytes()); - setRequestHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(buffer.length())); - setRequestContent(buffer); - } - } - } - - protected StreamResponseMessage createResponse() { - // Status - UpnpResponse responseOperation = - new UpnpResponse( - getResponseStatus(), - UpnpResponse.Status.getByStatusCode(getResponseStatus()).getStatusMsg() - ); - - if (log.isLoggable(Level.FINE)) - log.fine("Received response: " + responseOperation); - - StreamResponseMessage responseMessage = new StreamResponseMessage(responseOperation); - - // Headers - UpnpHeaders headers = new UpnpHeaders(); - HttpFields responseFields = getResponseFields(); - for (String name : responseFields.getFieldNamesCollection()) { - for (String value : responseFields.getValuesCollection(name)) { - headers.add(name, value); - } - } - responseMessage.setHeaders(headers); - - // Body - byte[] bytes = getResponseContentBytes(); - if (bytes != null && bytes.length > 0 && responseMessage.isContentTypeMissingOrText()) { - - if (log.isLoggable(Level.FINE)) - log.fine("Response contains textual entity body, converting then setting string on message"); - try { - responseMessage.setBodyCharacters(bytes); - } catch (UnsupportedEncodingException ex) { - throw new RuntimeException("Unsupported character encoding: " + ex, ex); - } - - } else if (bytes != null && bytes.length > 0) { - - if (log.isLoggable(Level.FINE)) - log.fine("Response contains binary entity body, setting bytes on message"); - responseMessage.setBody(UpnpMessage.BodyType.BYTES, bytes); - - } else { - if (log.isLoggable(Level.FINE)) - log.fine("Response did not contain entity body"); - } - - if (log.isLoggable(Level.FINE)) - log.fine("Response message complete: " + responseMessage); - return responseMessage; - } - } -} - - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/AbstractStreamClient.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/AbstractStreamClient.java deleted file mode 100644 index 2ba6848..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/AbstractStreamClient.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.transport.spi; - -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.seamless.util.Exceptions; - -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Implements the timeout/callback processing and unifies exception handling. - - * @author Christian Bauer - */ -public abstract class AbstractStreamClient implements StreamClient { - - final private static Logger log = Logger.getLogger(StreamClient.class.getName()); - - @Override - public StreamResponseMessage sendRequest(StreamRequestMessage requestMessage) throws InterruptedException { - - if (log.isLoggable(Level.FINE)) - log.fine("Preparing HTTP request: " + requestMessage); - - REQUEST request = createRequest(requestMessage); - if (request == null) - return null; - - Callable callable = createCallable(requestMessage, request); - - // We want to track how long it takes - long start = System.currentTimeMillis(); - - // Execute the request on a new thread - Future future = - getConfiguration().getRequestExecutorService().submit(callable); - - // Wait on the current thread for completion - try { - if (log.isLoggable(Level.FINE)) - log.fine( - "Waiting " + getConfiguration().getTimeoutSeconds() - + " seconds for HTTP request to complete: " + requestMessage - ); - StreamResponseMessage response = - future.get(getConfiguration().getTimeoutSeconds(), TimeUnit.SECONDS); - - // Log a warning if it took too long - long elapsed = System.currentTimeMillis() - start; - if (log.isLoggable(Level.FINEST)) - log.finest("Got HTTP response in " + elapsed + "ms: " + requestMessage); - if (getConfiguration().getLogWarningSeconds() > 0 - && elapsed > getConfiguration().getLogWarningSeconds()*1000) { - log.warning("HTTP request took a long time (" + elapsed + "ms): " + requestMessage); - } - - return response; - - } catch (InterruptedException ex) { - - if (log.isLoggable(Level.FINE)) - log.fine("Interruption, aborting request: " + requestMessage); - abort(request); - throw new InterruptedException("HTTP request interrupted and aborted"); - - } catch (TimeoutException ex) { - - log.info( - "Timeout of " + getConfiguration().getTimeoutSeconds() - + " seconds while waiting for HTTP request to complete, aborting: " + requestMessage - ); - abort(request); - return null; - - } catch (ExecutionException ex) { - Throwable cause = ex.getCause(); - if (!logExecutionException(cause)) { - log.log(Level.WARNING, "HTTP request failed: " + requestMessage, Exceptions.unwrap(cause)); - } - return null; - } finally { - onFinally(request); - } - } - - /** - * Create a proprietary representation of this request, log warnings and - * return null if creation fails. - */ - abstract protected REQUEST createRequest(StreamRequestMessage requestMessage); - - /** - * Create a callable procedure that will execute the request. - */ - abstract protected Callable createCallable(StreamRequestMessage requestMessage, - REQUEST request); - - /** - * Cancel and abort the request immediately, with the proprietary API. - */ - abstract protected void abort(REQUEST request); - - /** - * @return true if no more logging of this exception should be done. - */ - abstract protected boolean logExecutionException(Throwable t); - - protected void onFinally(REQUEST request) { - // Do nothing - } - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/AbstractStreamClientConfiguration.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/AbstractStreamClientConfiguration.java deleted file mode 100644 index 9eb93a0..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/AbstractStreamClientConfiguration.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.transport.spi; - -import org.fourthline.cling.model.ServerClientTokens; - -import java.util.concurrent.ExecutorService; - -/** - * @author Christian Bauer - */ -public abstract class AbstractStreamClientConfiguration implements StreamClientConfiguration { - - protected ExecutorService requestExecutorService; - protected int timeoutSeconds = 60; - protected int logWarningSeconds = 5; - - protected AbstractStreamClientConfiguration(ExecutorService requestExecutorService) { - this.requestExecutorService = requestExecutorService; - } - - protected AbstractStreamClientConfiguration(ExecutorService requestExecutorService, int timeoutSeconds) { - this.requestExecutorService = requestExecutorService; - this.timeoutSeconds = timeoutSeconds; - } - - protected AbstractStreamClientConfiguration(ExecutorService requestExecutorService, int timeoutSeconds, int logWarningSeconds) { - this.requestExecutorService = requestExecutorService; - this.timeoutSeconds = timeoutSeconds; - this.logWarningSeconds = logWarningSeconds; - } - - public ExecutorService getRequestExecutorService() { - return requestExecutorService; - } - - public void setRequestExecutorService(ExecutorService requestExecutorService) { - this.requestExecutorService = requestExecutorService; - } - - /** - * @return Configured value or default of 60 seconds. - */ - public int getTimeoutSeconds() { - return timeoutSeconds; - } - - public void setTimeoutSeconds(int timeoutSeconds) { - this.timeoutSeconds = timeoutSeconds; - } - - /** - * @return Configured value or default of 5 seconds. - */ - public int getLogWarningSeconds() { - return logWarningSeconds; - } - - public void setLogWarningSeconds(int logWarningSeconds) { - this.logWarningSeconds = logWarningSeconds; - } - - /** - * @return Defaults to string value of {@link org.fourthline.cling.model.ServerClientTokens}. - */ - public String getUserAgentValue(int majorVersion, int minorVersion) { - return new ServerClientTokens(majorVersion, minorVersion).toString(); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramIO.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramIO.java deleted file mode 100644 index 1f90c6d..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramIO.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import org.fourthline.cling.transport.Router; -import org.fourthline.cling.model.message.OutgoingDatagramMessage; - -import java.net.InetAddress; -import java.net.DatagramPacket; - -/** - * Service for receiving (unicast only) and sending UDP datagrams, one per bound IP address. - *

- * This service typically listens on a socket for UDP unicast datagrams, with - * an ephemeral port. - *

- *

- * This listening loop is started with the run() method, - * this service is Runnable. Any received datagram is then converted into an - * {@link org.fourthline.cling.model.message.IncomingDatagramMessage} and - * handled by the - * {@link org.fourthline.cling.transport.Router#received(org.fourthline.cling.model.message.IncomingDatagramMessage)} - * method. This conversion is the job of the {@link org.fourthline.cling.transport.spi.DatagramProcessor}. - *

- *

- * Clients of this service use it to send UDP datagrams, either to a unicast - * or multicast destination. Any {@link org.fourthline.cling.model.message.OutgoingDatagramMessage} can - * be converted and written into a datagram with the {@link org.fourthline.cling.transport.spi.DatagramProcessor}. - *

- *

- * An implementation has to be thread-safe. - *

- * - * @param The type of the service's configuration. - * - * @author Christian Bauer - */ -public interface DatagramIO extends Runnable { - - /** - * Configures the service and starts any listening sockets. - * - * @param bindAddress The address to bind any sockets on. - * @param router The router which handles received {@link org.fourthline.cling.model.message.IncomingDatagramMessage}s. - * @param datagramProcessor Reads and writes datagrams. - * @throws InitializationException If the service could not be initialized or started. - */ - public void init(InetAddress bindAddress, Router router, DatagramProcessor datagramProcessor) throws InitializationException; - - /** - * Stops the service, closes any listening sockets. - */ - public void stop(); - - /** - * @return This service's configuration. - */ - public C getConfiguration(); - - /** - * Sends a datagram after conversion with {@link org.fourthline.cling.transport.spi.DatagramProcessor#write(org.fourthline.cling.model.message.OutgoingDatagramMessage)}. - * - * @param message The message to send. - */ - public void send(OutgoingDatagramMessage message); - - /** - * The actual sending of a UDP datagram. - *

- * Recoverable errors should be logged, if appropriate only with debug level. Any - * non-recoverable errors should be thrown as RuntimeExceptions. - *

- * - * @param datagram The UDP datagram to send. - */ - public void send(DatagramPacket datagram); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramIOConfiguration.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramIOConfiguration.java deleted file mode 100644 index cf7718a..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramIOConfiguration.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -/** - * Collection of typically needed configuration settings. - * - * @author Christian Bauer - */ -public interface DatagramIOConfiguration { - - /** - * @return The TTL of a UDP datagram sent to a multicast address. - */ - public int getTimeToLive(); - - /** - * @return The maximum buffer size of received UDP datagrams. - */ - public int getMaxDatagramBytes(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramProcessor.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramProcessor.java deleted file mode 100644 index 536cb56..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/DatagramProcessor.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - - -import org.fourthline.cling.model.UnsupportedDataException; -import org.fourthline.cling.model.message.IncomingDatagramMessage; -import org.fourthline.cling.model.message.OutgoingDatagramMessage; - -import java.net.DatagramPacket; -import java.net.InetAddress; - -/** - * Reads and creates UDP datagrams from and into UPnP messages. - *

- * An implementation of this interface has to be thread-safe. - *

- * - * @author Christian Bauer - */ -public interface DatagramProcessor { - - /** - * Reads the datagram and instantiates a message. - *

- * The message is either a {@link org.fourthline.cling.model.message.UpnpRequest} or - * a {@link org.fourthline.cling.model.message.UpnpResponse} operation type. - *

- * - * @param receivedOnAddress The address of the socket on which this datagram was received. - * @param datagram The received UDP datagram. - * @return The populated instance. - * @throws org.fourthline.cling.model.UnsupportedDataException If the datagram could not be read, or didn't contain required data. - */ - public IncomingDatagramMessage read(InetAddress receivedOnAddress, DatagramPacket datagram) throws UnsupportedDataException; - - /** - * Creates a UDP datagram with the content of a message. - *

- * The outgoing message might be a {@link org.fourthline.cling.model.message.UpnpRequest} or a - * {@link org.fourthline.cling.model.message.UpnpResponse}. - *

- * - * @param message The outgoing datagram message. - * @return An actual UDP datagram. - * @throws UnsupportedDataException If the datagram could not be created. - */ - public DatagramPacket write(OutgoingDatagramMessage message) throws UnsupportedDataException; - -} - - diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/GENAEventProcessor.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/GENAEventProcessor.java deleted file mode 100644 index 91556da..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/GENAEventProcessor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import org.fourthline.cling.model.UnsupportedDataException; -import org.fourthline.cling.model.message.gena.IncomingEventRequestMessage; -import org.fourthline.cling.model.message.gena.OutgoingEventRequestMessage; - -/** - * Reads and writes GENA XML content. - * - * @author Christian Bauer - */ -public interface GENAEventProcessor { - - /** - * Transforms a collection of {@link org.fourthline.cling.model.state.StateVariableValue}s into an XML message body. - * - * @param requestMessage The message to transform. - * @throws org.fourthline.cling.model.UnsupportedDataException - */ - public void writeBody(OutgoingEventRequestMessage requestMessage) throws UnsupportedDataException; - - /** - * Transforms an XML message body and adds to a collection of {@link org.fourthline.cling.model.state.StateVariableValue}s.. - * - * @param requestMessage The message to transform. - * @throws UnsupportedDataException - */ - public void readBody(IncomingEventRequestMessage requestMessage) throws UnsupportedDataException; - -} \ No newline at end of file diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/InitializationException.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/InitializationException.java deleted file mode 100644 index b583ec8..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/InitializationException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -/** - * Thrown by the transport layer implementation when service setup fails. - *

- * This exception typically indicates a configuration problem and it is not - * recoverable unless you can continue without the service that threw this - * exception. - *

- * - * @author Christian Bauer - */ -public class InitializationException extends RuntimeException { - - public InitializationException(String s) { - super(s); - } - - public InitializationException(String s, Throwable throwable) { - super(s, throwable); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/MulticastReceiver.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/MulticastReceiver.java deleted file mode 100644 index ffa5ef4..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/MulticastReceiver.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import org.fourthline.cling.transport.Router; - -import java.net.NetworkInterface; - -/** - * Service for receiving multicast UDP datagrams, one per bound network interface. - *

- * This services typically listens on a socket for UDP datagrams, the socket has joined - * the configured multicast group. - *

- *

- * This listening loop is started with the run() method, - * this service is Runnable. Any received datagram is then converted into an - * {@link org.fourthline.cling.model.message.IncomingDatagramMessage} and - * handled by the - * {@link org.fourthline.cling.transport.Router#received(org.fourthline.cling.model.message.IncomingDatagramMessage)} - * method. This conversion is the job of the {@link org.fourthline.cling.transport.spi.DatagramProcessor}. - *

- *

- * An implementation has to be thread-safe. - *

- * - * @param The type of the service's configuration. - * - * @author Christian Bauer - */ -public interface MulticastReceiver extends Runnable { - - /** - * Configures the service and starts any listening sockets. - * - * @param networkInterface The network interface on which to join the multicast group on. - * @param router The router which handles received {@link org.fourthline.cling.model.message.IncomingDatagramMessage}s. - * @param networkAddressFactory The network address factory to use for local address lookup given a local interface and a remote address. - * @param datagramProcessor Reads and writes datagrams. - * @throws InitializationException If the service could not be initialized or started. - */ - public void init(NetworkInterface networkInterface, - Router router, - NetworkAddressFactory networkAddressFactory, - DatagramProcessor datagramProcessor) throws InitializationException; - - /** - * Stops the service, closes any listening sockets. - */ - public void stop(); - - /** - * @return This service's configuration. - */ - public C getConfiguration(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/MulticastReceiverConfiguration.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/MulticastReceiverConfiguration.java deleted file mode 100644 index 2c1cff7..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/MulticastReceiverConfiguration.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import java.net.InetAddress; - -/** - * Collection of typically needed configuration settings. - * - * @author Christian Bauer - */ -public interface MulticastReceiverConfiguration { - - /** - * @return The multicast group to join. - */ - public InetAddress getGroup(); - - /** - * @return The port to listen on. - */ - public int getPort(); - - /** - * @return The maximum buffer size of received UDP datagrams. - */ - public int getMaxDatagramBytes(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/NetworkAddressFactory.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/NetworkAddressFactory.java deleted file mode 100644 index 88ee512..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/NetworkAddressFactory.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.util.Iterator; - -/** - * Configuration utility for network interfaces and addresses. - *

- * An implementation has to be thread-safe. - *

- * - * @author Christian Bauer - */ -public interface NetworkAddressFactory { - - // An implementation can honor these if it wants (the default does) - public static final String SYSTEM_PROPERTY_NET_IFACES = "org.fourthline.cling.network.useInterfaces"; - public static final String SYSTEM_PROPERTY_NET_ADDRESSES = "org.fourthline.cling.network.useAddresses"; - - - /** - * @return The UDP multicast group to join. - */ - public InetAddress getMulticastGroup(); - - /** - * @return The UDP multicast port to listen on. - */ - public int getMulticastPort(); - - /** - * @return The TCP (HTTP) stream request port to listen on. - */ - public int getStreamListenPort(); - - /** - * The caller might remove() an interface if initialization fails. - * - * @return The local network interfaces on which multicast groups will be joined. - */ - public Iterator getNetworkInterfaces(); - - /** - * The caller might remove() an address if initialization fails. - * - * @return The local addresses of the network interfaces bound to - * sockets listening for unicast datagrams and TCP requests. - */ - public Iterator getBindAddresses(); - - /** - * @return true if there is at least one usable network interface and bind address. - */ - public boolean hasUsableNetwork(); - - /** - * @return The network prefix length of this address or null. - */ - public Short getAddressNetworkPrefixLength(InetAddress inetAddress); - - /** - * @param inetAddress An address of a local network interface. - * @return The MAC hardware address of the network interface or null if no - * hardware address could be obtained. - */ - public byte[] getHardwareAddress(InetAddress inetAddress); - - /** - * @param inetAddress An address of a local network interface. - * @return The broadcast address of the network (interface) or null if no - * broadcast address could be obtained. - */ - public InetAddress getBroadcastAddress(InetAddress inetAddress); - - /** - * Best-effort attempt finding a reachable local address for a given remote host. - *

- * This method is called whenever a multicast datagram has been received. We need to be - * able to communicate with the sender using UDP unicast and we need to tell the sender - * how we are reachable with TCP requests. We need a local address that is in the same - * subnet as the senders address, that is reachable from the senders point of view. - *

- * - * @param networkInterface The network interface to examine. - * @param isIPv6 True if the given remote address is an IPv6 address. - * @param remoteAddress The remote address for which to find a local address in the same subnet. - * @return A local address that is reachable from the given remote address. - * @throws IllegalStateException If no local address reachable by the remote address has been found. - */ - public InetAddress getLocalAddress(NetworkInterface networkInterface, - boolean isIPv6, - InetAddress remoteAddress) throws IllegalStateException; - - /** - * For debugging, logs all "usable" network interface(s) details with INFO level. - */ - public void logInterfaceInformation(); -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/NoNetworkException.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/NoNetworkException.java deleted file mode 100644 index 582f654..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/NoNetworkException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.fourthline.cling.transport.spi; - -/** - * Might be thrown by the constructor of {@link NetworkAddressFactory} and - * {@link org.fourthline.cling.transport.Router} if no usable - * network interfaces/addresses were discovered. - * - * @author Christian Bauer - */ -public class NoNetworkException extends InitializationException { - - public NoNetworkException(String s) { - super(s); - } -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/SOAPActionProcessor.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/SOAPActionProcessor.java deleted file mode 100644 index 0784a67..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/SOAPActionProcessor.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import org.fourthline.cling.model.UnsupportedDataException; -import org.fourthline.cling.model.action.ActionInvocation; -import org.fourthline.cling.model.message.control.ActionRequestMessage; -import org.fourthline.cling.model.message.control.ActionResponseMessage; - -/** - * Converts UPnP SOAP messages from/to action invocations. - *

- * The UPnP protocol layer processes local and remote {@link org.fourthline.cling.model.action.ActionInvocation} - * instances. The UPnP transport layer accepts and returns {@link org.fourthline.cling.model.message.StreamRequestMessage}s - * and {@link org.fourthline.cling.model.message.StreamResponseMessage}s. This processor is an adapter between the - * two layers, reading and writing SOAP content. - *

- * - * @author Christian Bauer - */ -public interface SOAPActionProcessor { - - /** - * Converts the given invocation input into SOAP XML content, setting on the given request message. - * - * @param requestMessage The request message on which the SOAP content is set. - * @param actionInvocation The action invocation from which input argument values are read. - * @throws org.fourthline.cling.model.UnsupportedDataException - */ - public void writeBody(ActionRequestMessage requestMessage, ActionInvocation actionInvocation) throws UnsupportedDataException; - - /** - * Converts the given invocation output into SOAP XML content, setting on the given response message. - * - * @param responseMessage The response message on which the SOAP content is set. - * @param actionInvocation The action invocation from which output argument values are read. - * @throws UnsupportedDataException - */ - public void writeBody(ActionResponseMessage responseMessage, ActionInvocation actionInvocation) throws UnsupportedDataException; - - /** - * Converts SOAP XML content of the request message and sets input argument values on the given invocation. - * - * @param requestMessage The request message from which SOAP content is read. - * @param actionInvocation The action invocation on which input argument values are set. - * @throws UnsupportedDataException - */ - public void readBody(ActionRequestMessage requestMessage, ActionInvocation actionInvocation) throws UnsupportedDataException; - - /** - * Converts SOAP XML content of the response message and sets output argument values on the given invocation. - * - * @param responseMsg The response message from which SOAP content is read. - * @param actionInvocation The action invocation on which output argument values are set. - * @throws UnsupportedDataException - */ - public void readBody(ActionResponseMessage responseMsg, ActionInvocation actionInvocation) throws UnsupportedDataException; - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/ServletContainerAdapter.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/ServletContainerAdapter.java deleted file mode 100644 index 568044f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/ServletContainerAdapter.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import javax.servlet.Servlet; -import java.io.IOException; -import java.util.concurrent.ExecutorService; - -/** - * Implement this to provide your own servlet container (instance), - *

- * It's OK if you don't start or stop your container when this adapter is - * called. You can treat the {@link #startIfNotRunning()} and - * {@link #stopIfRunning()} methods as suggestions, they only indicate what - * the UPnP stack wants to do. If your servlet container handles other - * services, keep it running all the time. - *

- *

- * An implementation must be thread-safe, all methods might be called concurrently - * by several threads. - *

- * - * @author Christian Bauer - */ -public interface ServletContainerAdapter { - - /** - * Might be called several times to integrate the servlet container with Cling's executor - * configuration. You can ignore this call if you want to configure the container's thread - * pooling independently from Cling. If you use the given Cling ExecutorService, - * make sure the Jetty container won't shut it down when {@link #stopIfRunning()} is called! - * - * @param executorService The service to use when spawning new servlet execution threads. - */ - void setExecutorService(ExecutorService executorService); - - /** - * Might be called several times to set up the connectors. This is the host/address - * and the port Cling expects to receive HTTP requests on. If you set up your HTTP - * server connectors elsewhere and ignore when Cling calls this method, make sure - * you configure Cling with the correct host/port of your servlet container. - * - * @param host The host address for the socket. - * @param port The port, might be -1 to bind to an ephemeral port. - * @return The actual registered local port. - * @throws IOException If the connector couldn't be opened to retrieve the registered local port. - */ - int addConnector(String host, int port) throws IOException; - - /** - * Removes a previously added connector. Implementation should close the corresponding - * listening server socket. It may stop the server when the last connector is removed. - * - * @param host The host address of the socket. - * @param port The port of the connector - */ - void removeConnector(String host, int port); - - /** - * Might be called several times to register (the same) handler for UPnP - * requests, should only register it once. - * - * @param contextPath The context path prefix for all UPnP requests. - * @param servlet The servlet handling all UPnP requests. - */ - void registerServlet(String contextPath, Servlet servlet); - - /** - * Start your servlet container if it isn't already running, might be called multiple times. - */ - void startIfNotRunning(); - - /** - * Stop your servlet container if it's still running, might be called multiple times. - */ - void stopIfRunning(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamClient.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamClient.java deleted file mode 100644 index ca5e616..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamClient.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; - -/** - * Service for sending TCP (HTTP) stream request messages. - * - *

- * An implementation has to be thread-safe. - * Its constructor may throw {@link org.fourthline.cling.transport.spi.InitializationException}. - *

- * - * @param The type of the service's configuration. - * - * @author Christian Bauer - */ -public interface StreamClient { - - /** - * Sends the given request via TCP (HTTP) and returns the response. - * - *

- * This method must implement expiration of timed out requests using the - * {@link StreamClientConfiguration} settings. When a request expires, a - * null response will be returned. - *

- *

- * This method will always try to complete execution without throwing an exception. It will - * return null if an error occurs, and optionally log any exception messages. - *

- *

- * The rules for logging are: - *

- *
    - *
  • If the caller interrupts the calling thread, log at FINE.
  • - *
  • If the request expires because the timeout has been reached, log at INFO level.
  • - *
  • If another error occurs, log at WARNING level
  • - *
- *

- * This method is required to add a Host HTTP header to the - * outgoing HTTP request, even if the given - * {@link org.fourthline.cling.model.message.StreamRequestMessage} does not contain such a header. - *

- *

- * This method will add the User-Agent HTTP header to the outgoing HTTP request if - * the given message did not already contain such a header. You can set this default value in your - * {@link StreamClientConfiguration}. - *

- * - * @param message The message to send. - * @return The response or null if no response has been received or an error occurred. - * @throws InterruptedException if you interrupt the calling thread. - */ - public StreamResponseMessage sendRequest(StreamRequestMessage message) throws InterruptedException; - - /** - * Stops the service, closes any connection pools etc. - */ - public void stop(); - - /** - * @return This service's configuration. - */ - public C getConfiguration(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamClientConfiguration.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamClientConfiguration.java deleted file mode 100644 index 81c324f..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamClientConfiguration.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import java.util.concurrent.ExecutorService; - -/** - * Collection of typically needed configuration settings. - * - * @author Christian Bauer - */ -public interface StreamClientConfiguration { - - /** - * Used to execute the actual HTTP request, the StreamClient waits on the "current" thread for - * completion or timeout. You probably want to use the same executor service for both, so usually - * this is {@link org.fourthline.cling.UpnpServiceConfiguration#getSyncProtocolExecutorService()}. - * - * @return The ExecutorService to use for actual sending of HTTP requests. - */ - public ExecutorService getRequestExecutorService(); - - /** - * @return The number of seconds to wait for a request to expire, spanning connect and data-reads. - */ - public int getTimeoutSeconds(); - - /** - * @return If the request completion takes longer than this, a warning will be logged (0 to disable) - */ - public int getLogWarningSeconds(); - - /** - * Used for outgoing HTTP requests if no other value was already set on messages. - * - * @param majorVersion The UPnP UDA major version. - * @param minorVersion The UPnP UDA minor version. - * @return The HTTP user agent value. - */ - public String getUserAgentValue(int majorVersion, int minorVersion); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamServer.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamServer.java deleted file mode 100644 index 11594c9..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamServer.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import org.fourthline.cling.transport.Router; - -import java.net.InetAddress; - -/** - * Service for receiving TCP (HTTP) streams, one per bound IP address. - *

- * This service typically listens on a socket for TCP connections. - *

- * This listening loop is started with the run() method, this service is - * Runnable. Then {@link Router#received(UpnpStream)} is called with a custom - * {@link UpnpStream}. This will start processing of the request and run() the - * {@link UpnpStream} (which is also Runnable) in a separate thread, - * freeing up the receiving thread immediately. - *

- *

- * The {@link UpnpStream} then creates a {@link org.fourthline.cling.model.message.StreamRequestMessage} - * and calls the {@link UpnpStream#process(org.fourthline.cling.model.message.StreamRequestMessage)} - * method. The {@link UpnpStream} then returns the response to the network client. - *

- *

- * In pseudo-code: - *

- *
- * MyStreamServer implements StreamServer {
- *      run() {
- *          while (not stopped) {
- *              Connection con = listenToSocketAndBlock();
- *              router.received( new MyUpnpStream(con) );
- *          }
- *      }
- * }
- *
- * MyUpnpStream(con) extends UpnpStream {
- *      run() {
- *          try {
- *              StreamRequestMessage request = // ... Read request
- *              StreamResponseMessage response = process(request);
- *              // ... Send response
- *              responseSent(response))
- *          } catch (Exception ex) {
- *              responseException(ex);
- *          }
- *      }
- * }
- * 
- *

- * An implementation has to be thread-safe. - *

- * - * @param The type of the service's configuration. - * - * @author Christian Bauer - */ -public interface StreamServer extends Runnable { - - /** - * Configures the service and starts any listening sockets. - * - * @param bindAddress The address to bind any sockets on. - * @param router The router which handles the incoming {@link org.fourthline.cling.transport.spi.UpnpStream}. - * @throws InitializationException If the service could not be initialized or started. - */ - public void init(InetAddress bindAddress, Router router) throws InitializationException; - - /** - * This method will be called potentially right after - * {@link #init(java.net.InetAddress, org.fourthline.cling.transport.Router)}, the - * actual assigned local port must be available before the server is started. - * - * @return The TCP port this service is listening on, e.g. the actual ephemeral port. - */ - public int getPort(); - - /** - * Stops the service, closes any listening sockets. - */ - public void stop(); - - /** - * @return This service's configuration. - */ - public C getConfiguration(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamServerConfiguration.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamServerConfiguration.java deleted file mode 100644 index 9f74228..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/StreamServerConfiguration.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -/** - * Collection of typically needed configuration settings. - * - * @author Christian Bauer - */ -public interface StreamServerConfiguration { - - /** - * @return The TCP port to listen on for HTTP requests. - */ - public int getListenPort(); - -} diff --git a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/UpnpStream.java b/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/UpnpStream.java deleted file mode 100644 index e57cf20..0000000 --- a/clinglibrary/src/main/java/org/fourthline/cling/transport/spi/UpnpStream.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2013 4th Line GmbH, Switzerland - * - * The contents of this file are subject to the terms of either the GNU - * Lesser General Public License Version 2 or later ("LGPL") or the - * Common Development and Distribution License Version 1 or later - * ("CDDL") (collectively, the "License"). You may not use this file - * except in compliance with the License. See LICENSE.txt for more - * information. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -package org.fourthline.cling.transport.spi; - -import org.fourthline.cling.model.message.StreamRequestMessage; -import org.fourthline.cling.model.message.StreamResponseMessage; -import org.fourthline.cling.model.message.UpnpResponse; -import org.fourthline.cling.protocol.ProtocolCreationException; -import org.fourthline.cling.protocol.ProtocolFactory; -import org.fourthline.cling.protocol.ReceivingSync; -import org.seamless.util.Exceptions; - -import java.util.logging.Logger; - -/** - * A runnable representation of a single HTTP request/response procedure. - *

- * Instantiated by the {@link StreamServer}, executed by the - * {@link org.fourthline.cling.transport.Router}. See the pseudo-code example - * in the documentation of {@link StreamServer}. An implementation's - * run() method has to call the {@link #process(org.fourthline.cling.model.message.StreamRequestMessage)}, - * {@link #responseSent(org.fourthline.cling.model.message.StreamResponseMessage)} and - * {@link #responseException(Throwable)} methods. - *

- *

- * An implementation does not have to be thread-safe. - *

- * @author Christian Bauer - */ -public abstract class UpnpStream implements Runnable { - - private static Logger log = Logger.getLogger(UpnpStream.class.getName()); - - protected final ProtocolFactory protocolFactory; - protected ReceivingSync syncProtocol; - - protected UpnpStream(ProtocolFactory protocolFactory) { - this.protocolFactory = protocolFactory; - } - - public ProtocolFactory getProtocolFactory() { - return protocolFactory; - } - - /** - * Selects a UPnP protocol, runs it within the calling thread, returns the response. - *

- * This method will return null if the UPnP protocol returned null. - * The HTTP response in this case is always 404 NOT FOUND. Any other (HTTP) error - * condition will be encapsulated in the returned response message and has to be - * passed to the HTTP client as it is. - *

- * @param requestMsg The TCP (HTTP) stream request message. - * @return The TCP (HTTP) stream response message, or null if a 404 should be send to the client. - */ - public StreamResponseMessage process(StreamRequestMessage requestMsg) { - log.fine("Processing stream request message: " + requestMsg); - - try { - // Try to get a protocol implementation that matches the request message - syncProtocol = getProtocolFactory().createReceivingSync(requestMsg); - } catch (ProtocolCreationException ex) { - log.warning("Processing stream request failed - " + Exceptions.unwrap(ex).toString()); - return new StreamResponseMessage(UpnpResponse.Status.NOT_IMPLEMENTED); - } - - // Run it - log.fine("Running protocol for synchronous message processing: " + syncProtocol); - syncProtocol.run(); - - // ... then grab the response - StreamResponseMessage responseMsg = syncProtocol.getOutputMessage(); - - if (responseMsg == null) { - // That's ok, the caller is supposed to handle this properly (e.g. convert it to HTTP 404) - log.finer("Protocol did not return any response message"); - return null; - } - log.finer("Protocol returned response: " + responseMsg); - return responseMsg; - } - - /** - * Must be called by a subclass after the response has been successfully sent to the client. - * - * @param responseMessage The response message successfully sent to the client. - */ - protected void responseSent(StreamResponseMessage responseMessage) { - if (syncProtocol != null) - syncProtocol.responseSent(responseMessage); - } - - /** - * Must be called by a subclass if the response was not delivered to the client. - * - * @param t The reason why the response wasn't delivered. - */ - protected void responseException(Throwable t) { - if (syncProtocol != null) - syncProtocol.responseException(t); - } - - @Override - public String toString() { - return "(" + getClass().getSimpleName() + ")"; - } -} diff --git a/clinglibrary/src/main/res/values/strings.xml b/clinglibrary/src/main/res/values/strings.xml deleted file mode 100644 index d6728e1..0000000 --- a/clinglibrary/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - ClingLibrary - diff --git a/clinglibrary/src/test/java/com/zane/clinglibrary/ExampleUnitTest.java b/clinglibrary/src/test/java/com/zane/clinglibrary/ExampleUnitTest.java deleted file mode 100644 index 7a8ee90..0000000 --- a/clinglibrary/src/test/java/com/zane/clinglibrary/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.zane.clinglibrary; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/dkplayer-java/src/main/res/drawable-xhdpi/dkplayer_dlna_connected_change_device.png b/dkplayer-java/src/main/res/drawable-xhdpi/dkplayer_dlna_connected_change_device.png deleted file mode 100644 index 95c44f5dd641c0cc5d8a78b7a1d213e217a313ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6824 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 diff --git a/dkplayer-java/src/main/res/drawable-xhdpi/dkplayer_dlna_connected_tv_bg.png b/dkplayer-java/src/main/res/drawable-xhdpi/dkplayer_dlna_connected_tv_bg.png deleted file mode 100644 index f01a21381f95b2c540960139a701cabc855d5a06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170783 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 &%j7>fH?FdKhYull<^GfK7ZDHLGMx! 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 z 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%0AFA2}(%1>srY9V5s*Kyf^6d+oQhWR76{UqW{3^5v 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̋ZX62EKcK?HrN|LNx? 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 diff --git a/dkplayer-java/src/main/res/drawable-xhdpi/dkplayer_icon_dlna.png b/dkplayer-java/src/main/res/drawable-xhdpi/dkplayer_icon_dlna.png deleted file mode 100644 index 7c0518257adc7980ccce536d13141f9dbe50bf89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1157 zcmV;01bX|4P)Px(KS@MERA>e5noVp>Q51kXXjK%Ug7{5{lvtF7pCFCeAyq*{2#t-#rdul;k=WT= zsUk>)ioXQuq*ygJ5~&c0s7P9*ZA$#~Z+vImH#zU-O<&%dwr}3lNzUAJ&pr3v^Syg# z-ko`qDDse0DzyXm0kjHTiq1t7Xg*7dP6!BoghEE^$Esx`Eb<=tfsmd@D~# zy&mun4nhVP*b_Jfw%BPbkg^|+gFp-XzikTae(Yv+ia0Hitp*Xl4;r zfEtX5<2q2TP}*x% zjGXS4xdN!*+pS`{umdj;eOxOX<%iY-n7$ZDIq)Adwl4HmzrxOt_kT_j8L&zIs>)ur zbw*g3IaKy$97RRBZ)XOJ4A_8ZhzcM#DZoS6rKaA_1?o_3q0LBvfp|^kFIDz>m9?!e zj0z8KMha}w)i8%yj$?m_kHwy+bzA2iIsP7ygU zFuf#m*GY)74%MI7dIzYmaAxGdCT$HR_ifqIBA?KwX={vL@&))YJfA(7n%Ds&9{$j- zyZ|;(O&%1D9=@Dhc>!z)Y`EuK2z>_63DoHv_-yKQ^eHQ7cP^$p{_qvx-f=rxM4;2p z^XsDTKt2KE0!;FuzJ!GB=fmh~cCMz&S;!R|xRh<>^{67w*T6ZCrx^tJo1&SGy;jv@ zZL)a6B212a6X3T_&6FptdYr4LtmNOyuL=#QE%jDl?5Y6O+fdXS1X!N9ee`H-!&ieY zNAv!DEjgkqP{}!o+R}-mEDeHD%@RIBr)OD8`DtZLk9b+;$;B;i&uq6@dHS%6+g@vC z<$$iic@3R~7Lt4i<|wfD1S)e|GLH55?n^@fND2mltaM<7DYL>-afH>DCkgw|Ds%}t z5A}@2A5`?;5+tcmr!tR8Wh^w-|9~Aa4 Xb5~xOdmCIf00000NkvXXu0mjfe)%BQ diff --git a/dkplayer-java/src/main/res/drawable-xxhdpi/dkplayer_dlna_connected_change_device.png b/dkplayer-java/src/main/res/drawable-xxhdpi/dkplayer_dlna_connected_change_device.png deleted file mode 100644 index bb05cf479ab243c648095703286f618c95609ab8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11201 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%0D? z?XzUijChnj-pzZES$>LZaUN4TAaF4-yiG#00X5^6^`dC&hCr)grPG*OhgJ{gIPtc@ zC=bg4ZUOZyK<7Zx&hb^|O0mD`;AJX4!+SVidRm@)S=8{}n584+`WQN|f8~a+5eu^0 zwVqg*^KX$tpyTd$)E^t|7>5o1{u?WGD38w#`8J0%Z-}g6+Clx^4rgFQAX2-l=m>sO zT1XAstAdUw}DLE#f&kixW=<@WP32O|a9z?4wPdwzz=U3CfDx z?Xqd3m4W~>V-l4|PpHS-mWmyn9o8VUXezKCpT^XHC|x*hPA zeH+w?qU;uJgvopSO#f`woxt8Y)mAe6!dW+3!)xv=aKm|=Hs{fvXB#x+U?NUbqa`fh zepJBYVF*^^JvamAhnleazAXtuEjKS-M1SeQeoAEOt}cIX<9*M-2lrb_3Evn7inZ%< zmuc|xJqldd5_(!bSK-0G}n68->sK<}?#2lpZ~(^(bn7_Sy}3Se)g zr>Bq7eet64-PU(5TT_%7iJ`i-*ujc8{$s2M!PU}ymGeqB$FSa)*2UI^!VMNw`^l0q zma)u_^D_+ZD-mP6#{~IEad8a~9&abZH=3k+jD;Hcm3dQuc}GR2y>yQ^bi^OjU2N=+ z{&}b3o#t)NIUMr=0uFe6jg`5>_EU$Ifg75{k;3oUZjbweK)cTjo7*W?iw5X5Im&EA z$fRAw%OEGi`4M?p(Ob*S+F*;)EnD1Wi>{8&Nx63DJLdcIG5l(f_eZM$HUDNw=xZoH z?I9Kcp6{k=y)FhG301MXM=STypd#=)<2%hM%90KA^`GYGJt`}cU(N1ffF-)U0#LoD&f{uyM($5+iom++wT zG5j!sewK$26hIpUUkCK_J@hq&Ci6dpD6soA;2>_BvZZ=D4}?MFcVNgidOx;9JkkM^ z;IKcy!yu{;Rz%PZO^}=$Xm9Z`u`W(R zPNu6EkV5hQe`X~5YJTqT65XC2JF=}(jax|!S7X8FL)p0661X2n+vXuQ4W?f@tA`R9 zE0h$oPCp#$e@wvh*vDIUI8~7I`s{Eee01iVrDnOAY7PR&!{w)8AB($gjOZ|kIM|TE ziGt_~FkFFL&p(!+LAoJ|g@vNBb!ybg!y8gakfkr!^4d#Qwk>?)yxODHVmL*mt+J?) z29A!oWm3*V@elgK_z}Ggm38K)pl7|?xU4p_So_H`gQ>jump&Ci0jo$=vkZG0h3((d zYvM7C@lGkAz%4QdO>-}9r)_QVh%}eg46yXg#oUr#15vvhVr;eFI5Y5zblD0;kxa+Z z@2<48w8vYYts_Q>utC(3VS_ypoZ-v;CtMD$a@DD|eH+YL>DZ<~v8kibY_-bC7rub4H?9uDzZ46Bo zv{6!GnC|6}T)bCd(rWeA52i#w` zN*R|OPKpyJ)%Nk&+FMq?2+^f;Toy2d&$8`kcD`{Oi`{gSl?2<0YRm+cF`I{&zMsG*rcGY>tiW8ho^1j%oI?A1wr{~4QzgoVLqy3QUYy&^K8jOypm4kujl zi1IQgSxRYSLNuC+%F`5WE2PZ7+Ia(u&>-GxkdlZ%S;fFpx fm(MxnneRk`7URI5J7>U~T#%~bQ-yLlOu+vG=U2yj diff --git a/dkplayer-java/src/main/res/drawable-xxhdpi/dkplayer_dlna_connected_exit.png b/dkplayer-java/src/main/res/drawable-xxhdpi/dkplayer_dlna_connected_exit.png deleted file mode 100644 index 1736c116f0077126944b47962078b4cf7bf77f5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15356 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�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 IDz*{-2MbJx2mk;8 diff --git a/other/module-lite.sh b/other/module-lite.sh deleted file mode 100644 index 3dafacd..0000000 --- a/other/module-lite.sh +++ /dev/null @@ -1,270 +0,0 @@ -#! /usr/bin/env bash - -#-------------------- -# Standard options: -export COMMON_FF_CFG_FLAGS= -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --prefix=PREFIX" - -# Licensing options: -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-gpl" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-version3" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-nonfree" - -# Configuration options: -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-static" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-shared" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-small" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-runtime-cpudetect" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-gray" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-swscale-alpha" - -# Program options: -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-programs" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffmpeg" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffplay" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffprobe" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffserver" - -# Documentation options: -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-doc" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-htmlpages" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-manpages" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-podpages" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-txtpages" - -# Component options: -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-avdevice" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avcodec" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avformat" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avutil" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-swresample" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-swscale" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-postproc" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avfilter" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-avresample" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-pthreads" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-w32threads" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-os2threads" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-network" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-dct" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-dwt" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-lsp" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-lzo" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mdct" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-rdft" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-fft" - -# Hardware accelerators: -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-d3d11va" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-dxva2" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vaapi" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vda" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vdpau" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-videotoolbox" - -# Individual component options: -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-everything" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-encoders" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-encoder=png" - -# ./configure --list-decoders -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-decoders" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=aac" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=aac_latm" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=flv" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=h264" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mp3*" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=vp6f" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=flac" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=hevc" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=vp8" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=vp9" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=h263" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=h263i" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=h263p" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mpeg4" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mjpeg" - -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-hwaccels" - -# ./configure --list-muxers -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-muxers" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-muxer=mp4" - -# ./configure --list-demuxers -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-demuxers" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=aac" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=concat" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=data" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=flv" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=hls" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=live_flv" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mov" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mp3" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mpegps" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mpegts" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mpegvideo" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=flac" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=hevc" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=webm_dash_manifest" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mpeg4" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtsp" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mjpeg" - -# ./configure --list-parsers -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-parsers" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=aac" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=aac_latm" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=h264" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=flac" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=hevc" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=mpeg4" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=mpeg4video" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=mpegvideo" - -# ./configure --list-bsf -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-bsfs" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=chomp" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=dca_core" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=dump_extradata" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=hevc_mp4toannexb" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=imx_dump_header" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=mjpeg2jpeg" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=mjpega_dump_header" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=mov2textsub" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=mp3_header_decompress" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=mpeg4_unpack_bframes" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=noise" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=remove_extradata" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=text2movsub" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=vp9_superframe" - -# ./configure --list-protocols -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocols" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=async" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=bluray" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=concat" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=crypto" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=ffrtmpcrypt" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=ffrtmphttp" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=gopher" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=icecast" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=librtmp*" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=libssh" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=md5" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=mmsh" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=mmst" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=rtmp*" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtmp" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtmpt" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtp" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=sctp" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=srtp" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=subfile" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=unix" - -# -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-devices" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-filters" - -# External library support: -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-iconv" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-audiotoolbox" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-videotoolbox" - -# ... - -# Advanced options (experts only): -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --cross-prefix=${FF_CROSS_PREFIX}-" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-cross-compile" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --sysroot=PATH" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --sysinclude=PATH" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --target-os=TAGET_OS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --target-exec=CMD" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --target-path=DIR" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --toolchain=NAME" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --nm=NM" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --ar=AR" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --as=AS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --yasmexe=EXE" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --cc=CC" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --cxx=CXX" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --dep-cc=DEPCC" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --ld=LD" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-cc=HOSTCC" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-cflags=HCFLAGS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-cppflags=HCPPFLAGS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-ld=HOSTLD" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-ldflags=HLDFLAGS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-libs=HLIBS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-os=OS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --extra-cflags=ECFLAGS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --extra-cxxflags=ECFLAGS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --extra-ldflags=ELDFLAGS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --extra-libs=ELIBS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --extra-version=STRING" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --optflags=OPTFLAGS" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --build-suffix=SUFFIX" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --malloc-prefix=PREFIX" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --progs-suffix=SUFFIX" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --arch=ARCH" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --cpu=CPU" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-pic" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-sram" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-thumb" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-symver" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-hardcoded-tables" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-safe-bitstream-reader" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-memalign-hack" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-lto" - -# Optimization options (experts only): -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-asm" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-altivec" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-amd3dnow" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-amd3dnowext" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mmx" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mmxext" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-sse" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-sse2" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-sse3" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ssse3" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-sse4" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-sse42" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-avx" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-fma4" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-armv5te" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-armv6" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-armv6t2" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vfp" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-neon" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vis" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-inline-asm" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-yasm" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mips32r2" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mipsdspr1" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mipsdspr2" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mipsfpu" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-fast-unaligned" - -# Developer options (useful when working on FFmpeg itself): -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-coverage" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-debug" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-debug=LEVEL" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-optimizations" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-extra-warnings" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-stripping" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --assert-level=level" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-memory-poisoning" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --valgrind=VALGRIND" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-ftrapv" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --samples=PATH" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-xmm-clobber-test" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-random" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-random" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-random=LIST" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-random=LIST" -# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --random-seed=VALUE" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-linux-perf" -export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bzlib" - diff --git a/other/test.ffconcat b/other/test.ffconcat deleted file mode 100644 index 7ec8b8f..0000000 --- a/other/test.ffconcat +++ /dev/null @@ -1,7 +0,0 @@ -ffconcat version 1.0 -file 'http://gslb.miaopai.com/stream/FQXM04zrW1dcXGiPdJ6Q3KAq2Fpv4TLV.mp4' -duration 30 -file 'http://gslb.miaopai.com/stream/FQXM04zrW1dcXGiPdJ6Q3KAq2Fpv4TLV.mp4' -duration 30 -file 'http://gslb.miaopai.com/stream/FQXM04zrW1dcXGiPdJ6Q3KAq2Fpv4TLV.mp4' -duration 30 \ No newline at end of file diff --git a/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java b/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java index bff4546..52cb971 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java +++ b/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java @@ -937,6 +937,10 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro this.mDanmakuEnable = mDanmakuEnable; } + public boolean isDLNAEnable() { + return mDLNAEnable; + } + public List getFloatingComments() { return mFloatingComments; } diff --git a/player/src/main/java/cn/ctyun/videoplayer/widget/controller/DanmakuController.java b/player/src/main/java/cn/ctyun/videoplayer/widget/controller/DanmakuController.java index 25ebe75..67927e7 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/widget/controller/DanmakuController.java +++ b/player/src/main/java/cn/ctyun/videoplayer/widget/controller/DanmakuController.java @@ -181,6 +181,9 @@ public class DanmakuController extends DefinitionController { mIvDanmakuControl.setVisibility(GONE); mOpenEditDanmaku.setVisibility(GONE); } + if (!((DanmakuControllerInterface) mMediaPlayer).isDanmakuEnable()) { + mDLNAButton.setVisibility(GONE); + } } } -- Gitee From d6597bf83b9bfa017d79a8c22e31f845fc9727b1 Mon Sep 17 00:00:00 2001 From: liujt Date: Wed, 13 Mar 2019 14:48:18 +0800 Subject: [PATCH 03/11] =?UTF-8?q?=E5=BC=B9=E5=B9=95=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 24 +- .../ctyun/player/activity/DemoActivity.java | 46 +- .../ctyun/videoplayer/bean/DanmakuDetail.java | 50 +++ .../ctyun/videoplayer/bean/DanmakuModel.java | 25 ++ .../videoplayer/bean/FloatingComment.java | 23 - .../videoplayer/player/IjkVideoView.java | 2 +- .../videoplayer/widget/DanmakuVideoView.java | 398 ++++++++---------- sdk_api.md | 4 +- 8 files changed, 306 insertions(+), 266 deletions(-) create mode 100644 player/src/main/java/cn/ctyun/videoplayer/bean/DanmakuDetail.java create mode 100644 player/src/main/java/cn/ctyun/videoplayer/bean/DanmakuModel.java delete mode 100644 player/src/main/java/cn/ctyun/videoplayer/bean/FloatingComment.java diff --git a/README.md b/README.md index 6c22d04..02f9d41 100644 --- a/README.md +++ b/README.md @@ -110,22 +110,22 @@ android { // 设置播放器id mVideoView.setVideoId("asdasdasdads"); - List floatingComments = new ArrayList<>(); - FloatingComment floatingComment = new FloatingComment(); - floatingComment.setText("啊啊啊啊啊啊啊啊啊啊啊啊"); - floatingComments.add(floatingComment); - FloatingComment floatingComment2 = new FloatingComment(); - floatingComment2.setText("dsadasdsadadssd"); - floatingComments.add(floatingComment2); + List danmakuDetails = new ArrayList<>(); + FloatingComment danmakuDetail = new FloatingComment(); + danmakuDetail.setText("啊啊啊啊啊啊啊啊啊啊啊啊"); + danmakuDetails.add(danmakuDetail); + FloatingComment danmakuDetail2 = new FloatingComment(); + danmakuDetail2.setText("dsadasdsadadssd"); + danmakuDetails.add(danmakuDetail2); // for (int i=0; i<200; i++) { - // floatingComment = new FloatingComment(); - // floatingComment.setText("这是一条弹幕"+i); - // floatingComments.add(floatingComment); + // danmakuDetail = new FloatingComment(); + // danmakuDetail.setText("这是一条弹幕"+i); + // danmakuDetails.add(danmakuDetail); // } // 启用弹幕,进入播放器不展示弹幕 - mVideoView.enableDanmaku(floatingComments); + mVideoView.enableDanmaku(danmakuDetails); // 启用弹幕,进入播放器就展示弹幕 - // mVideoView.enableDanmaku(floatingComments, true); + // mVideoView.enableDanmaku(danmakuDetails, true); // 启用投屏 mVideoView.enableDLNA(); diff --git a/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java b/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java index 8888fc5..d9a5129 100644 --- a/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java +++ b/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java @@ -7,16 +7,15 @@ import android.util.Log; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.FrameLayout; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import cn.ctyun.player.R; -import cn.ctyun.videoplayer.bean.FloatingComment; +import cn.ctyun.videoplayer.bean.DanmakuDetail; +import cn.ctyun.videoplayer.bean.DanmakuModel; import cn.ctyun.videoplayer.bean.VideoModel; -import cn.ctyun.videoplayer.interf.AdControllerListener; import cn.ctyun.videoplayer.player.PlayerConfig; import cn.ctyun.videoplayer.util.Constants; import cn.ctyun.videoplayer.util.MemoryLeakUtil; @@ -67,7 +66,7 @@ public class DemoActivity extends AppCompatActivity{ mVideoView.setPlayerConfig(new PlayerConfig.Builder() .autoRotate() // 自动旋转屏幕 .enableMediaCodec() // 启动硬解码 - .savingProgress() // 保存播放进度 +// .savingProgress() // 保存播放进度 .build()); // 可选:设置暂停广告 @@ -94,22 +93,37 @@ public class DemoActivity extends AppCompatActivity{ // 设置播放器id mVideoView.setVideoId("asdasdasdads"); - List floatingComments = new ArrayList<>(); - FloatingComment floatingComment = new FloatingComment(); - floatingComment.setText("啊啊啊啊啊啊啊啊啊啊啊啊"); - floatingComments.add(floatingComment); - FloatingComment floatingComment2 = new FloatingComment(); - floatingComment2.setText("dsadasdsadadssd"); - floatingComments.add(floatingComment2); + DanmakuModel danmakuModel = new DanmakuModel(); + List danmakuDetails = new ArrayList<>(); + danmakuModel.setDanmakuDetails(danmakuDetails); + danmakuModel.setScrollSpeed(1.2f); + DanmakuDetail danmakuDetail = new DanmakuDetail(); + danmakuDetail.setType(1); + danmakuDetail.setRelativeTime(3.0f); + danmakuDetail.setText("啊啊啊啊啊啊啊啊啊啊啊啊"); + danmakuDetail.setColor(16777215); + danmakuDetails.add(danmakuDetail); + DanmakuDetail danmakuDetail3 = new DanmakuDetail(); + danmakuDetail3.setType(4); + danmakuDetail3.setRelativeTime(3.5f); + danmakuDetail3.setText("弹幕来啦~~~~"); + danmakuDetail3.setColor(16711680); + danmakuDetails.add(danmakuDetail3); + DanmakuDetail danmakuDetail2 = new DanmakuDetail(); + danmakuDetail2.setType(5); + danmakuDetail2.setRelativeTime(6.0f); + danmakuDetail2.setText("dsadasdsadadssd"); + danmakuDetail2.setColor(16776960); + danmakuDetails.add(danmakuDetail2); // for (int i=0; i<200; i++) { -// floatingComment = new FloatingComment(); -// floatingComment.setText("这是一条弹幕"+i); -// floatingComments.add(floatingComment); +// danmakuDetail = new DanmakuDetail(); +// danmakuDetail.setText("这是一条弹幕"+i); +// danmakuDetails.add(danmakuDetail); // } // 启用弹幕,进入播放器不展示弹幕 - mVideoView.enableDanmaku(floatingComments); +// mVideoView.enableDanmaku(danmakuModel); // 启用弹幕,进入播放器就展示弹幕 -// mVideoView.enableDanmaku(floatingComments, true); + mVideoView.enableDanmaku(danmakuModel, true); // 启用投屏 mVideoView.enableDLNA(); // 自动播放 diff --git a/player/src/main/java/cn/ctyun/videoplayer/bean/DanmakuDetail.java b/player/src/main/java/cn/ctyun/videoplayer/bean/DanmakuDetail.java new file mode 100644 index 0000000..53bec09 --- /dev/null +++ b/player/src/main/java/cn/ctyun/videoplayer/bean/DanmakuDetail.java @@ -0,0 +1,50 @@ +package cn.ctyun.videoplayer.bean; + +public class DanmakuDetail { + + private int type; // 弹幕类型:1滚动弹幕、4底端弹幕、5顶端弹幕 + private float relativeTime; // 弹幕发送相对视频的时间 + private String text; // 文字 + private int color; // 十进制颜色 + private int fontSize; // 12非常小,16特小,18小,25中,36大,45很大,64特别大【默认是25】 + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public int getColor() { + return color; + } + + public void setColor(int color) { + this.color = color; + } + + public float getRelativeTime() { + return relativeTime; + } + + public void setRelativeTime(float relativeTime) { + this.relativeTime = relativeTime; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public int getFontSize() { + return fontSize; + } + + public void setFontSize(int fontSize) { + this.fontSize = fontSize; + } +} diff --git a/player/src/main/java/cn/ctyun/videoplayer/bean/DanmakuModel.java b/player/src/main/java/cn/ctyun/videoplayer/bean/DanmakuModel.java new file mode 100644 index 0000000..f84a731 --- /dev/null +++ b/player/src/main/java/cn/ctyun/videoplayer/bean/DanmakuModel.java @@ -0,0 +1,25 @@ +package cn.ctyun.videoplayer.bean; + +import java.util.List; + +public class DanmakuModel { + + private float scrollSpeed; + private List danmakuDetails; + + public float getScrollSpeed() { + return scrollSpeed; + } + + public void setScrollSpeed(float scrollSpeed) { + this.scrollSpeed = scrollSpeed; + } + + public List getDanmakuDetails() { + return danmakuDetails; + } + + public void setDanmakuDetails(List danmakuDetails) { + this.danmakuDetails = danmakuDetails; + } +} diff --git a/player/src/main/java/cn/ctyun/videoplayer/bean/FloatingComment.java b/player/src/main/java/cn/ctyun/videoplayer/bean/FloatingComment.java deleted file mode 100644 index c5a7567..0000000 --- a/player/src/main/java/cn/ctyun/videoplayer/bean/FloatingComment.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.ctyun.videoplayer.bean; - -public class FloatingComment { - - private String text; - private String color; - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public String getColor() { - return color; - } - - public void setColor(String color) { - this.color = color; - } -} diff --git a/player/src/main/java/cn/ctyun/videoplayer/player/IjkVideoView.java b/player/src/main/java/cn/ctyun/videoplayer/player/IjkVideoView.java index 2440d7e..1ece9a6 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/player/IjkVideoView.java +++ b/player/src/main/java/cn/ctyun/videoplayer/player/IjkVideoView.java @@ -643,7 +643,7 @@ public class IjkVideoView extends BaseIjkVideoView { // * 设置播放速度 // * @param speed // */ -// public void setSpeed(float speed) { +// public void setScrollSpeed(float speed) { // // } // diff --git a/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java b/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java index 52cb971..f5e27e7 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java +++ b/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java @@ -7,11 +7,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; -import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Paint; import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Handler; @@ -19,8 +16,6 @@ import android.os.IBinder; import android.os.Message; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.text.Spanned; -import android.text.TextPaint; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -38,6 +33,7 @@ import android.widget.Toast; import org.fourthline.cling.model.meta.Device; +import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; @@ -46,7 +42,8 @@ import java.util.List; import cn.ctyun.videoplayer.R; import cn.ctyun.videoplayer.adapter.DLNADevicesAdapter; -import cn.ctyun.videoplayer.bean.FloatingComment; +import cn.ctyun.videoplayer.bean.DanmakuDetail; +import cn.ctyun.videoplayer.bean.DanmakuModel; import cn.ctyun.videoplayer.controller.DLNAControllerInterface; import cn.ctyun.videoplayer.controller.DanmakuControllerInterface; import cn.ctyun.videoplayer.controller.StandardVideoController; @@ -74,10 +71,8 @@ import master.flame.danmaku.danmaku.model.BaseDanmaku; import master.flame.danmaku.danmaku.model.DanmakuTimer; import master.flame.danmaku.danmaku.model.IDanmakus; import master.flame.danmaku.danmaku.model.IDisplayer; -import master.flame.danmaku.danmaku.model.android.BaseCacheStuffer; import master.flame.danmaku.danmaku.model.android.DanmakuContext; import master.flame.danmaku.danmaku.model.android.Danmakus; -import master.flame.danmaku.danmaku.model.android.SpannedCacheStuffer; import master.flame.danmaku.danmaku.parser.BaseDanmakuParser; import master.flame.danmaku.danmaku.parser.IDataSource; import master.flame.danmaku.ui.widget.DanmakuView; @@ -93,7 +88,7 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro private boolean mDanmakuEnable; // 是否初始化显示弹幕 private boolean mIsShowDanmakuInit; - private List mFloatingComments; +// private List mDanmakuDetails; // 弹幕视图 private DanmakuView mDanmakuView; // 弹幕控制相关 @@ -207,14 +202,14 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro if (mDLNAEnable) { - mHandler.removeCallbacksAndMessages(null); - // Unbind UPnP service - mContext.unbindService(mUpnpServiceConnection); - mContext.unregisterReceiver(mTransportStateBroadcastReceiver); - mBrowseRegistryListener.setOnDeviceListChangedListener(null); - - ClingManager.getInstance().destroy(); - ClingDeviceList.getInstance().destroy(); + mHandler.removeCallbacksAndMessages(null); + // Unbind UPnP service + mContext.unbindService(mUpnpServiceConnection); + mContext.unregisterReceiver(mTransportStateBroadcastReceiver); + mBrowseRegistryListener.setOnDeviceListChangedListener(null); + + ClingManager.getInstance().destroy(); + ClingDeviceList.getInstance().destroy(); // MemoryLeakUtil.fixLeak(this); } mContext = null; @@ -229,101 +224,114 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro } } - public void initDanMuView() { + public void initDanMuView() { - if (mVideoController instanceof DanmakuController) { - ((DanmakuController)mVideoController).selectDanmakuControl(true); - } + if (mVideoController instanceof DanmakuController) { + ((DanmakuController) mVideoController).selectDanmakuControl(true); + } - // 设置最大显示行数 - HashMap maxLinesPair = new HashMap(); - maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 5); // 滚动弹幕最大显示5行 - // 设置是否禁止重叠 - HashMap overlappingEnablePair = new HashMap(); - overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true); - overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true); - -// mDanmakuView = (IDanmakuView) findViewById(R.id.sv_danmaku); - mDanmakuView = new DanmakuView(getContext()); - mDanmakuContext = DanmakuContext.create(); - mDanmakuContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 3) - .setDuplicateMergingEnabled(false) + // 设置最大显示行数 + HashMap maxLinesPair = new HashMap(); + maxLinesPair.put(BaseDanmaku.TYPE_SCROLL_RL, 5); // 滚动弹幕最大显示5行 + // 设置是否禁止重叠 + HashMap overlappingEnablePair = new HashMap(); + overlappingEnablePair.put(BaseDanmaku.TYPE_SCROLL_RL, true); + overlappingEnablePair.put(BaseDanmaku.TYPE_FIX_TOP, true); + + mDanmakuView = new DanmakuView(getContext()); + mDanmakuContext = DanmakuContext.create(); + mDanmakuContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 3) + .setDuplicateMergingEnabled(false) // .setScrollSpeedFactor(1.2f) -// .setScaleTextSize(1.2f) +// .setScaleTextSize(1.8f) // .setCacheStuffer(new BackgroundCacheStuffer(), mCacheStufferAdapter) // 图文混排使用SpannedCacheStuffer // .setCacheStuffer(new BackgroundCacheStuffer()) // 绘制背景使用BackgroundCacheStuffer - .setMaximumLines(maxLinesPair) - .preventOverlapping(overlappingEnablePair).setDanmakuMargin(40); - if (mDanmakuView != null) { - mDanmakuParser = createParser(this.getResources().openRawResource(R.raw.bili)); -// mDanmakuParser = createParser(null); - mDanmakuView.setCallback(new master.flame.danmaku.controller.DrawHandler.Callback() { - @Override - public void updateTimer(DanmakuTimer timer) { - } + .setMaximumLines(maxLinesPair) + .preventOverlapping(overlappingEnablePair).setDanmakuMargin(40); + if (mDanmakuView != null) { +// mDanmakuParser = createParser(this.getResources().openRawResource(R.raw.commentstest)); + mDanmakuView.setCallback(new master.flame.danmaku.controller.DrawHandler.Callback() { + @Override + public void updateTimer(DanmakuTimer timer) { + } - @Override - public void drawingFinished() { + @Override + public void drawingFinished() { - } + } - @Override - public void danmakuShown(BaseDanmaku danmaku) { + @Override + public void danmakuShown(BaseDanmaku danmaku) { // Log.d("DFM", "danmakuShown(): text=" + danmaku.text); - } + } - @Override - public void prepared() { - mDanmakuView.start(); - if (mFloatingComments != null && mFloatingComments.size() > 0) { - for (FloatingComment floatingComment : mFloatingComments) { - sendDanmu(1, floatingComment.getText(), 60f, -1, false); - } - } - } - }); - mDanmakuView.setOnDanmakuClickListener(new IDanmakuView.OnDanmakuClickListener() { - - @Override - public boolean onDanmakuClick(IDanmakus danmakus) { - Log.d("DFM", "onDanmakuClick: danmakus size:" + danmakus.size()); - BaseDanmaku latest = danmakus.last(); - if (null != latest) { - Log.d("DFM", "onDanmakuClick: text of latest danmaku:" + latest.text); - return true; - } - return false; - } + @Override + public void prepared() { + mDanmakuView.start(); +// if (mDanmakuDetails != null && mDanmakuDetails.size() > 0) { +// for (DanmakuDetail floatingComment : mDanmakuDetails) { +// sendDanmu(1, floatingComment.getText(), 60f, -1, false); +// } +// } + } + }); + mDanmakuView.setOnDanmakuClickListener(new IDanmakuView.OnDanmakuClickListener() { - @Override - public boolean onDanmakuLongClick(IDanmakus danmakus) { - return false; + @Override + public boolean onDanmakuClick(IDanmakus danmakus) { + Log.d("DFM", "onDanmakuClick: danmakus size:" + danmakus.size()); + BaseDanmaku latest = danmakus.last(); + if (null != latest) { + Log.d("DFM", "onDanmakuClick: text of latest danmaku:" + latest.text); + return true; } + return false; + } + + @Override + public boolean onDanmakuLongClick(IDanmakus danmakus) { + return false; + } - @Override - public boolean onViewClick(IDanmakuView view) { + @Override + public boolean onViewClick(IDanmakuView view) { // mMediaController.setVisibility(View.VISIBLE); - return false; - } - }); + return false; + } + }); // mDanmakuView.prepare(mDanmakuParser, mDanmakuContext); // mDanmakuView.showFPS(true); - mDanmakuView.enableDanmakuDrawingCache(true); - } + mDanmakuView.enableDanmakuDrawingCache(true); + } } - public void enableDanmaku(List floatingComments) { + public void enableDanmaku(DanmakuModel danmakuModel) { mDanmakuEnable = true; - mFloatingComments = floatingComments; + if (danmakuModel != null) { +// mDanmakuDetails = danmakuModel.getDanmakuDetails(); + transFloatingComments(danmakuModel.getDanmakuDetails()); + if (danmakuModel.getScrollSpeed() > 0.0 && mDanmakuContext != null) { + mDanmakuContext.setScrollSpeedFactor(danmakuModel.getScrollSpeed()); + } + } + mIsShowDanmakuInit = false; // 默认关闭弹幕 if (mVideoController instanceof DanmakuController) { ((DanmakuController) mVideoController).enableDanmaku(); } } - public void enableDanmaku(List floatingComments, boolean showDanmakuInit) { + public void enableDanmaku(DanmakuModel danmakuModel, boolean showDanmakuInit) { mDanmakuEnable = true; + if (danmakuModel != null) { +// mDanmakuDetails = danmakuModel.getDanmakuDetails(); + transFloatingComments(danmakuModel.getDanmakuDetails()); + if (danmakuModel.getScrollSpeed() > 0.0 && mDanmakuContext != null) { + mDanmakuContext.setScrollSpeedFactor(danmakuModel.getScrollSpeed()); + } + } + mIsShowDanmakuInit = showDanmakuInit; if (mVideoController instanceof DanmakuController) { ((DanmakuController) mVideoController).enableDanmaku(); @@ -333,6 +341,18 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro } } + private void transFloatingComments(List danmakuDetails) { + if (danmakuDetails == null || danmakuDetails.size() < 1) { + return; + } + String xmlNodes = parseNodeToXML(danmakuDetails); + if (xmlNodes != null && xmlNodes.length() > 0) { + mDanmakuParser = createParser(new ByteArrayInputStream(xmlNodes.getBytes())); + } else { + mDanmakuParser = createParser(null); + } + } + private BaseDanmakuParser createParser(InputStream stream) { if (stream == null) { @@ -359,80 +379,6 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro } -// private BaseCacheStuffer.Proxy mCacheStufferAdapter = new BaseCacheStuffer.Proxy() { -// -// private Drawable mDrawable; -// -// @Override -// public void prepareDrawing(final BaseDanmaku danmaku, boolean fromWorkerThread) { -// if (danmaku.text instanceof Spanned) { // 根据你的条件检查是否需要需要更新弹幕 -// // FIXME 这里只是简单启个线程来加载远程url图片,请使用你自己的异步线程池,最好加上你的缓存池 -// new Thread() { -// -// @Override -// public void run() { -//// String url = "http://www.bilibili.com/favicon.ico"; -//// InputStream inputStream = null; -//// Drawable drawable = mDrawable; -//// if(drawable == null) { -//// try { -//// URLConnection urlConnection = new URL(url).openConnection(); -//// inputStream = urlConnection.getInputStream(); -//// drawable = BitmapDrawable.createFromStream(inputStream, "bitmap"); -//// mDrawable = drawable; -//// } catch (MalformedURLException e) { -//// e.printStackTrace(); -//// } catch (IOException e) { -//// e.printStackTrace(); -//// } finally { -//// IOUtils.closeQuietly(inputStream); -//// } -//// } -//// if (drawable != null) { -//// drawable.setBounds(0, 0, 100, 100); -//// SpannableStringBuilder spannable = createSpannable(drawable); -//// danmaku.text = spannable; -//// if(mDanmakuView != null) { -//// mDanmakuView.invalidateDanmaku(danmaku, false); -//// } -//// return; -//// } -// } -// }.start(); -// } -// } -// -// @Override -// public void releaseResource(BaseDanmaku danmaku) { -// // TODO 重要:清理含有ImageSpan的text中的一些占用内存的资源 例如drawable -// } -// }; - - /** - * 绘制背景(自定义弹幕样式) - */ - private static class BackgroundCacheStuffer extends SpannedCacheStuffer { - // 通过扩展SimpleTextCacheStuffer或SpannedCacheStuffer个性化你的弹幕样式 - final Paint paint = new Paint(); - - @Override - public void measure(BaseDanmaku danmaku, TextPaint paint, boolean fromWorkerThread) { - danmaku.padding = 10; // 在背景绘制模式下增加padding - super.measure(danmaku, paint, fromWorkerThread); - } - - @Override - public void drawBackground(BaseDanmaku danmaku, Canvas canvas, float left, float top) { -// paint.setColor(0x8125309b); - canvas.drawRect(left + 2, top + 2, left + danmaku.paintWidth - 2, top + danmaku.paintHeight - 2, paint); - } - - @Override - public void drawStroke(BaseDanmaku danmaku, String lineText, Canvas canvas, float left, float top, Paint paint) { - // 禁用描边绘制 - } - } - /** * 发射弹幕 * @@ -441,7 +387,7 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro * @return 弹幕数据 */ @Override - public void sendDanmu(int danmakuType, String text, float danmakuTextSize, int danmakuTextColor, boolean isLive) { + public void sendDanmu(int danmakuType, String text, float textSize, int textColor, boolean isLive) { // if (!mIsEnableDanmaku) { // throw new RuntimeException("Danmaku is disable, use enableDanmaku() first"); // } @@ -462,8 +408,8 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro danmaku.padding = 5; danmaku.isLive = isLive; danmaku.priority = 0; // 可能会被各种过滤器过滤并隐藏显示 - danmaku.textSize = danmakuTextSize; - danmaku.textColor = danmakuTextColor; + danmaku.textSize = textSize; + danmaku.textColor = textColor; danmaku.underlineColor = Color.GREEN; danmaku.setTime(mDanmakuView.getCurrentTime() + 500); mDanmakuView.addDanmaku(danmaku); @@ -498,21 +444,29 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro } - - - - - /** 连接设备状态: 播放状态 */ + /** + * 连接设备状态: 播放状态 + */ public static final int PLAY_ACTION = 0xa1; - /** 连接设备状态: 暂停状态 */ + /** + * 连接设备状态: 暂停状态 + */ public static final int PAUSE_ACTION = 0xa2; - /** 连接设备状态: 停止状态 */ + /** + * 连接设备状态: 停止状态 + */ public static final int STOP_ACTION = 0xa3; - /** 连接设备状态: 转菊花状态 */ + /** + * 连接设备状态: 转菊花状态 + */ public static final int TRANSITIONING_ACTION = 0xa4; - /** 获取进度 */ + /** + * 获取进度 + */ public static final int GET_POSITION_INFO_ACTION = 0xa5; //todo 和ERROR_ACTION值重复了 - /** 投放失败 */ + /** + * 投放失败 + */ public static final int ERROR_ACTION = 0xa5; private Context mContext; @@ -534,7 +488,9 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro private static ClingPlayControl mClingPlayControl = new ClingPlayControl(); - /** 用于监听发现设备 */ + /** + * 用于监听发现设备 + */ private BrowseRegistryListener mBrowseRegistryListener = new BrowseRegistryListener(); private ServiceConnection mUpnpServiceConnection = new ServiceConnection() { @Override @@ -649,16 +605,15 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro } - private void initDevicePopView() { - mPopLayout = (LinearLayout) LayoutInflater.from((Activity)mContext).inflate(R.layout.layout_dlna_devices_pop, null); - mPopupWindow = new PopupWindow(mPopLayout, (int)getResources().getDimension(R.dimen.dlna_pop_width), ViewGroup.LayoutParams.WRAP_CONTENT, true); + mPopLayout = (LinearLayout) LayoutInflater.from((Activity) mContext).inflate(R.layout.layout_dlna_devices_pop, null); + mPopupWindow = new PopupWindow(mPopLayout, (int) getResources().getDimension(R.dimen.dlna_pop_width), ViewGroup.LayoutParams.WRAP_CONTENT, true); mPopupWindow.setBackgroundDrawable(new ColorDrawable(0xaaffffff)); mPopupWindow.setOutsideTouchable(true); mPopupWindow.setClippingEnabled(false); mDeviceList = mPopLayout.findViewById(R.id.dlna_lv_devices); - mDeviceList.addHeaderView(new View(mContext)); + mDeviceList.addHeaderView(new View(mContext)); // mDeviceList.addFooterView(new View(mContext)); //mBottomDivider = mPopLayout.findViewById(R.id.dlna_bottom_divider); @@ -667,8 +622,8 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro mIvDLNAPopClose = mPopLayout.findViewById(R.id.dlna_iv_pop_close); mTVWifiName = mPopLayout.findViewById(R.id.dlna_tv_wifi_name); - mLLSearching = mPopLayout.findViewById(R.id.dlna_ll_search_devices_prompt); - mTVResearch = mPopLayout.findViewById(R.id.dlna_tv_refresh_devices); + mLLSearching = mPopLayout.findViewById(R.id.dlna_ll_search_devices_prompt); + mTVResearch = mPopLayout.findViewById(R.id.dlna_tv_refresh_devices); mIvDLNAPopClose.setOnClickListener(this); mTVResearch.setOnClickListener(this); @@ -693,7 +648,7 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro } - Log.d(TAG, "***************** onItemClick name="+device.getDetails().getFriendlyName()); + Log.d(TAG, "***************** onItemClick name=" + device.getDetails().getFriendlyName()); playDLNA(); //mDevicesAdapter.setConnectedDevice(mSelectedDevice.getDevice()); } @@ -703,7 +658,7 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro mBrowseRegistryListener.setOnDeviceListChangedListener(new DeviceListChangedListener() { @Override public void onDeviceAdded(final IDevice device) { - ((Activity)mContext).runOnUiThread(new Runnable() { + ((Activity) mContext).runOnUiThread(new Runnable() { public void run() { mDevicesAdapter.add((ClingDevice) device); } @@ -712,7 +667,7 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro @Override public void onDeviceRemoved(final IDevice device) { - ((Activity)mContext).runOnUiThread(new Runnable() { + ((Activity) mContext).runOnUiThread(new Runnable() { public void run() { mDevicesAdapter.remove((ClingDevice) device); } @@ -724,7 +679,7 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro private void refreshDeviceList() { Collection devices = ClingManager.getInstance().getDmrDevices(); ClingDeviceList.getInstance().setClingDeviceList(devices); - Log.d(TAG, "refreshDeviceList() devices="+devices); + Log.d(TAG, "refreshDeviceList() devices=" + devices); mDevicesAdapter.clear(); if (devices != null) { ClingDeviceList.getInstance().setClingDeviceList(devices); @@ -741,17 +696,17 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro ConnectivityManager ctm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = ctm.getActiveNetworkInfo(); String ssid = networkInfo.getExtraInfo(); - mTVWifiName.setText(ssid.substring(1, ssid.length()-1)); + mTVWifiName.setText(ssid.substring(1, ssid.length() - 1)); } private void showDevicesPop() { Log.d(TAG, "showDevicesPop()"); //下面measure操作会导致Android 8.0以上手机弹出框第二次显示时listitem不加载 //mPopLayout.measure(View.MeasureSpec.AT_MOST, View.MeasureSpec.UNSPECIFIED); - mPopupWindow.setWidth((int)getResources().getDimension(R.dimen.dlna_pop_width)); - mPopupWindow.showAtLocation(((Activity)mContext).getWindow().getDecorView(), Gravity.CENTER, 0, 0); - Log.e(TAG, "showDevicesPop getDimension="+ getResources().getDimension(R.dimen.dlna_pop_width) - +" mPopupWindow="+mPopupWindow.getWidth()); + mPopupWindow.setWidth((int) getResources().getDimension(R.dimen.dlna_pop_width)); + mPopupWindow.showAtLocation(((Activity) mContext).getWindow().getDecorView(), Gravity.CENTER, 0, 0); + Log.e(TAG, "showDevicesPop getDimension=" + getResources().getDimension(R.dimen.dlna_pop_width) + + " mPopupWindow=" + mPopupWindow.getWidth()); } private void stopDLNA() { @@ -785,7 +740,7 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro @Override public void success(IResponse response) { Log.e(TAG, "playNew success"); - ((Activity)mContext).runOnUiThread(new Runnable() { + ((Activity) mContext).runOnUiThread(new Runnable() { @Override public void run() { mPopupWindow.dismiss(); @@ -797,10 +752,10 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro Log.e(TAG, "playNew success pause and show connected view"); // if (isPlaying()) { - mMediaPlayer.pause(); - setPlayState(STATE_DLNA_CONNECTED); + mMediaPlayer.pause(); + setPlayState(STATE_DLNA_CONNECTED); ((DanmakuController) mVideoController).setDLNADisableGesture(true); - setKeepScreenOn(false); + setKeepScreenOn(false); // if (mAudioFocusHelper != null) // mAudioFocusHelper.abandonFocus(); // } @@ -825,7 +780,7 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro @Override public void success(IResponse response) { Log.e(TAG, "play success"); - ((Activity)mContext).runOnUiThread(new Runnable() { + ((Activity) mContext).runOnUiThread(new Runnable() { @Override public void run() { mPopupWindow.dismiss(); @@ -836,10 +791,10 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro Log.e(TAG, "play success pause and show connected view"); // if (isPlaying()) { - mMediaPlayer.pause(); - setPlayState(STATE_DLNA_CONNECTED); + mMediaPlayer.pause(); + setPlayState(STATE_DLNA_CONNECTED); ((DanmakuController) mVideoController).setDLNADisableGesture(true); - setKeepScreenOn(false); + setKeepScreenOn(false); // if (mAudioFocusHelper != null) // mAudioFocusHelper.abandonFocus(); // } @@ -860,21 +815,20 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro } - @Override public void onClick(View v) { - int i = v.getId(); - if (i == R.id.dlna_iv_pop_close) { - mPopupWindow.dismiss(); - } else if (i == R.id.dlna_tv_refresh_devices) { + int i = v.getId(); + if (i == R.id.dlna_iv_pop_close) { + mPopupWindow.dismiss(); + } else if (i == R.id.dlna_tv_refresh_devices) { mDevicesAdapter.clear(); - ClingManager.getInstance().searchDevices(); - mDeviceList.setEnabled(false); + ClingManager.getInstance().searchDevices(); + mDeviceList.setEnabled(false); - //todo 需要添加延时(刷新太快,看不到刷新过程) - refreshDeviceList(); - mDeviceList.setEnabled(true); - } + //todo 需要添加延时(刷新太快,看不到刷新过程) + refreshDeviceList(); + mDeviceList.setEnabled(true); + } } @@ -941,11 +895,31 @@ public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuContro return mDLNAEnable; } - public List getFloatingComments() { - return mFloatingComments; - } +// public List getFloatingComments() { +// return mDanmakuDetails; +// } +// +// public void setFloatingComments(List mDanmakuDetails) { +// this.mDanmakuDetails = mDanmakuDetails; +// } + + public String parseNodeToXML(List danmakuDetails) { + StringBuffer xmlnodes = new StringBuffer(); + if (danmakuDetails != null && danmakuDetails.size() > 0) { + xmlnodes.append(""); + xmlnodes.append(""); + for (int i = 0; i < danmakuDetails.size(); i++) { + DanmakuDetail danmakuDetail = danmakuDetails.get(i); + int type = danmakuDetail.getType() > 0 ? danmakuDetail.getType() : 1; + int fontSize = danmakuDetail.getFontSize() > 0 ? danmakuDetail.getFontSize() : 25; + xmlnodes.append("" + danmakuDetail.getText() + ""); + } + xmlnodes.append(""); + } - public void setFloatingComments(List mFloatingComments) { - this.mFloatingComments = mFloatingComments; + return xmlnodes.toString(); } } diff --git a/sdk_api.md b/sdk_api.md index 3fe2558..99231ad 100644 --- a/sdk_api.md +++ b/sdk_api.md @@ -110,7 +110,7 @@ 退出全屏播放 -### player.setSpeed(speed: float) => null +### player.setSpeed(scrollSpeed: float) => null 设置播放的速度 @@ -126,7 +126,7 @@ "fontSize": "auto", "opacity": 1 }, - "speed": 1 + "scrollSpeed": 1 } ``` -- Gitee From f939709a3bd53b858c9dd56be356cef562d43b47 Mon Sep 17 00:00:00 2001 From: liujt Date: Fri, 22 Mar 2019 15:21:14 +0800 Subject: [PATCH 04/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B0=B4=E5=8D=B0?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=9B=E5=A2=9E=E5=8A=A0m3u8=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=A6=BB=E7=BA=BF=E7=BC=93=E5=AD=98=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E6=B5=8B=E8=AF=95=E4=B8=AD=EF=BC=8C=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E5=AE=8C=E5=85=A8=E6=90=9E=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 1 + .../ctyun/player/activity/DemoActivity.java | 18 ++- build.gradle | 8 +- gradle.properties | 4 +- player/build.gradle | 1 + ...a => BaseMediaPlayerControlInterface.java} | 11 +- .../controller/BaseVideoController.java | 22 ++- ...va => DanmakuControllerInterfaceBase.java} | 2 +- .../controller/StandardVideoController.java | 50 ++++++- ...DefinitionMediaPlayerControlInterface.java | 4 +- ....java => MediaPlayerControlInterface.java} | 6 +- .../videoplayer/player/BaseIjkVideoView.java | 28 +++- .../{Constants.java => PlayerConstants.java} | 9 +- .../videoplayer/util/VideoCacheManager.java | 2 +- .../videoplayer/widget/CacheIjkVideoView.java | 133 ++++++++++++++++-- .../videoplayer/widget/DanmakuVideoView.java | 4 +- .../ctyun/videoplayer/widget/VideoView.java | 61 ++++++-- .../widget/controller/AdController.java | 10 +- .../widget/controller/DanmakuController.java | 20 +-- .../main/res/drawable/shape_watermark_bg.xml | 6 + .../dkplayer_layout_standard_controller.xml | 15 ++ player/src/main/res/values/styles.xml | 10 ++ 22 files changed, 356 insertions(+), 69 deletions(-) rename player/src/main/java/cn/ctyun/videoplayer/controller/{MediaPlayerControlInterface.java => BaseMediaPlayerControlInterface.java} (85%) rename player/src/main/java/cn/ctyun/videoplayer/controller/{DanmakuControllerInterface.java => DanmakuControllerInterfaceBase.java} (74%) rename player/src/main/java/cn/ctyun/videoplayer/interf/{ListMediaPlayerControlInterface.java => MediaPlayerControlInterface.java} (64%) rename player/src/main/java/cn/ctyun/videoplayer/util/{Constants.java => PlayerConstants.java} (52%) create mode 100644 player/src/main/res/drawable/shape_watermark_bg.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ac003eb..8bd071e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,6 +20,7 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/my_app_name" + tools:replace="android:label" android:supportsRtl="true" android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> diff --git a/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java b/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java index d9a5129..5c16878 100644 --- a/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java +++ b/app/src/main/java/cn/ctyun/player/activity/DemoActivity.java @@ -17,17 +17,18 @@ import cn.ctyun.videoplayer.bean.DanmakuDetail; import cn.ctyun.videoplayer.bean.DanmakuModel; import cn.ctyun.videoplayer.bean.VideoModel; import cn.ctyun.videoplayer.player.PlayerConfig; -import cn.ctyun.videoplayer.util.Constants; +import cn.ctyun.videoplayer.util.PlayerConstants; import cn.ctyun.videoplayer.util.MemoryLeakUtil; import cn.ctyun.videoplayer.widget.VideoView; public class DemoActivity extends AppCompatActivity{ - private static final String TAG = "CHL_" + DemoActivity.class.getSimpleName(); + private static final String TAG = DemoActivity.class.getSimpleName(); private VideoView mVideoView; private static final String URL_VOD = "http://mov.bn.netease.com/open-movie/nos/flv/2017/01/03/SC8U8K7BC_hd.flv"; // private static final String URL_VOD = "http://vfile.hshan.com/2018/1524/9156/4430/152491564430.ssm/152491564430.m3u8"; +// private static final String URL_VOD = "http://vfile.hshan.com/2018/1524/9156/4430/152491564430.ssm/152491564430_0_11040000.ts?seq=0&vc=0&ac=206"; // private static final String URL_VOD = "http://baobab.wdjcdn.com/14564977406580.mp4"; // private static final String URL_VOD = "http://uploads.cutv.com:8088/video/data/201703/10/encode_file/515b6a95601ba6b39620358f2677a17358c2472411d53.mp4"; private static final String URL_AD = "https://gslb.miaopai.com/stream/IR3oMYDhrON5huCmf7sHCfnU5YKEkgO2.mp4"; @@ -60,32 +61,33 @@ public class DemoActivity extends AppCompatActivity{ int widthPixels = getResources().getDisplayMetrics().widthPixels; ViewGroup.LayoutParams layoutParams = mVideoView.getLayoutParams(); layoutParams.height = widthPixels / 16 * 9; -// mVideoView.setLayoutParams(new ViewGroup.LayoutParams(widthPixels, widthPixels / 16 * 9)); // 可选:播放器相关配置,其他配置参照类PlayerConfig mVideoView.setPlayerConfig(new PlayerConfig.Builder() .autoRotate() // 自动旋转屏幕 .enableMediaCodec() // 启动硬解码 -// .savingProgress() // 保存播放进度 + .savingProgress() // 保存播放进度 .build()); // 可选:设置暂停广告 mVideoView.setPauseAd(pauseAdUrl); // 设置海报 mVideoView.setThumbUrl(pauseAdUrl2); + // 设置水印 + mVideoView.setWatermarkText("我的水印", PlayerConstants.WatermarkTextPosition.BOTTOM_RIGHT); // 必选:设置播放源 List videos = new ArrayList<>(); // 片头广告 -// videos.add(new VideoModel(URL_AD, "", Constants.VIDEO_TYPE_START_AD, new AdControllerListener() { +// videos.add(new VideoModel(URL_AD, "", PlayerConstants.VIDEO_TYPE_START_AD, new AdControllerListener() { // @Override // public void onAdClick() { // Toast.makeText(DemoActivity.this, "广告点击跳转", Toast.LENGTH_SHORT).show(); // } // })); - videos.add(new VideoModel(URL_VOD, "这是一个标题", Constants.VIDEO_TYPE_VOD)); + videos.add(new VideoModel(URL_VOD, "这是一个标题", PlayerConstants.VIDEO_TYPE_VOD)); // 片尾广告 -// videos.add(new VideoModel(URL_AD, "", Constants.VIDEO_TYPE_END_AD)); +// videos.add(new VideoModel(URL_AD, "", PlayerConstants.VIDEO_TYPE_END_AD)); mVideoView.setVideos(videos); @@ -93,6 +95,8 @@ public class DemoActivity extends AppCompatActivity{ // 设置播放器id mVideoView.setVideoId("asdasdasdads"); + + DanmakuModel danmakuModel = new DanmakuModel(); List danmakuDetails = new ArrayList<>(); danmakuModel.setDanmakuDetails(danmakuDetails); diff --git a/build.gradle b/build.gradle index d5fb1cf..5a6f336 100644 --- a/build.gradle +++ b/build.gradle @@ -3,10 +3,12 @@ buildscript { repositories { google() - jcenter() +// jcenter() mavenCentral() maven { url 'https://jitpack.io' } maven { url 'http://4thline.org/m2' } + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + maven{ url'http://maven.aliyun.com/nexus/content/repositories/jcenter'} } dependencies { classpath 'com.android.tools.build:gradle:3.1.3' @@ -20,10 +22,12 @@ buildscript { allprojects { repositories { google() - jcenter() +// jcenter() mavenCentral() maven { url 'https://jitpack.io' } maven { url 'http://4thline.org/m2' } + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + maven{ url'http://maven.aliyun.com/nexus/content/repositories/jcenter'} } } diff --git a/gradle.properties b/gradle.properties index 396c58f..fbc1db2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,9 +13,9 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Mon Apr 10 16:35:27 CST 2017 -systemProp.http.proxyHost=127.0.0.1 +#systemProp.http.proxyHost=127.0.0.1 org.gradle.jvmargs=-Xmx1536m -systemProp.http.proxyPort=1080 +#systemProp.http.proxyPort=1080 KEY_PWD=123456 KEY_ALIAS=devlin KEYSTORE_PWD=123456 diff --git a/player/build.gradle b/player/build.gradle index 5d4359a..a8e532a 100644 --- a/player/build.gradle +++ b/player/build.gradle @@ -20,6 +20,7 @@ dependencies { implementation 'com.iheartradio.m3u8:open-m3u8:0.2.4' implementation 'com.squareup.okhttp3:okhttp:3.12.0' implementation 'com.github.bumptech.glide:glide:4.9.0' + implementation 'com.jwkj:M3U8Manger:v2.3.0' // testCompile 'junit:junit:4.12' diff --git a/player/src/main/java/cn/ctyun/videoplayer/controller/MediaPlayerControlInterface.java b/player/src/main/java/cn/ctyun/videoplayer/controller/BaseMediaPlayerControlInterface.java similarity index 85% rename from player/src/main/java/cn/ctyun/videoplayer/controller/MediaPlayerControlInterface.java rename to player/src/main/java/cn/ctyun/videoplayer/controller/BaseMediaPlayerControlInterface.java index 826a53f..d747275 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/controller/MediaPlayerControlInterface.java +++ b/player/src/main/java/cn/ctyun/videoplayer/controller/BaseMediaPlayerControlInterface.java @@ -2,7 +2,7 @@ package cn.ctyun.videoplayer.controller; import android.graphics.Bitmap; -public interface MediaPlayerControlInterface { +public interface BaseMediaPlayerControlInterface { void start(); @@ -84,4 +84,13 @@ public interface MediaPlayerControlInterface { long getPlayableVideoDuration(); void setPlayableVideoDuration(long sec); + + String getWatermarkText(); + + void setWatermarkText(String watermarkText); + + String getWatermarkPosition(); + + void setWatermarkPosition(String watermarkPosition); + } \ No newline at end of file diff --git a/player/src/main/java/cn/ctyun/videoplayer/controller/BaseVideoController.java b/player/src/main/java/cn/ctyun/videoplayer/controller/BaseVideoController.java index 03cb802..3b1af08 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/controller/BaseVideoController.java +++ b/player/src/main/java/cn/ctyun/videoplayer/controller/BaseVideoController.java @@ -31,7 +31,7 @@ import java.util.Locale; public abstract class BaseVideoController extends FrameLayout { protected View mControllerView;//控制器视图 - protected MediaPlayerControlInterface mMediaPlayer;//播放器 + protected BaseMediaPlayerControlInterface mMediaPlayer;//播放器 protected boolean mShowing;//控制器是否处于显示状态 protected boolean mIsLocked; protected int mDefaultTimeout = 4000; @@ -43,6 +43,8 @@ public abstract class BaseVideoController extends FrameLayout { protected Activity mAttachActivity; protected String mThumbUrl; +// protected String mWatermarkText; +// protected String mWatermarkPosition; public BaseVideoController(@NonNull Context context) { @@ -229,7 +231,7 @@ public abstract class BaseVideoController extends FrameLayout { return false; } - public void setMediaPlayer(MediaPlayerControlInterface mediaPlayer) { + public void setMediaPlayer(BaseMediaPlayerControlInterface mediaPlayer) { this.mMediaPlayer = mediaPlayer; } @@ -241,6 +243,22 @@ public abstract class BaseVideoController extends FrameLayout { return this.mThumbUrl; } +// public String getWatermarkText() { +// return mWatermarkText; +// } +// +// public void setWatermarkText(String mWatermarkText) { +// this.mWatermarkText = mWatermarkText; +// } +// +// public String getWatermarkPosition() { +// return mWatermarkPosition; +// } +// +// public void setWatermarkPosition(String mWatermarkPosition) { +// this.mWatermarkPosition = mWatermarkPosition; +// } + public void hidePausedAd() { } diff --git a/player/src/main/java/cn/ctyun/videoplayer/controller/DanmakuControllerInterface.java b/player/src/main/java/cn/ctyun/videoplayer/controller/DanmakuControllerInterfaceBase.java similarity index 74% rename from player/src/main/java/cn/ctyun/videoplayer/controller/DanmakuControllerInterface.java rename to player/src/main/java/cn/ctyun/videoplayer/controller/DanmakuControllerInterfaceBase.java index dffe978..4740f39 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/controller/DanmakuControllerInterface.java +++ b/player/src/main/java/cn/ctyun/videoplayer/controller/DanmakuControllerInterfaceBase.java @@ -1,6 +1,6 @@ package cn.ctyun.videoplayer.controller; -public interface DanmakuControllerInterface extends MediaPlayerControlInterface { +public interface DanmakuControllerInterfaceBase extends BaseMediaPlayerControlInterface { void sendDanmu(int danmakuType, String text, float danmakuTextSize, int danmakuTextColor, boolean isLive); diff --git a/player/src/main/java/cn/ctyun/videoplayer/controller/StandardVideoController.java b/player/src/main/java/cn/ctyun/videoplayer/controller/StandardVideoController.java index d30cb6b..53f2a48 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/controller/StandardVideoController.java +++ b/player/src/main/java/cn/ctyun/videoplayer/controller/StandardVideoController.java @@ -30,6 +30,7 @@ import cn.ctyun.videoplayer.dlnaupnp.entity.ClingDevice; import cn.ctyun.videoplayer.player.IjkVideoView; import cn.ctyun.videoplayer.receive.BatteryReceiver; import cn.ctyun.videoplayer.util.L; +import cn.ctyun.videoplayer.util.PlayerConstants; import cn.ctyun.videoplayer.util.PlayerUtils; import cn.ctyun.videoplayer.util.Utils; import cn.ctyun.videoplayer.widget.MarqueeTextView; @@ -91,6 +92,9 @@ public class StandardVideoController extends GestureVideoController implements V private boolean mDLNAConnected; private boolean mFullScreen; + private RelativeLayout mRlWatermark; + private TextView mTvWatermark; + public StandardVideoController(@NonNull Context context) { this(context, null); } @@ -184,10 +188,13 @@ public class StandardVideoController extends GestureVideoController implements V mLLDLNAChangeDeivce_land.setOnClickListener(this); mLLDLNAExit_land.setOnClickListener(this); + mRlWatermark = mControllerView.findViewById(R.id.rl_watermark); + mTvWatermark = mControllerView.findViewById(R.id.tv_watermark); + } @Override - public void setMediaPlayer(MediaPlayerControlInterface mediaPlayer) { + public void setMediaPlayer(BaseMediaPlayerControlInterface mediaPlayer) { super.setMediaPlayer(mediaPlayer); if (mediaPlayer != null) { if (mediaPlayer.getPauseAdResId() > 0 || !TextUtils.isEmpty(mediaPlayer.getPauseAdUrl())) { @@ -201,6 +208,27 @@ public class StandardVideoController extends GestureVideoController implements V if (!TextUtils.isEmpty(mThumbUrl)) { Glide.with(mAttachActivity).load(mThumbUrl).into(mThumb); } + + if (!TextUtils.isEmpty(mMediaPlayer.getWatermarkText())) { + mTvWatermark.setText(mMediaPlayer.getWatermarkText()); + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)mTvWatermark.getLayoutParams(); + if (PlayerConstants.WatermarkTextPosition.TOP_LEFT.equals(mMediaPlayer.getWatermarkPosition())) { + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT); + } else if (PlayerConstants.WatermarkTextPosition.TOP_RIGHT.equals(mMediaPlayer.getWatermarkPosition())) { + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + } else if (PlayerConstants.WatermarkTextPosition.BOTTOM_LEFT.equals(mMediaPlayer.getWatermarkPosition())) { + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT); + } else if (PlayerConstants.WatermarkTextPosition.BOTTOM_RIGHT.equals(mMediaPlayer.getWatermarkPosition())) { + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + } else { + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT); + } + } } } @@ -337,6 +365,7 @@ public class StandardVideoController extends GestureVideoController implements V mLoadingProgress.setVisibility(GONE); mStartPlayButton.setVisibility(VISIBLE); mThumb.setVisibility(VISIBLE); + handleWatermarkVisible(GONE); break; case IjkVideoView.STATE_PLAYING: L.e("STATE_PLAYING"); @@ -346,11 +375,14 @@ public class StandardVideoController extends GestureVideoController implements V mCompleteContainer.setVisibility(GONE); mThumb.setVisibility(GONE); mStartPlayButton.setVisibility(GONE); + handleWatermarkVisible(VISIBLE); break; case IjkVideoView.STATE_PAUSED: L.e("STATE_PAUSED"); mPlayButton.setSelected(false); mStartPlayButton.setVisibility(GONE); + mThumb.setVisibility(GONE); + handleWatermarkVisible(VISIBLE); break; case IjkVideoView.STATE_PREPARING: L.e("STATE_PREPARING"); @@ -358,12 +390,14 @@ public class StandardVideoController extends GestureVideoController implements V mStartPlayButton.setVisibility(GONE); mLoadingProgress.setVisibility(VISIBLE); // mThumb.setVisibility(View.VISIBLE); + handleWatermarkVisible(GONE); break; case IjkVideoView.STATE_PREPARED: L.e("STATE_PREPARED"); if (!mIsLive) mBottomProgress.setVisibility(VISIBLE); // mLoadingProgress.setVisibility(GONE); mStartPlayButton.setVisibility(GONE); + handleWatermarkVisible(GONE); break; case IjkVideoView.STATE_ERROR: L.e("STATE_ERROR"); @@ -372,17 +406,20 @@ public class StandardVideoController extends GestureVideoController implements V mThumb.setVisibility(GONE); mBottomProgress.setVisibility(GONE); mTopContainer.setVisibility(GONE); + handleWatermarkVisible(GONE); break; case IjkVideoView.STATE_BUFFERING: L.e("STATE_BUFFERING"); mStartPlayButton.setVisibility(GONE); mLoadingProgress.setVisibility(VISIBLE); mThumb.setVisibility(GONE); + handleWatermarkVisible(GONE); break; case IjkVideoView.STATE_BUFFERED: mLoadingProgress.setVisibility(GONE); mStartPlayButton.setVisibility(GONE); mThumb.setVisibility(GONE); + handleWatermarkVisible(GONE); L.e("STATE_BUFFERED"); break; case IjkVideoView.STATE_PLAYBACK_COMPLETED: @@ -390,12 +427,13 @@ public class StandardVideoController extends GestureVideoController implements V hide(); removeCallbacks(mShowProgress); mStartPlayButton.setVisibility(GONE); - mThumb.setVisibility(VISIBLE); + mThumb.setVisibility(GONE); mCompleteContainer.setVisibility(VISIBLE); mBottomProgress.setProgress(0); mBottomProgress.setSecondaryProgress(0); mIsLocked = false; mMediaPlayer.setLock(false); + handleWatermarkVisible(GONE); if (dlnaListener != null) { dlnaListener.onDLNADismissPop(); @@ -693,4 +731,12 @@ public class StandardVideoController extends GestureVideoController implements V public void hidePausedAd() { mRlPauseAd.setVisibility(GONE); } + + private void handleWatermarkVisible(int visible) { + if (!TextUtils.isEmpty(mMediaPlayer.getWatermarkText())) { + mRlWatermark.setVisibility(visible); + } else { + mRlWatermark.setVisibility(GONE); + } + } } diff --git a/player/src/main/java/cn/ctyun/videoplayer/interf/DefinitionMediaPlayerControlInterface.java b/player/src/main/java/cn/ctyun/videoplayer/interf/DefinitionMediaPlayerControlInterface.java index 8a865d4..d48b7d7 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/interf/DefinitionMediaPlayerControlInterface.java +++ b/player/src/main/java/cn/ctyun/videoplayer/interf/DefinitionMediaPlayerControlInterface.java @@ -1,6 +1,6 @@ package cn.ctyun.videoplayer.interf; -import cn.ctyun.videoplayer.controller.MediaPlayerControlInterface; +import cn.ctyun.videoplayer.controller.BaseMediaPlayerControlInterface; import java.util.LinkedHashMap; @@ -9,7 +9,7 @@ import java.util.LinkedHashMap; * Created by xinyu on 2017/12/25. */ -public interface DefinitionMediaPlayerControlInterface extends MediaPlayerControlInterface { +public interface DefinitionMediaPlayerControlInterface extends BaseMediaPlayerControlInterface { LinkedHashMap getDefinitionData(); void switchDefinition(String definition); } diff --git a/player/src/main/java/cn/ctyun/videoplayer/interf/ListMediaPlayerControlInterface.java b/player/src/main/java/cn/ctyun/videoplayer/interf/MediaPlayerControlInterface.java similarity index 64% rename from player/src/main/java/cn/ctyun/videoplayer/interf/ListMediaPlayerControlInterface.java rename to player/src/main/java/cn/ctyun/videoplayer/interf/MediaPlayerControlInterface.java index 9a6d3f6..ad75268 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/interf/ListMediaPlayerControlInterface.java +++ b/player/src/main/java/cn/ctyun/videoplayer/interf/MediaPlayerControlInterface.java @@ -1,12 +1,12 @@ package cn.ctyun.videoplayer.interf; -import cn.ctyun.videoplayer.controller.DanmakuControllerInterface; +import cn.ctyun.videoplayer.controller.DanmakuControllerInterfaceBase; /** * Created by xinyu on 2017/12/25. */ -public interface ListMediaPlayerControlInterface extends DanmakuControllerInterface { +public interface MediaPlayerControlInterface extends DanmakuControllerInterfaceBase { void skipToNext(); @@ -18,4 +18,6 @@ public interface ListMediaPlayerControlInterface extends DanmakuControllerInterf void stopEndAd(); +// void setWatermarkText(String watermarkText, String position); + } diff --git a/player/src/main/java/cn/ctyun/videoplayer/player/BaseIjkVideoView.java b/player/src/main/java/cn/ctyun/videoplayer/player/BaseIjkVideoView.java index 405ed05..ca81325 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/player/BaseIjkVideoView.java +++ b/player/src/main/java/cn/ctyun/videoplayer/player/BaseIjkVideoView.java @@ -11,11 +11,10 @@ import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.util.AttributeSet; import android.view.OrientationEventListener; -import android.view.WindowManager; import android.widget.FrameLayout; import cn.ctyun.videoplayer.controller.BaseVideoController; -import cn.ctyun.videoplayer.controller.MediaPlayerControlInterface; +import cn.ctyun.videoplayer.controller.BaseMediaPlayerControlInterface; import cn.ctyun.videoplayer.listener.OnVideoViewStateChangeListener; import cn.ctyun.videoplayer.listener.PlayerEventListener; import cn.ctyun.videoplayer.util.PlayerUtils; @@ -33,7 +32,7 @@ import tv.danmaku.ijk.media.player.IjkMediaPlayer; * Created by Devlin_n on 2017/4/7. */ -public abstract class BaseIjkVideoView extends FrameLayout implements MediaPlayerControlInterface, PlayerEventListener { +public abstract class BaseIjkVideoView extends FrameLayout implements BaseMediaPlayerControlInterface, PlayerEventListener { // 关联的Activity protected AppCompatActivity mAttachActivity; @@ -739,6 +738,7 @@ public abstract class BaseIjkVideoView extends FrameLayout implements MediaPlaye this.mVideoId = videoId; } + @Override public long getPlayableVideoDuration() { return mPlayableVideoDuration; @@ -754,4 +754,26 @@ public abstract class BaseIjkVideoView extends FrameLayout implements MediaPlaye mVideoController.doStartStopFullScreen(); } + protected String mWatermarkText; + protected String mWatermarkPosition; + public void setWatermarkText(String watermarkText, String position) { + this.mWatermarkText = watermarkText; + this.mWatermarkPosition = position; + } + + public String getWatermarkText() { + return mWatermarkText; + } + + public void setWatermarkText(String mWatermarkText) { + this.mWatermarkText = mWatermarkText; + } + + public String getWatermarkPosition() { + return mWatermarkPosition; + } + + public void setWatermarkPosition(String mWatermarkPosition) { + this.mWatermarkPosition = mWatermarkPosition; + } } diff --git a/player/src/main/java/cn/ctyun/videoplayer/util/Constants.java b/player/src/main/java/cn/ctyun/videoplayer/util/PlayerConstants.java similarity index 52% rename from player/src/main/java/cn/ctyun/videoplayer/util/Constants.java rename to player/src/main/java/cn/ctyun/videoplayer/util/PlayerConstants.java index 0eb2d02..98b62de 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/util/Constants.java +++ b/player/src/main/java/cn/ctyun/videoplayer/util/PlayerConstants.java @@ -1,10 +1,17 @@ package cn.ctyun.videoplayer.util; -public class Constants { +public class PlayerConstants { public static final String VIDEO_TYPE_START_AD = "START_AD"; public static final String VIDEO_TYPE_END_AD = "END_AD"; public static final String VIDEO_TYPE_VOD = "VOD"; public static final String VIDEO_TYPE_LIVE = "LIVE"; + public interface WatermarkTextPosition { + String TOP_LEFT = "TOP_LEFT"; + String TOP_RIGHT = "TOP_RIGHT"; + String BOTTOM_LEFT = "BOTTOM_LEFT"; + String BOTTOM_RIGHT = "BOTTOM_RIGHT"; + } + } diff --git a/player/src/main/java/cn/ctyun/videoplayer/util/VideoCacheManager.java b/player/src/main/java/cn/ctyun/videoplayer/util/VideoCacheManager.java index 3947286..c072e27 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/util/VideoCacheManager.java +++ b/player/src/main/java/cn/ctyun/videoplayer/util/VideoCacheManager.java @@ -18,7 +18,7 @@ public class VideoCacheManager { return sharedProxy == null ? (sharedProxy = newProxy(context)) : sharedProxy; } - private static HttpProxyCacheServer newProxy(Context context) { + public static HttpProxyCacheServer newProxy(Context context) { return new HttpProxyCacheServer.Builder(context) .maxCacheSize(1024 * 1024 * 1024) // 1 Gb for cache //缓存路径,不设置默认在sd_card/Android/data/[app_package_name]/cache中 diff --git a/player/src/main/java/cn/ctyun/videoplayer/widget/CacheIjkVideoView.java b/player/src/main/java/cn/ctyun/videoplayer/widget/CacheIjkVideoView.java index 54e439e..b17f3cd 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/widget/CacheIjkVideoView.java +++ b/player/src/main/java/cn/ctyun/videoplayer/widget/CacheIjkVideoView.java @@ -1,21 +1,43 @@ package cn.ctyun.videoplayer.widget; import android.content.Context; +import android.net.Uri; +import android.os.Environment; +import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.AttributeSet; +import android.util.Log; import com.danikula.videocache.CacheListener; import com.danikula.videocache.HttpProxyCacheServer; +import com.hdl.m3u8.M3U8DownloadTask; +import com.hdl.m3u8.M3U8LiveManger; +import com.hdl.m3u8.bean.M3U8; +import com.hdl.m3u8.bean.M3U8Ts; +import com.hdl.m3u8.bean.OnDownloadListener; +import com.hdl.m3u8.utils.MUtils; +import com.hdl.m3u8.utils.NetSpeedUtils; import cn.ctyun.videoplayer.player.IjkVideoView; import cn.ctyun.videoplayer.util.VideoCacheManager; +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.file.Files; +import java.util.logging.Logger; public class CacheIjkVideoView extends IjkVideoView { + public static final String TAG = CacheIjkVideoView.class.getSimpleName(); + protected HttpProxyCacheServer mCacheServer; protected int mBufferedPercentage; protected boolean mIsCacheEnabled = true; //默认打开缓存 @@ -32,7 +54,8 @@ public class CacheIjkVideoView extends IjkVideoView { super(context, attrs, defStyleAttr); } - + private long lastLength = 0; + M3U8DownloadTask task1 = new M3U8DownloadTask("1001"); @Override protected void startPrepare(boolean needReset) { // super.startPrepare(needReset); @@ -40,21 +63,65 @@ public class CacheIjkVideoView extends IjkVideoView { if (needReset) mMediaPlayer.reset(); if (mAssetFileDescriptor != null) { mMediaPlayer.setDataSource(mAssetFileDescriptor); - } else if (mIsCacheEnabled && !mCurrentUrl.startsWith("file://") && !mCurrentUrl.contains(".m3u8")) { - //本地文件和m3u8不能缓存 - mCacheServer = getCacheServer(); - String proxyPath = mCacheServer.getProxyUrl(mCurrentUrl); - mCacheServer.registerCacheListener(cacheListener, mCurrentUrl); - if (mCacheServer.isCached(mCurrentUrl)) { - mBufferedPercentage = 100; + //本地文件不能缓存 + } else if (mIsCacheEnabled && !mCurrentUrl.startsWith("file://")) { + if (mCurrentUrl.contains(".m3u8")) { + + mMediaPlayer.setDataSource(mCurrentUrl, mHeaders); + mMediaPlayer.prepareAsync(); + setPlayState(STATE_PREPARING); + setPlayerState(isFullScreen() ? PLAYER_FULL_SCREEN : PLAYER_NORMAL); + +// new Thread() { +// @Override +// public void run() { +// try { +// String proxyPath= "/sdcard/" + System.currentTimeMillis() + ".m3u8"; +// +// parseIndex(mCurrentUrl, proxyPath); +//// mCacheServer.registerCacheListener(cacheListener, mCurrentUrl); +//// if (mCacheServer.isCached(mCurrentUrl)) { +//// mBufferedPercentage = 100; +//// } +// mMediaPlayer.setDataSource(proxyPath, mHeaders); +// +// CacheIjkVideoView.this.mAttachActivity.runOnUiThread(new Runnable() { +// @Override +// public void run() { +// mMediaPlayer.prepareAsync(); +// setPlayState(STATE_PREPARING); +// setPlayerState(isFullScreen() ? PLAYER_FULL_SCREEN : PLAYER_NORMAL); +// } +// }); +// +// +// } catch (IOException e) { +// e.printStackTrace(); +// } +// } +// }.start(); + + } else { + mCacheServer = getCacheServer(); + String proxyPath = mCacheServer.getProxyUrl(mCurrentUrl); + mCacheServer.registerCacheListener(cacheListener, mCurrentUrl); + if (mCacheServer.isCached(mCurrentUrl)) { + mBufferedPercentage = 100; + } + mMediaPlayer.setDataSource(proxyPath, mHeaders); + mMediaPlayer.prepareAsync(); + setPlayState(STATE_PREPARING); + setPlayerState(isFullScreen() ? PLAYER_FULL_SCREEN : PLAYER_NORMAL); } - mMediaPlayer.setDataSource(proxyPath, mHeaders); } else { mMediaPlayer.setDataSource(mCurrentUrl, mHeaders); + mMediaPlayer.prepareAsync(); + setPlayState(STATE_PREPARING); + setPlayerState(isFullScreen() ? PLAYER_FULL_SCREEN : PLAYER_NORMAL); } - mMediaPlayer.prepareAsync(); - setPlayState(STATE_PREPARING); - setPlayerState(isFullScreen() ? PLAYER_FULL_SCREEN : PLAYER_NORMAL); +// mMediaPlayer.prepareAsync(); +// setPlayState(STATE_PREPARING); +// setPlayerState(isFullScreen() ? PLAYER_FULL_SCREEN : PLAYER_NORMAL); } @@ -95,4 +162,46 @@ public class CacheIjkVideoView extends IjkVideoView { mBufferedPercentage = percentsAvailable; } }; + + public String parseIndex(String url, String toFile) throws IOException { + HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + if (conn.getResponseCode() == 200) { + String realUrl = conn.getURL().toString(); + BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); + + + File newFile = new File(toFile); + FileWriter write = new FileWriter(newFile,true); + BufferedWriter bufferedWriter = new BufferedWriter(write); + + String line; +// mCacheServer = getCacheServer(); + HttpProxyCacheServer cacheServer = VideoCacheManager.newProxy(getContext().getApplicationContext()); + while ((line = reader.readLine()) != null) { + if (line.startsWith("#")) { + + } else { + cacheServer.registerCacheListener(new CacheListener() { + @Override + public void onCacheAvailable(File cacheFile, String url, int percentsAvailable) { + mBufferedPercentage = percentsAvailable; + } + }, line); + line = cacheServer.getProxyUrl(line); + } + bufferedWriter.write(line); + bufferedWriter.newLine();//换行 + bufferedWriter.flush(); + + } + reader.close(); + write.close(); + bufferedWriter.close(); + + return toFile; + + } + + return null; + } } diff --git a/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java b/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java index f5e27e7..ce6e4dc 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java +++ b/player/src/main/java/cn/ctyun/videoplayer/widget/DanmakuVideoView.java @@ -45,7 +45,7 @@ import cn.ctyun.videoplayer.adapter.DLNADevicesAdapter; import cn.ctyun.videoplayer.bean.DanmakuDetail; import cn.ctyun.videoplayer.bean.DanmakuModel; import cn.ctyun.videoplayer.controller.DLNAControllerInterface; -import cn.ctyun.videoplayer.controller.DanmakuControllerInterface; +import cn.ctyun.videoplayer.controller.DanmakuControllerInterfaceBase; import cn.ctyun.videoplayer.controller.StandardVideoController; import cn.ctyun.videoplayer.danmaku.BiliDanmukuParser; import cn.ctyun.videoplayer.dlnaupnp.Intents; @@ -82,7 +82,7 @@ import master.flame.danmaku.ui.widget.DanmakuView; * Created by liujingtao on 2019/2/25. */ -public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuControllerInterface, View.OnClickListener { +public class DanmakuVideoView extends CacheIjkVideoView implements DanmakuControllerInterfaceBase, View.OnClickListener { // 是否启用弹幕 private boolean mDanmakuEnable; diff --git a/player/src/main/java/cn/ctyun/videoplayer/widget/VideoView.java b/player/src/main/java/cn/ctyun/videoplayer/widget/VideoView.java index 547e70d..68da907 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/widget/VideoView.java +++ b/player/src/main/java/cn/ctyun/videoplayer/widget/VideoView.java @@ -8,6 +8,9 @@ import android.util.AttributeSet; import android.util.Log; import android.widget.Toast; +import com.hdl.m3u8.M3U8InfoManger; +import com.hdl.m3u8.bean.M3U8; +import com.hdl.m3u8.bean.OnM3U8InfoListener; import com.iheartradio.m3u8.Encoding; import com.iheartradio.m3u8.Format; import com.iheartradio.m3u8.ParseException; @@ -27,15 +30,17 @@ import java.util.List; import cn.ctyun.videoplayer.bean.M3u8PlayList; import cn.ctyun.videoplayer.bean.VideoModel; -import cn.ctyun.videoplayer.interf.ListMediaPlayerControlInterface; -import cn.ctyun.videoplayer.util.Constants; +import cn.ctyun.videoplayer.interf.MediaPlayerControlInterface; +import cn.ctyun.videoplayer.util.PlayerConstants; import cn.ctyun.videoplayer.util.HttpUtils; import cn.ctyun.videoplayer.widget.controller.AdController; import cn.ctyun.videoplayer.widget.controller.DanmakuController; import okhttp3.Call; import okhttp3.Response; -public class VideoView extends DefinitionIjkVideoView implements ListMediaPlayerControlInterface { +public class VideoView extends DefinitionIjkVideoView implements MediaPlayerControlInterface { + + private static final String TAG = VideoView.class.getSimpleName(); protected List mVideoModels;//列表播放数据 protected int mCurrentVideoPosition = 0;//列表播放时当前播放视频的在List中的位置 @@ -44,6 +49,8 @@ public class VideoView extends DefinitionIjkVideoView implements ListMediaPlayer private String mThumbUrl; private boolean hasSetThumb = false; + + public VideoView(@NonNull Context context) { super(context); } @@ -68,8 +75,8 @@ public class VideoView extends DefinitionIjkVideoView implements ListMediaPlayer return; } VideoModel videoModel = mVideoModels.get(mCurrentVideoPosition); - if (Constants.VIDEO_TYPE_START_AD.equals(videoModel.getVideoType()) - || Constants.VIDEO_TYPE_END_AD.equals(videoModel.getVideoType())) { + if (PlayerConstants.VIDEO_TYPE_START_AD.equals(videoModel.getVideoType()) + || PlayerConstants.VIDEO_TYPE_END_AD.equals(videoModel.getVideoType())) { Toast.makeText(getContext(), "广告不支持停止播放", Toast.LENGTH_SHORT).show(); return; } @@ -81,6 +88,11 @@ public class VideoView extends DefinitionIjkVideoView implements ListMediaPlayer this.mThumbUrl = thumbUrl; } +// public void setWatermarkText(String watermarkText, String position) { +// this.mWatermarkText = watermarkText; +// this.mWatermarkPosition = position; +// } + @Override public String getThumbUrl() { return mThumbUrl; @@ -92,7 +104,7 @@ public class VideoView extends DefinitionIjkVideoView implements ListMediaPlayer return; } VideoModel videoModel = mVideoModels.get(mCurrentVideoPosition); - if (Constants.VIDEO_TYPE_START_AD.equals(videoModel.getVideoType())) { + if (PlayerConstants.VIDEO_TYPE_START_AD.equals(videoModel.getVideoType())) { if (mCurrentVideoPosition + 1 == mVideoModels.size()) { // 已经最后一个,直接停止 super.stop(); } else { @@ -106,7 +118,7 @@ public class VideoView extends DefinitionIjkVideoView implements ListMediaPlayer if (mVideoModels != null && mVideoModels.size() > 0) { if (mCurrentVideoPosition < mVideoModels.size()) { VideoModel videoModel = mVideoModels.get(mCurrentVideoPosition); - if (Constants.VIDEO_TYPE_END_AD.equals(videoModel.getVideoType())) { + if (PlayerConstants.VIDEO_TYPE_END_AD.equals(videoModel.getVideoType())) { if (mCurrentVideoPosition + 1 == mVideoModels.size()) { // 已经最后一个,直接停止 super.stop(); } else { @@ -154,8 +166,8 @@ public class VideoView extends DefinitionIjkVideoView implements ListMediaPlayer mCurrentTitle = videoModel.getTitle(); // setCacheEnabled(true); // 默认打开缓存,离线可观看 // mCurrentPosition = 0; - if (Constants.VIDEO_TYPE_START_AD.equals(videoModel.getVideoType()) - || Constants.VIDEO_TYPE_END_AD.equals(videoModel.getVideoType())) { + if (PlayerConstants.VIDEO_TYPE_START_AD.equals(videoModel.getVideoType()) + || PlayerConstants.VIDEO_TYPE_END_AD.equals(videoModel.getVideoType())) { AdController adController = new AdController(getContext()); if (hasSetThumb) { adController.setThumbUrl(null); @@ -177,17 +189,38 @@ public class VideoView extends DefinitionIjkVideoView implements ListMediaPlayer hasSetThumb = true; } } - if (Constants.VIDEO_TYPE_LIVE.equals(videoModel.getVideoType())) { + if (PlayerConstants.VIDEO_TYPE_LIVE.equals(videoModel.getVideoType())) { danmakuController.setLive(); - setVideoController(danmakuController); - } else { - setVideoController(danmakuController); } +// danmakuController.setWatermarkText(mWatermarkText); +// danmakuController.setWatermarkPosition(mWatermarkPosition); + setVideoController(danmakuController); +// setVideoPath(videoModel.getUrl()); + +// if (!videoModel.getUrl().contains("m3u8")) { +// return; +// } +// M3U8InfoManger.getInstance().getM3U8Info(videoModel.getUrl(), new OnM3U8InfoListener() { +// @Override +// public void onSuccess(M3U8 m3U8) { +// Log.d(TAG,"获取成功了" + m3U8); +// } +// +// @Override +// public void onStart() { +// Log.d(TAG, "开始获取信息"); +// } +// +// @Override +// public void onError(Throwable errorMsg) { +// Log.d(TAG, "出错了" + errorMsg); +// } +// }); } } -// setVideoPath(videoModel.getUrl()); + } diff --git a/player/src/main/java/cn/ctyun/videoplayer/widget/controller/AdController.java b/player/src/main/java/cn/ctyun/videoplayer/widget/controller/AdController.java index a2c3134..6342a25 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/widget/controller/AdController.java +++ b/player/src/main/java/cn/ctyun/videoplayer/widget/controller/AdController.java @@ -17,9 +17,9 @@ import com.bumptech.glide.Glide; import cn.ctyun.videoplayer.R; import cn.ctyun.videoplayer.controller.BaseVideoController; -import cn.ctyun.videoplayer.controller.MediaPlayerControlInterface; +import cn.ctyun.videoplayer.controller.BaseMediaPlayerControlInterface; import cn.ctyun.videoplayer.interf.AdControllerListener; -import cn.ctyun.videoplayer.interf.ListMediaPlayerControlInterface; +import cn.ctyun.videoplayer.interf.MediaPlayerControlInterface; import cn.ctyun.videoplayer.player.IjkVideoView; import cn.ctyun.videoplayer.util.PlayerUtils; @@ -98,11 +98,11 @@ public class AdController extends BaseVideoController implements View.OnClickLis } else if (id == R.id.ad_detail) { if (listener != null) listener.onAdClick(); } else if (id == R.id.ad_time) { - ((ListMediaPlayerControlInterface) mMediaPlayer).skipToNext(); + ((MediaPlayerControlInterface) mMediaPlayer).skipToNext(); } else if (id == R.id.start_play) { doPauseResume(); } else if (id == R.id.iv_replay) { -// ((ListMediaPlayerControlInterface)mMediaPlayer).restart(); +// ((MediaPlayerControlInterface)mMediaPlayer).restart(); mMediaPlayer.retry(); } } @@ -259,7 +259,7 @@ public class AdController extends BaseVideoController implements View.OnClickLis } @Override - public void setMediaPlayer(MediaPlayerControlInterface mediaPlayer) { + public void setMediaPlayer(BaseMediaPlayerControlInterface mediaPlayer) { super.setMediaPlayer(mediaPlayer); if (mediaPlayer != null) { if (!TextUtils.isEmpty(mThumbUrl)) { diff --git a/player/src/main/java/cn/ctyun/videoplayer/widget/controller/DanmakuController.java b/player/src/main/java/cn/ctyun/videoplayer/widget/controller/DanmakuController.java index 67927e7..0ca01a7 100644 --- a/player/src/main/java/cn/ctyun/videoplayer/widget/controller/DanmakuController.java +++ b/player/src/main/java/cn/ctyun/videoplayer/widget/controller/DanmakuController.java @@ -13,8 +13,8 @@ import android.widget.RadioButton; import android.widget.RadioGroup; import cn.ctyun.videoplayer.R; -import cn.ctyun.videoplayer.controller.DanmakuControllerInterface; -import cn.ctyun.videoplayer.controller.MediaPlayerControlInterface; +import cn.ctyun.videoplayer.controller.DanmakuControllerInterfaceBase; +import cn.ctyun.videoplayer.controller.BaseMediaPlayerControlInterface; import cn.ctyun.videoplayer.player.IjkVideoView; import cn.ctyun.videoplayer.util.AnimHelper; import cn.ctyun.videoplayer.util.NavUtils; @@ -174,14 +174,14 @@ public class DanmakuController extends DefinitionController { } @Override - public void setMediaPlayer(MediaPlayerControlInterface mediaPlayer) { + public void setMediaPlayer(BaseMediaPlayerControlInterface mediaPlayer) { super.setMediaPlayer(mediaPlayer); if (mediaPlayer != null) { - if (!((DanmakuControllerInterface) mMediaPlayer).isDanmakuEnable()) { + if (!((DanmakuControllerInterfaceBase) mMediaPlayer).isDanmakuEnable()) { mIvDanmakuControl.setVisibility(GONE); mOpenEditDanmaku.setVisibility(GONE); } - if (!((DanmakuControllerInterface) mMediaPlayer).isDanmakuEnable()) { + if (!((DanmakuControllerInterfaceBase) mMediaPlayer).isDanmakuEnable()) { mDLNAButton.setVisibility(GONE); } } @@ -231,11 +231,11 @@ public class DanmakuController extends DefinitionController { recoverFromEditVideo(); } else if (i == R.id.iv_do_send) { recoverFromEditVideo(); - if (mMediaPlayer instanceof DanmakuControllerInterface) { + if (mMediaPlayer instanceof DanmakuControllerInterfaceBase) { if (mDanmakuTextSize == INVALID_VALUE) { mDanmakuTextSize = 25f * (((DanmakuVideoView)mMediaPlayer).getDanmakuParser().getDisplayer().getDensity() - 0.6f); } - ((DanmakuControllerInterface) mMediaPlayer).sendDanmu(mDanmakuType, + ((DanmakuControllerInterfaceBase) mMediaPlayer).sendDanmu(mDanmakuType, mEtDanmakuContent.getText().toString(), mDanmakuTextSize, mDanmakuTextColor, false); mEtDanmakuContent.setText(""); } @@ -277,8 +277,8 @@ public class DanmakuController extends DefinitionController { } else { mIvDanmakuControl.setSelected(false); } - if (mMediaPlayer instanceof DanmakuControllerInterface) { - ((DanmakuControllerInterface) mMediaPlayer).showOrHideDanmaku(isShow); + if (mMediaPlayer instanceof DanmakuControllerInterfaceBase) { + ((DanmakuControllerInterfaceBase) mMediaPlayer).showOrHideDanmaku(isShow); } } @@ -366,7 +366,7 @@ public class DanmakuController extends DefinitionController { switch (playState) { case IjkVideoView.STATE_PLAYBACK_COMPLETED: // Toast.makeText(mAttachActivity, "dasdasd", Toast.LENGTH_SHORT).show(); - ((DanmakuControllerInterface) mMediaPlayer).releaseDanmaku(); + ((DanmakuControllerInterfaceBase) mMediaPlayer).releaseDanmaku(); // showOrHideDanmaku(false); break; } diff --git a/player/src/main/res/drawable/shape_watermark_bg.xml b/player/src/main/res/drawable/shape_watermark_bg.xml new file mode 100644 index 0000000..f3fe02f --- /dev/null +++ b/player/src/main/res/drawable/shape_watermark_bg.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/player/src/main/res/layout/dkplayer_layout_standard_controller.xml b/player/src/main/res/layout/dkplayer_layout_standard_controller.xml index 77e8dab..ac93466 100644 --- a/player/src/main/res/layout/dkplayer_layout_standard_controller.xml +++ b/player/src/main/res/layout/dkplayer_layout_standard_controller.xml @@ -6,6 +6,21 @@ android:layout_height="match_parent" android:orientation="vertical"> + + + + + + 5dp center +