diff --git a/build/ant-contrib-1.0b2.jar b/build/ant-contrib-1.0b2.jar new file mode 100644 index 000000000..ea817cd43 Binary files /dev/null and b/build/ant-contrib-1.0b2.jar differ diff --git a/build/ant-contrib.jar b/build/ant-contrib.jar deleted file mode 100644 index 14bfe5a26..000000000 Binary files a/build/ant-contrib.jar and /dev/null differ diff --git a/build/build.xml b/build/build.xml index a93e74c18..bf190da6d 100644 --- a/build/build.xml +++ b/build/build.xml @@ -17,7 +17,7 @@ - + @@ -26,29 +26,36 @@ - + - + + + + - - + + - - + + - - - - - - - + + + + + + + + + + + + + + + @@ -132,6 +139,40 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -170,54 +211,68 @@ + - + + + includes="org/jivesoftware/smack/**/*.class, **/smack-config.xml, **/core.providers, **/jul.properties"> - - + + - + + - - + + - - + + - + + + - + + + - - - + + - + + + - + @@ -225,35 +280,79 @@ - - + + - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -283,7 +382,7 @@ - + @@ -365,7 +464,7 @@ @@ -385,7 +484,7 @@ - + diff --git a/build/eclipse/classpath b/build/eclipse/classpath index 67dd4e3b5..135c0ca29 100644 --- a/build/eclipse/classpath +++ b/build/eclipse/classpath @@ -5,7 +5,11 @@ - + + + + + diff --git a/build/eclipse/project b/build/eclipse/project index 3b685ff03..4d04574a8 100644 --- a/build/eclipse/project +++ b/build/eclipse/project @@ -1,6 +1,6 @@ - smack-3.3.x + smack-3.4.x diff --git a/build/release.xml b/build/release.xml index b4a0eef4b..71d3e491e 100644 --- a/build/release.xml +++ b/build/release.xml @@ -14,7 +14,7 @@ - + @@ -28,155 +28,66 @@ - - - - - - - - - - - - - - - - - + + + + + + + - - + + + - - - - + + + + + + - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + - - - - - - - - - - - - - - - - - - - - - + + + ----------------------------------------------- -Release made, testing Ant targets of release... +Release made ----------------------------------------------- - - - diff --git a/build/resources/META-INF/core.providers b/build/resources/META-INF/core.providers new file mode 100644 index 000000000..614a2d8d7 --- /dev/null +++ b/build/resources/META-INF/core.providers @@ -0,0 +1,19 @@ + + + + + + + query + jabber:iq:privacy + org.jivesoftware.smack.provider.PrivacyProvider + + + + + ping + urn:xmpp:ping + org.jivesoftware.smack.ping.provider.PingProvider + + + diff --git a/build/resources/META-INF/smack.providers b/build/resources/META-INF/extension.providers similarity index 64% rename from build/resources/META-INF/smack.providers rename to build/resources/META-INF/extension.providers index 452e3df55..a5eb372fb 100644 --- a/build/resources/META-INF/smack.providers +++ b/build/resources/META-INF/extension.providers @@ -1,663 +1,445 @@ - - - - - - - query - jabber:iq:private - org.jivesoftware.smackx.PrivateDataManager$PrivateDataIQProvider - - - - - query - jabber:iq:time - org.jivesoftware.smackx.packet.Time - - - - - x - jabber:x:roster - org.jivesoftware.smackx.provider.RosterExchangeProvider - - - - - x - jabber:x:event - org.jivesoftware.smackx.provider.MessageEventProvider - - - - - active - http://jabber.org/protocol/chatstates - org.jivesoftware.smackx.packet.ChatStateExtension$Provider - - - - composing - http://jabber.org/protocol/chatstates - org.jivesoftware.smackx.packet.ChatStateExtension$Provider - - - - paused - http://jabber.org/protocol/chatstates - org.jivesoftware.smackx.packet.ChatStateExtension$Provider - - - - inactive - http://jabber.org/protocol/chatstates - org.jivesoftware.smackx.packet.ChatStateExtension$Provider - - - - gone - http://jabber.org/protocol/chatstates - org.jivesoftware.smackx.packet.ChatStateExtension$Provider - - - - - html - http://jabber.org/protocol/xhtml-im - org.jivesoftware.smackx.provider.XHTMLExtensionProvider - - - - - x - jabber:x:conference - org.jivesoftware.smackx.GroupChatInvitation$Provider - - - - - query - http://jabber.org/protocol/disco#items - org.jivesoftware.smackx.provider.DiscoverItemsProvider - - - - - query - http://jabber.org/protocol/disco#info - org.jivesoftware.smackx.provider.DiscoverInfoProvider - - - - - x - jabber:x:data - org.jivesoftware.smackx.provider.DataFormProvider - - - - - x - http://jabber.org/protocol/muc#user - org.jivesoftware.smackx.provider.MUCUserProvider - - - - - query - http://jabber.org/protocol/muc#admin - org.jivesoftware.smackx.provider.MUCAdminProvider - - - - - query - http://jabber.org/protocol/muc#owner - org.jivesoftware.smackx.provider.MUCOwnerProvider - - - - - x - jabber:x:delay - org.jivesoftware.smackx.provider.DelayInformationProvider - - - - delay - urn:xmpp:delay - org.jivesoftware.smackx.provider.DelayInfoProvider - - - - - query - jabber:iq:version - org.jivesoftware.smackx.packet.Version - - - - - vCard - vcard-temp - org.jivesoftware.smackx.provider.VCardProvider - - - - - offline - http://jabber.org/protocol/offline - org.jivesoftware.smackx.packet.OfflineMessageRequest$Provider - - - - - offline - http://jabber.org/protocol/offline - org.jivesoftware.smackx.packet.OfflineMessageInfo$Provider - - - - - query - jabber:iq:last - org.jivesoftware.smackx.packet.LastActivity$Provider - - - - - query - jabber:iq:search - org.jivesoftware.smackx.search.UserSearch$Provider - - - - - sharedgroup - http://www.jivesoftware.org/protocol/sharedgroup - org.jivesoftware.smackx.packet.SharedGroupsInfo$Provider - - - - - addresses - http://jabber.org/protocol/address - org.jivesoftware.smackx.provider.MultipleAddressesProvider - - - - - si - http://jabber.org/protocol/si - org.jivesoftware.smackx.provider.StreamInitiationProvider - - - - query - http://jabber.org/protocol/bytestreams - org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider - - - - open - http://jabber.org/protocol/ibb - org.jivesoftware.smackx.bytestreams.ibb.provider.OpenIQProvider - - - - data - http://jabber.org/protocol/ibb - org.jivesoftware.smackx.bytestreams.ibb.provider.DataPacketProvider - - - - close - http://jabber.org/protocol/ibb - org.jivesoftware.smackx.bytestreams.ibb.provider.CloseIQProvider - - - - data - http://jabber.org/protocol/ibb - org.jivesoftware.smackx.bytestreams.ibb.provider.DataPacketProvider - - - - - query - jabber:iq:privacy - org.jivesoftware.smack.provider.PrivacyProvider - - - - - command - http://jabber.org/protocol/commands - org.jivesoftware.smackx.provider.AdHocCommandDataProvider - - - - bad-action - http://jabber.org/protocol/commands - org.jivesoftware.smackx.provider.AdHocCommandDataProvider$BadActionError - - - - malformed-actionn - http://jabber.org/protocol/commands - org.jivesoftware.smackx.provider.AdHocCommandDataProvider$MalformedActionError - - - - bad-locale - http://jabber.org/protocol/commands - org.jivesoftware.smackx.provider.AdHocCommandDataProvider$BadLocaleError - - - - bad-payload - http://jabber.org/protocol/commands - org.jivesoftware.smackx.provider.AdHocCommandDataProvider$BadPayloadError - - - - bad-sessionid - http://jabber.org/protocol/commands - org.jivesoftware.smackx.provider.AdHocCommandDataProvider$BadSessionIDError - - - - session-expired - http://jabber.org/protocol/commands - org.jivesoftware.smackx.provider.AdHocCommandDataProvider$SessionExpiredError - - - - - - offer - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.OfferRequestProvider - - - - offer-revoke - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.OfferRevokeProvider - - - - agent-status-request - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.AgentStatusRequest$Provider - - - - transcripts - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.TranscriptsProvider - - - - transcript - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.TranscriptProvider - - - - workgroups - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.AgentWorkgroups$Provider - - - - agent-info - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.AgentInfo$Provider - - - - transcript-search - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.TranscriptSearch$Provider - - - - occupants-info - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.OccupantsInfo$Provider - - - - chat-settings - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.settings.ChatSettings$InternalProvider - - - - chat-notes - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.ext.notes.ChatNotes$Provider - - - - chat-sessions - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.ext.history.AgentChatHistory$InternalProvider - - - - offline-settings - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.settings.OfflineSettings$InternalProvider - - - - sound-settings - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.settings.SoundSettings$InternalProvider - - - - workgroup-properties - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.settings.WorkgroupProperties$InternalProvider - - - - - search-settings - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.settings.SearchSettings$InternalProvider - - - - workgroup-form - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.ext.forms.WorkgroupForm$InternalProvider - - - - macros - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.ext.macros.Macros$InternalProvider - - - - chat-metadata - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.ext.history.ChatMetadata$Provider - - - - generic-metadata - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.settings.GenericSettings$InternalProvider - - - - monitor - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.MonitorPacket$InternalProvider - - - - - queue-status - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.QueueUpdate$Provider - - - - workgroup - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.WorkgroupInformation$Provider - - - - metadata - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.MetaDataProvider - - - - session - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.SessionID$Provider - - - - user - http://jivesoftware.com/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.UserID$Provider - - - - agent-status - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.AgentStatus$Provider - - - - notify-queue-details - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.QueueDetails$Provider - - - - notify-queue - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.QueueOverview$Provider - - - - invite - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.RoomInvitation$Provider - - - - transfer - http://jabber.org/protocol/workgroup - org.jivesoftware.smackx.workgroup.packet.RoomTransfer$Provider - - - - - headers - http://jabber.org/protocol/shim - org.jivesoftware.smackx.provider.HeadersProvider - - - - header - http://jabber.org/protocol/shim - org.jivesoftware.smackx.provider.HeaderProvider - - - - - pubsub - http://jabber.org/protocol/pubsub - org.jivesoftware.smackx.pubsub.provider.PubSubProvider - - - - create - http://jabber.org/protocol/pubsub - org.jivesoftware.smackx.pubsub.provider.SimpleNodeProvider - - - - items - http://jabber.org/protocol/pubsub - org.jivesoftware.smackx.pubsub.provider.ItemsProvider - - - - item - http://jabber.org/protocol/pubsub - org.jivesoftware.smackx.pubsub.provider.ItemProvider - - - - subscriptions - http://jabber.org/protocol/pubsub - org.jivesoftware.smackx.pubsub.provider.SubscriptionsProvider - - - - subscription - http://jabber.org/protocol/pubsub - org.jivesoftware.smackx.pubsub.provider.SubscriptionProvider - - - - affiliations - http://jabber.org/protocol/pubsub - org.jivesoftware.smackx.pubsub.provider.AffiliationsProvider - - - - affiliation - http://jabber.org/protocol/pubsub - org.jivesoftware.smackx.pubsub.provider.AffiliationProvider - - - - options - http://jabber.org/protocol/pubsub - org.jivesoftware.smackx.pubsub.provider.FormNodeProvider - - - - - pubsub - http://jabber.org/protocol/pubsub#owner - org.jivesoftware.smackx.pubsub.provider.PubSubProvider - - - - configure - http://jabber.org/protocol/pubsub#owner - org.jivesoftware.smackx.pubsub.provider.FormNodeProvider - - - - default - http://jabber.org/protocol/pubsub#owner - org.jivesoftware.smackx.pubsub.provider.FormNodeProvider - - - - - event - http://jabber.org/protocol/pubsub#event - org.jivesoftware.smackx.pubsub.provider.EventProvider - - - - configuration - http://jabber.org/protocol/pubsub#event - org.jivesoftware.smackx.pubsub.provider.ConfigEventProvider - - - - delete - http://jabber.org/protocol/pubsub#event - org.jivesoftware.smackx.pubsub.provider.SimpleNodeProvider - - - - options - http://jabber.org/protocol/pubsub#event - org.jivesoftware.smackx.pubsub.provider.FormNodeProvider - - - - items - http://jabber.org/protocol/pubsub#event - org.jivesoftware.smackx.pubsub.provider.ItemsProvider - - - - item - http://jabber.org/protocol/pubsub#event - org.jivesoftware.smackx.pubsub.provider.ItemProvider - - - - retract - http://jabber.org/protocol/pubsub#event - org.jivesoftware.smackx.pubsub.provider.RetractEventProvider - - - - purge - http://jabber.org/protocol/pubsub#event - org.jivesoftware.smackx.pubsub.provider.SimpleNodeProvider - - - - - nick - http://jabber.org/protocol/nick - org.jivesoftware.smackx.packet.Nick$Provider - - - - - attention - urn:xmpp:attention:0 - org.jivesoftware.smackx.packet.AttentionExtension$Provider - - - - - received - urn:xmpp:receipts - org.jivesoftware.smackx.receipts.DeliveryReceipt$Provider - - - request - urn:xmpp:receipts - org.jivesoftware.smackx.receipts.DeliveryReceiptRequest$Provider - - - - - c - http://jabber.org/protocol/caps - org.jivesoftware.smackx.entitycaps.provider.CapsExtensionProvider - - - - - ping - urn:xmpp:ping - org.jivesoftware.smack.ping.provider.PingProvider - - - + + + + + + + query + jabber:iq:private + org.jivesoftware.smackx.PrivateDataManager$PrivateDataIQProvider + + + + + query + jabber:iq:time + org.jivesoftware.smackx.packet.Time + + + + + x + jabber:x:roster + org.jivesoftware.smackx.provider.RosterExchangeProvider + + + + + x + jabber:x:event + org.jivesoftware.smackx.provider.MessageEventProvider + + + + + active + http://jabber.org/protocol/chatstates + org.jivesoftware.smackx.packet.ChatStateExtension$Provider + + + + composing + http://jabber.org/protocol/chatstates + org.jivesoftware.smackx.packet.ChatStateExtension$Provider + + + + paused + http://jabber.org/protocol/chatstates + org.jivesoftware.smackx.packet.ChatStateExtension$Provider + + + + inactive + http://jabber.org/protocol/chatstates + org.jivesoftware.smackx.packet.ChatStateExtension$Provider + + + + gone + http://jabber.org/protocol/chatstates + org.jivesoftware.smackx.packet.ChatStateExtension$Provider + + + + + html + http://jabber.org/protocol/xhtml-im + org.jivesoftware.smackx.provider.XHTMLExtensionProvider + + + + + x + jabber:x:conference + org.jivesoftware.smackx.GroupChatInvitation$Provider + + + + + query + http://jabber.org/protocol/disco#items + org.jivesoftware.smackx.provider.DiscoverItemsProvider + + + + + query + http://jabber.org/protocol/disco#info + org.jivesoftware.smackx.provider.DiscoverInfoProvider + + + + + x + jabber:x:data + org.jivesoftware.smackx.provider.DataFormProvider + + + + + x + http://jabber.org/protocol/muc#user + org.jivesoftware.smackx.provider.MUCUserProvider + + + + + query + http://jabber.org/protocol/muc#admin + org.jivesoftware.smackx.provider.MUCAdminProvider + + + + + query + http://jabber.org/protocol/muc#owner + org.jivesoftware.smackx.provider.MUCOwnerProvider + + + + + x + jabber:x:delay + org.jivesoftware.smackx.provider.DelayInformationProvider + + + + delay + urn:xmpp:delay + org.jivesoftware.smackx.provider.DelayInfoProvider + + + + + query + jabber:iq:version + org.jivesoftware.smackx.packet.Version + + + + + vCard + vcard-temp + org.jivesoftware.smackx.provider.VCardProvider + + + + + offline + http://jabber.org/protocol/offline + org.jivesoftware.smackx.packet.OfflineMessageRequest$Provider + + + + + offline + http://jabber.org/protocol/offline + org.jivesoftware.smackx.packet.OfflineMessageInfo$Provider + + + + + query + jabber:iq:last + org.jivesoftware.smackx.packet.LastActivity$Provider + + + + + query + jabber:iq:search + org.jivesoftware.smackx.search.UserSearch$Provider + + + + + sharedgroup + http://www.jivesoftware.org/protocol/sharedgroup + org.jivesoftware.smackx.packet.SharedGroupsInfo$Provider + + + + + addresses + http://jabber.org/protocol/address + org.jivesoftware.smackx.provider.MultipleAddressesProvider + + + + + si + http://jabber.org/protocol/si + org.jivesoftware.smackx.provider.StreamInitiationProvider + + + + query + http://jabber.org/protocol/bytestreams + org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider + + + + open + http://jabber.org/protocol/ibb + org.jivesoftware.smackx.bytestreams.ibb.provider.OpenIQProvider + + + + data + http://jabber.org/protocol/ibb + org.jivesoftware.smackx.bytestreams.ibb.provider.DataPacketProvider + + + + close + http://jabber.org/protocol/ibb + org.jivesoftware.smackx.bytestreams.ibb.provider.CloseIQProvider + + + + data + http://jabber.org/protocol/ibb + org.jivesoftware.smackx.bytestreams.ibb.provider.DataPacketProvider + + + + + command + http://jabber.org/protocol/commands + org.jivesoftware.smackx.provider.AdHocCommandDataProvider + + + + bad-action + http://jabber.org/protocol/commands + org.jivesoftware.smackx.provider.AdHocCommandDataProvider$BadActionError + + + + malformed-actionn + http://jabber.org/protocol/commands + org.jivesoftware.smackx.provider.AdHocCommandDataProvider$MalformedActionError + + + + bad-locale + http://jabber.org/protocol/commands + org.jivesoftware.smackx.provider.AdHocCommandDataProvider$BadLocaleError + + + + bad-payload + http://jabber.org/protocol/commands + org.jivesoftware.smackx.provider.AdHocCommandDataProvider$BadPayloadError + + + + bad-sessionid + http://jabber.org/protocol/commands + org.jivesoftware.smackx.provider.AdHocCommandDataProvider$BadSessionIDError + + + + session-expired + http://jabber.org/protocol/commands + org.jivesoftware.smackx.provider.AdHocCommandDataProvider$SessionExpiredError + + + + + headers + http://jabber.org/protocol/shim + org.jivesoftware.smackx.provider.HeadersProvider + + + + header + http://jabber.org/protocol/shim + org.jivesoftware.smackx.provider.HeaderProvider + + + + + pubsub + http://jabber.org/protocol/pubsub + org.jivesoftware.smackx.pubsub.provider.PubSubProvider + + + + create + http://jabber.org/protocol/pubsub + org.jivesoftware.smackx.pubsub.provider.SimpleNodeProvider + + + + items + http://jabber.org/protocol/pubsub + org.jivesoftware.smackx.pubsub.provider.ItemsProvider + + + + item + http://jabber.org/protocol/pubsub + org.jivesoftware.smackx.pubsub.provider.ItemProvider + + + + subscriptions + http://jabber.org/protocol/pubsub + org.jivesoftware.smackx.pubsub.provider.SubscriptionsProvider + + + + subscription + http://jabber.org/protocol/pubsub + org.jivesoftware.smackx.pubsub.provider.SubscriptionProvider + + + + affiliations + http://jabber.org/protocol/pubsub + org.jivesoftware.smackx.pubsub.provider.AffiliationsProvider + + + + affiliation + http://jabber.org/protocol/pubsub + org.jivesoftware.smackx.pubsub.provider.AffiliationProvider + + + + options + http://jabber.org/protocol/pubsub + org.jivesoftware.smackx.pubsub.provider.FormNodeProvider + + + + + pubsub + http://jabber.org/protocol/pubsub#owner + org.jivesoftware.smackx.pubsub.provider.PubSubProvider + + + + configure + http://jabber.org/protocol/pubsub#owner + org.jivesoftware.smackx.pubsub.provider.FormNodeProvider + + + + default + http://jabber.org/protocol/pubsub#owner + org.jivesoftware.smackx.pubsub.provider.FormNodeProvider + + + + + event + http://jabber.org/protocol/pubsub#event + org.jivesoftware.smackx.pubsub.provider.EventProvider + + + + configuration + http://jabber.org/protocol/pubsub#event + org.jivesoftware.smackx.pubsub.provider.ConfigEventProvider + + + + delete + http://jabber.org/protocol/pubsub#event + org.jivesoftware.smackx.pubsub.provider.SimpleNodeProvider + + + + options + http://jabber.org/protocol/pubsub#event + org.jivesoftware.smackx.pubsub.provider.FormNodeProvider + + + + items + http://jabber.org/protocol/pubsub#event + org.jivesoftware.smackx.pubsub.provider.ItemsProvider + + + + item + http://jabber.org/protocol/pubsub#event + org.jivesoftware.smackx.pubsub.provider.ItemProvider + + + + retract + http://jabber.org/protocol/pubsub#event + org.jivesoftware.smackx.pubsub.provider.RetractEventProvider + + + + purge + http://jabber.org/protocol/pubsub#event + org.jivesoftware.smackx.pubsub.provider.SimpleNodeProvider + + + + + nick + http://jabber.org/protocol/nick + org.jivesoftware.smackx.packet.Nick$Provider + + + + + attention + urn:xmpp:attention:0 + org.jivesoftware.smackx.packet.AttentionExtension$Provider + + + + + received + urn:xmpp:receipts + org.jivesoftware.smackx.receipts.DeliveryReceipt$Provider + + + request + urn:xmpp:receipts + org.jivesoftware.smackx.receipts.DeliveryReceiptRequest$Provider + + + + + c + http://jabber.org/protocol/caps + org.jivesoftware.smackx.entitycaps.provider.CapsExtensionProvider + + + + + forwarded + urn:xmpp:forward:0 + org.jivesoftware.smackx.forward.provider.ForwardedProvider + + + diff --git a/build/resources/META-INF/jul.properties b/build/resources/META-INF/jul.properties new file mode 100644 index 000000000..fe90575ec --- /dev/null +++ b/build/resources/META-INF/jul.properties @@ -0,0 +1,3 @@ +# Java Util Logging configuration for Smack. +handlers = java.util.logging.ConsoleHandler +.level = WARNING \ No newline at end of file diff --git a/build/resources/META-INF/sample.providers b/build/resources/META-INF/sample.providers new file mode 100644 index 000000000..b13ddbdaa --- /dev/null +++ b/build/resources/META-INF/sample.providers @@ -0,0 +1,17 @@ + + + + + + element + ns + com.myco.MyIQProvider + + + + elem + http://jabber.org/protocol/whoknows + com.myco.MyExtProvider + + + diff --git a/build/resources/META-INF/smack-config.xml b/build/resources/META-INF/smack-config.xml index a4df4764c..7bfda704b 100644 --- a/build/resources/META-INF/smack-config.xml +++ b/build/resources/META-INF/smack-config.xml @@ -22,9 +22,12 @@ - org.jivesoftware.smackx.ServiceDiscoveryManager + org.jivesoftware.smack.provider.CoreInitializer + org.jivesoftware.smack.provider.VmArgInitializer org.jivesoftware.smack.PrivacyListManager org.jivesoftware.smack.keepalive.KeepAliveManager + org.jivesoftware.smackx.provider.ExtensionInitializer + org.jivesoftware.smackx.ServiceDiscoveryManager org.jivesoftware.smackx.XHTMLManager org.jivesoftware.smackx.muc.MultiUserChat org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager diff --git a/build/resources/releasedocs/README.html b/build/resources/releasedocs/README.html index f935622c9..242dcb007 100644 --- a/build/resources/releasedocs/README.html +++ b/build/resources/releasedocs/README.html @@ -148,7 +148,7 @@ hr { @version@ released: - @builddate@ + @releasedate@ diff --git a/build/resources/releasedocs/changelog.html b/build/resources/releasedocs/changelog.html index 8540a94dd..96e5dd8c2 100644 --- a/build/resources/releasedocs/changelog.html +++ b/build/resources/releasedocs/changelog.html @@ -140,6 +140,47 @@ hr {
+ +

3.4.0 -- Feb 2, 2014

+ +

Bug Fixes

+
    +
  • [SMACK-442] - Manager's should also handle connectionClosedOnError()
  • +
  • [SMACK-443] - ReconnectionSuccessful listeners are invoked twice on reconnection if connect() failed before
  • +
  • [SMACK-452] - PacketParserUtils.parseStreamError() is not aware of optional text element and therefore failes to parse stream error's correctly. Prevents ReconnectionManager from reconnecting.
  • +
  • [SMACK-458] - Smack's Managers should not remove itself when the connection is closed or should re-add themselfs if the connection get reconnected
  • +
  • [SMACK-462] - Prevent duplicate manager instances by using the manager's constructor in the ConnectionCreationListener's connectionCreated
  • +
  • [SMACK-463] - packet listeners silently fail when preceding listener caused exception
  • +
  • [SMACK-524] - Use correct block-size definition for IBB transfers
  • +
  • [SMACK-525] - NPE in XMPPConnection.notifyConnectionError
  • +
  • [SMACK-529] - Add support for XEP-0280 "Message Carbons"
  • +
  • [SMACK-530] - DNSUtilTest requires an internet connection to work, it should be moved to integration tests.
  • +
+ +

New Feature

+
    +
  • [SMACK-286] - Need to change ProviderManager to support loading smack.providers from alternative locations
  • +
  • [SMACK-387] - Allow configuration of ChatManager to be able to allow message handling to be customized.
  • +
  • [SMACK-403] - Add support for XEP-0297 "Stanza Forwarding"
  • +
  • [SMACK-434] - Create a project to contain non production ready implementations of specifications
  • +
+ +

Improvement

+
    +
  • [SMACK-343] - Make Smack jar an OSGi bundle.
  • +
  • [SMACK-381] - Separate the configuration for smack extension related classes from the smack jar.
  • +
  • [SMACK-444] - Allow 'null' for TruststorePath and TruststorePassword in ServerTrustManager
  • +
  • [SMACK-456] - Add the causing exception to the XMPPExceptions thrown in XMPPConnection
  • +
  • [SMACK-457] - Remove unnecessary printStackTrace() in XMPPConnection
  • +
  • [SMACK-460] - ServiceDiscoveryManager should not use the constructor in connectionCreated()
  • +
  • [SMACK-461] - Remove incorrect deprecated marker for DiscoverInfo.Identity.setType()
  • +
  • [SMACK-464] - Make it clear that PacketListener's added with Connection.addPacketListener() are only for received packets
  • +
  • [SMACK-534] - Convert all System.out and printStackTrace calls to use Java util logging.
  • +
  • [SMACK-339] - Allow ConnectionListeners to be added before Connection is connected. Currently throws exception
  • +
  • [SMACK-373] - Don't remove listeners after a disconnect() , keep state of Connection between disconnect() and connect()/login()
  • +
  • [SMACK-434] - Create a project to contain non production ready implementations of specifications
  • +
  • [SMACK-526] - Deprecate all PEP related classes.
  • +

3.3.1 -- Oct 6, 2013

diff --git a/documentation/gettingstarted.html b/documentation/gettingstarted.html index c6dd7d670..7c6d5725d 100644 --- a/documentation/gettingstarted.html +++ b/documentation/gettingstarted.html @@ -40,6 +40,37 @@ over which features applications require: +

Configuration

+Smack has an initialization process that involves 2 phases. +
    +
  • Initializing system properties - Initializing all the system properties accessible through the class +SmackConfiguration. These properties are retrieve by the getXXX methods on that class. +
  • Initializing startup classes - Initializing any classes meant to be active at startup by instantiating +the class, and then calling the initialize method on that class if it extends SmackInitializer. +If it does not extend this interface, then initialization will have to take place in a static block of code +which is automatically executed when the class is loaded. +
+

+Initialization is accomplished via a configuration file. By default, Smack will load the one embedded in +the Smack jar at META-INF/smack-config.xml. This particular configuration contains all the default +property values as well as a list of initializer classes to load. All manager type classes are contained +in this list of initializers. If your application does not use all the features provided by Smack via the +aforementioned managers, you may want to 'turn them off' by providing a custom config file that does not +include that feature. +

+If you want to change the configuration file used, you have two options: +

    +
  • Programmatically - Call the setConfigFileUrl method of SmackConfiguration with the location +of a new config file. +
    SmackConfiguration.setConfigFileUrl("classpath:test/smack-config.xml", null)
    +
  • VM Argument - Set the VM argument smack.config.file to the location of a new config file. +
    -Dsmack.config.file=file:///c:/com/myco/provider/myco_custom_config.xml
    +
+ +

+Please note, there is a copy of the smack-config.xml in the samples directory of the deployment +archive file (zip or tar). +

Establishing a Connection

diff --git a/documentation/providers.html b/documentation/providers.html index 229df7f8b..21f441b64 100644 --- a/documentation/providers.html +++ b/documentation/providers.html @@ -15,44 +15,68 @@ Provider Architecture: Packet Extensions and Custom IQ's

+

Introduction

The Smack provider architecture is a system for plugging in custom XML parsing of packet extensions and IQ packets. The standard Smack Extensions -are built using the provider architecture. Two types of -providers exist:
    +are built using the provider architecture. There are two types of +providers:
    • IQProvider -- parses IQ requests into Java objects. -
    • PacketExtension -- parses XML sub-documents attached to +
    • Extension Provider -- parses XML sub-documents attached to packets into PacketExtension instances.
    -

    IQProvider

    - -By default, Smack only knows how to process IQ packets with sub-packets that -are in a few namespaces such as:
      +By default, Smack only knows how to process a few standard packets and sub-packets +that are in a few namespaces such as:
      • jabber:iq:auth
      • jabber:iq:roster
      • jabber:iq:register
      -Because many more IQ types are part of XMPP and its extensions, a pluggable IQ parsing -mechanism is provided. IQ providers are registered programatically or by creating a -smack.providers file in the META-INF directory of your JAR file. The file is an XML -document that contains one or more iqProvider entries, as in the following example: +There are many more IQ types and extensions that are part of XMPP standards, and of +course an endless number that can be added as custom extensions. To support this, an +extensible parsing mechanism is provided via Smack and user build providers. +

      +Whenever a packet extension is found in a packet, parsing will +be passed to the correct provider. Each provider can either implement the +PacketExtensionProvider interface or be a standard Java Bean. In the +former case, each extension provider is responsible for parsing the raw +XML stream, via the XML Pull Parser, to contruct an object. In the latter case, bean introspection +is used to try to automatically set the properties of the class using +the values in the packet extension sub-element. +

      +When no extension provider is registered for an element name and +namespace combination, Smack will store all top-level elements of the +sub-packet in the DefaultPacketExtension object and then attach it to the packet. + +

      +Management of these providers is accomplished via the ProviderManager +class. There are multiple ways to add providers to the manager.

        +
      • Call addXXProvider methods - You can call the appropriate add methods directly. +
        +    ProviderManager.getInstance().addIQProvider("element", "namespace", new MyIQProvider());
        +    ProviderManager.getInstance().addExtensionProvider("element", "namespace", new MyExtProvider());
        +
        +
      • Add a loader - You can add a ProviderLoader which will inject a means of loading multiple +providers (both types) into the manager. This is the mechanism used by Smack to load from the +Smack specific file format (via ProviderFileLoader). Implementers can provide the means to load +providers from any source they wish, or simply reuse the ProviderFileLoader to load from +their own provider files. +
        +    ProviderManager.getInstance().addLoader(new ProviderFileLoader(FileUtils.getStreamForUrl("classpath:com/myco/provider/myco_custom.providers", null)));
        +
        +
      • VM Argument - You can add a provider file via the VM argument smack.provider.file. +This will load the file at the specified URL during startup when Smack initializes. +This also assumes the default configuration, since it requires that the VmArgInitializer was +part of the startup configuration.
        - <?xml version="1.0"?>
        - <smackProviders>
        -     <iqProvider>
        -         <elementName>query</elementName>
        -         <namespace>jabber:iq:time</namespace>
        -         <className>org.jivesoftware.smack.packet.Time</className>
        -     </iqProvider>
        - </smackProviders>
        + -Dsmack.provider.file=classpath:com/myco/provider/myco_custom.providers + or + -Dsmack.provider.file=file:///c:/myco/provider/myco_custom.providers + +
      -Each IQ provider is associated with an element name and a namespace. In the -example above, the element name is query and the namespace is -abber:iq:time. If multiple provider entries attempt to register to -handle the same namespace, the first entry loaded from the classpath will -take precedence.

      +

      IQ Providers

      The IQ provider class can either implement the IQProvider interface, or extend the IQ class. In the former case, each IQProvider is @@ -61,54 +85,191 @@ the latter case, bean introspection is used to try to automatically set properties of the IQ instance using the values found in the IQ packet XML. For example, an XMPP time packet resembles the following: +

      +Introspection +

      +Time Packet

      -<iq type='result' to='joe@example.com' from='mary@example.com' id='time_1'>
      -    <query xmlns='jabber:iq:time'>
      -        <utc>20020910T17:58:35</utc>
      -        <tz>MDT</tz>
      -        <display>Tue Sep 10 12:58:35 2002</display>
      -    </query>
      -</iq>
      + <iq type='result' to='joe@example.com' from='mary@example.com' id='time_1'> + <query xmlns='jabber:iq:time'> + <utc>20020910T17:58:35</utc> + <tz>MDT</tz> + <display>Tue Sep 10 12:58:35 2002</display> + </query> + </iq> + -In order for this packet to be automatically mapped to the Time object listed in the -providers file above, it must have the methods setUtc(String), setTz(String), and -setDisplay(String). The introspection service will automatically try to convert the String +

      +Time IQ Class +

      +    class Time extends IQ {
      +        private Date utc;
      +        private TimeZone timeZone;
      +        private String display;
      +
      +        @Override
      +        public String getChildElementXML() {
      +            return null;
      +        }
      +
      +        public void setUtc(String utcString) {
      +            try {
      +                utc = StringUtils.parseDate(utcString);
      +            } catch (ParseException e) {
      +            }
      +        }
      +
      +        public void setTimeZone(String zone) {
      +            timeZone = TimeZone.getTimeZone(zone);
      +        }
      +
      +        public void setDisplay(String timeDisplay) {
      +            display = timeDisplay;
      +        }
      +    }
      +
      + +The introspection service will automatically try to convert the String value from the XML into a boolean, int, long, float, double, or Class depending on the -type the IQ instance expects.

      +type the IQ instance expects. -

      PacketExtensionProvider

      +

      +IQProvider Implementation +

      +Disco Items Packet +

      +    <iq type='result' from='shakespeare.lit' to='romeo@montague.net/orchard' id='items1'>
      +       <query xmlns='http://jabber.org/protocol/disco#items'>
      +           <item jid='people.shakespeare.lit' name='Directory of Characters'/>
      +           <item jid='plays.shakespeare.lit' name='Play-Specific Chatrooms'/>
      +           <item jid='mim.shakespeare.lit' name='Gateway to Marlowe IM'/>
      +           <item jid='words.shakespeare.lit' name='Shakespearean Lexicon'/>
      +           <item jid='globe.shakespeare.lit' name='Calendar of Performances'/>
      +           <item jid='headlines.shakespeare.lit' name='Latest Shakespearean News'/>
      +           <item jid='catalog.shakespeare.lit' name='Buy Shakespeare Stuff!'/>
      +           <item jid='en2fr.shakespeare.lit' name='French Translation Service'/>
      +       </query>
      +    </iq>
      +
      -Packet extension providers provide a pluggable system for -packet extensions, which are child elements in a custom namespace -of IQ, message and presence packets. -Each extension provider is registered with an element name and namespace -in the smack.providers file as in the following example: +

      +Disco Items IQProvider +

      +    public class DiscoverItemsProvider implements IQProvider {
      +
      +        public IQ parseIQ(XmlPullParser parser) throws Exception {
      +            DiscoverItems discoverItems = new DiscoverItems();
      +            boolean done = false;
      +            DiscoverItems.Item item;
      +            String jid = "";
      +            String name = "";
      +            String action = "";
      +            String node = "";
      +            discoverItems.setNode(parser.getAttributeValue("", "node"));
      +            while (!done) {
      +                int eventType = parser.next();
      +	
      +                if (eventType == XmlPullParser.START_TAG && "item".equals(parser.getName())) {
      +                    // Initialize the variables from the parsed XML
      +                    jid = parser.getAttributeValue("", "jid");
      +                    name = parser.getAttributeValue("", "name");
      +                    node = parser.getAttributeValue("", "node");
      +                    action = parser.getAttributeValue("", "action");
      +                }
      +                else if (eventType == XmlPullParser.END_TAG && "item".equals(parser.getName())) {
      +                    // Create a new Item and add it to DiscoverItems.
      +                    item = new DiscoverItems.Item(jid);
      +                    item.setName(name);
      +                    item.setNode(node);
      +                    item.setAction(action);
      +                    discoverItems.addItem(item);
      +                }
      +                else if (eventType == XmlPullParser.END_TAG && "query".equals(parser.getName())) {
      +                    done = true;
      +                }
      +            }
      +            return discoverItems;
      +        }
      +    }
      +
      + +

      Extension Providers

      + +Packet extension providers are responsible for parsing packet extensions, which are +child elements in a custom namespace of IQ, message and presence packets. +

      +Pubsub Subscription Packet

      -<?xml version="1.0"?>
      -<smackProviders>
      +   <iq type='result' from='pubsub.shakespeare.lit' to='francisco@denmark.lit/barracks' id='sub1'>
      +       <pubsub xmlns='http://jabber.org/protocol/pubsub'>
      +           <subscription node='princely_musings' jid='francisco@denmark.lit' subscription='unconfigured'>
      +               <subscribe-options>
      +                   <required/>
      +               </subscribe-options>
      +           </subscription>
      +       </pubsub>
      +    </iq>
      +
      + +

      +Subscription PacketExtensionProvider Implementation + +

      +    public class SubscriptionProvider implements PacketExtensionProvider {
      +        public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
      +            String jid = parser.getAttributeValue(null, "jid");
      +            String nodeId = parser.getAttributeValue(null, "node");
      +            String subId = parser.getAttributeValue(null, "subid");
      +            String state = parser.getAttributeValue(null, "subscription");
      +            boolean isRequired = false;
      +
      +            int tag = parser.next();
      +
      +            if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("subscribe-options")) {
      +                tag = parser.next();
      +	
      +                if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("required"))
      +                    isRequired = true;
      +			
      +                while (parser.next() != XmlPullParser.END_TAG && parser.getName() != "subscribe-options");
      +            }
      +            while (parser.getEventType() != XmlPullParser.END_TAG) parser.next();
      +            return new Subscription(jid, nodeId, subId, (state == null ? null : Subscription.State.valueOf(state)), isRequired);
      +        }
      +    }
      +
      + +

      Provider file format

      + +This is the format for a provider file which can be parsed by the ProviderFileLoader. +
      + <?xml version="1.0"?>
      + <smackProviders>
      +     <iqProvider>
      +         <elementName>query</elementName>
      +         <namespace>jabber:iq:time</namespace>
      +         <className>org.jivesoftware.smack.packet.Time</className>
      +     </iqProvider>
      +     
      +     <iqProvider>
      +         <elementName>query</elementName>
      +         <namespace>http://jabber.org/protocol/disco#items</namespace>
      +         <className>org.jivesoftware.smackx.provider.DiscoverItemsProvider</className>
      +     </iqProvider>
      +
           <extensionProvider>
      -        <elementName>x</elementName>
      -        <namespace>jabber:iq:event</namespace>
      -        <className>org.jivesoftware.smack.packet.MessageEvent</className>
      +        <elementName>subscription</elementName>
      +        <namespace>http://jabber.org/protocol/pubsub</namespace>
      +        <className>org.jivesoftware.smackx.pubsub.provider.SubscriptionProvider</className>
           </extensionProvider>
      -</smackProviders>
      + </smackProviders> -If multiple provider entries attempt to register to handle the same element -name and namespace, the first entry loaded from the classpath will take -precedence.

      +Each provider is associated with an element name and a namespace. If multiple provider entries attempt to register to +handle the same namespace, the last entry added to the ProviderManager will overwrite any other that was loaded +before it. +

      -Whenever a packet extension is found in a packet, parsing will -be passed to the correct provider. Each provider can either implement the -PacketExtensionProvider interface or be a standard Java Bean. In the -former case, each extension provider is responsible for parsing the raw -XML stream to contruct an object. In the latter case, bean introspection -is used to try to automatically set the properties of the class using -the values in the packet extension sub-element.

      - -When an extension provider is not registered for an element name and -namespace combination, Smack will store all top-level elements of the -sub-packet in DefaultPacketExtension object and then attach it to the packet.


      diff --git a/experimental/resources/META-INF/experimental.providers b/experimental/resources/META-INF/experimental.providers new file mode 100644 index 000000000..5acbc0018 --- /dev/null +++ b/experimental/resources/META-INF/experimental.providers @@ -0,0 +1,17 @@ + + + + + + + sent + urn:xmpp:carbons:2 + org.jivesoftware.smackx.carbons.provider.CarbonManagerProvider + + + received + urn:xmpp:carbons:2 + org.jivesoftware.smackx.carbons.provider.CarbonManagerProvider + + + diff --git a/experimental/source/org/jivesoftware/smackx/carbons/Carbon.java b/experimental/source/org/jivesoftware/smackx/carbons/Carbon.java new file mode 100644 index 000000000..39c188851 --- /dev/null +++ b/experimental/source/org/jivesoftware/smackx/carbons/Carbon.java @@ -0,0 +1,117 @@ +/** + * Copyright 2013 Georg Lukas + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.carbons; + +import org.jivesoftware.smack.packet.PacketExtension; +import org.jivesoftware.smackx.forward.Forwarded; + +/** + * Packet extension for XEP-0280: Message Carbons. The extension + * XEP-0280 is + * meant to synchronize a message flow to multiple presences of a user. + * + *

      + * It accomplishes this by wrapping a {@link Forwarded} packet in a sent + * or received element + * + * @author Georg Lukas + */ +public class Carbon implements PacketExtension { + public static final String NAMESPACE = "urn:xmpp:carbons:2"; + + private Direction dir; + private Forwarded fwd; + + /** + * Construct a Carbon message extension. + * + * @param dir Determines if the carbon is being sent/received + * @param fwd The forwarded message. + */ + public Carbon(Direction dir, Forwarded fwd) { + this.dir = dir; + this.fwd = fwd; + } + + /** + * Get the direction (sent or received) of the carbon. + * + * @return the {@link Direction} of the carbon. + */ + public Direction getDirection() { + return dir; + } + + /** + * Get the forwarded packet. + * + * @return the {@link Forwarded} message contained in this Carbon. + */ + public Forwarded getForwarded() { + return fwd; + } + + @Override + public String getElementName() { + return dir.toString(); + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String toXML() { + StringBuilder buf = new StringBuilder(); + buf.append("<").append(getElementName()).append(" xmlns=\"") + .append(getNamespace()).append("\">"); + + buf.append(fwd.toXML()); + + buf.append(""); + return buf.toString(); + } + + /** + * Defines the direction of a {@link Carbon} message. + */ + public static enum Direction { + received, + sent + } + + /** + * Packet extension indicating that a message may not be carbon-copied. Adding this + * extension to any message will disallow that message from being copied. + */ + public static class Private implements PacketExtension { + public static final String ELEMENT = "private"; + + public String getElementName() { + return ELEMENT; + } + + public String getNamespace() { + return Carbon.NAMESPACE; + } + + public String toXML() { + return "<" + ELEMENT + " xmlns=\"" + Carbon.NAMESPACE + "\"/>"; + } + } +} diff --git a/experimental/source/org/jivesoftware/smackx/carbons/CarbonManager.java b/experimental/source/org/jivesoftware/smackx/carbons/CarbonManager.java new file mode 100644 index 000000000..9217860ce --- /dev/null +++ b/experimental/source/org/jivesoftware/smackx/carbons/CarbonManager.java @@ -0,0 +1,213 @@ +/** + * Copyright 2013 Georg Lukas + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.carbons; + +import java.util.Collections; +import java.util.Map; +import java.util.WeakHashMap; + +import org.jivesoftware.smack.Connection; +import org.jivesoftware.smack.ConnectionCreationListener; +import org.jivesoftware.smack.PacketCollector; +import org.jivesoftware.smack.PacketListener; +import org.jivesoftware.smack.SmackConfiguration; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.filter.PacketIDFilter; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Packet; +import org.jivesoftware.smackx.ServiceDiscoveryManager; +import org.jivesoftware.smackx.packet.DiscoverInfo; + +/** + * Packet extension for XEP-0280: Message Carbons. This class implements + * the manager for registering {@link Carbon} support, enabling and disabling + * message carbons. + * + * You should call enableCarbons() before sending your first undirected + * presence. + * + * @author Georg Lukas + */ +public class CarbonManager { + + private static Map instances = + Collections.synchronizedMap(new WeakHashMap()); + + static { + Connection.addConnectionCreationListener(new ConnectionCreationListener() { + public void connectionCreated(Connection connection) { + new CarbonManager(connection); + } + }); + } + + private Connection connection; + private volatile boolean enabled_state = false; + + private CarbonManager(Connection connection) { + ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); + sdm.addFeature(Carbon.NAMESPACE); + this.connection = connection; + instances.put(connection, this); + } + + /** + * Obtain the CarbonManager responsible for a connection. + * + * @param connection the connection object. + * + * @return a CarbonManager instance + */ + public static CarbonManager getInstanceFor(Connection connection) { + CarbonManager carbonManager = instances.get(connection); + + if (carbonManager == null) { + carbonManager = new CarbonManager(connection); + } + + return carbonManager; + } + + private IQ carbonsEnabledIQ(final boolean new_state) { + IQ setIQ = new IQ() { + public String getChildElementXML() { + return "<" + (new_state? "enable" : "disable") + " xmlns='" + Carbon.NAMESPACE + "'/>"; + } + }; + setIQ.setType(IQ.Type.SET); + return setIQ; + } + + /** + * Returns true if XMPP Carbons are supported by the server. + * + * @return true if supported + */ + public boolean isSupportedByServer() { + try { + DiscoverInfo result = ServiceDiscoveryManager + .getInstanceFor(connection).discoverInfo(connection.getServiceName()); + return result.containsFeature(Carbon.NAMESPACE); + } + catch (XMPPException e) { + return false; + } + } + + /** + * Notify server to change the carbons state. This method returns + * immediately and changes the variable when the reply arrives. + * + * You should first check for support using isSupportedByServer(). + * + * @param new_state whether carbons should be enabled or disabled + */ + public void sendCarbonsEnabled(final boolean new_state) { + IQ setIQ = carbonsEnabledIQ(new_state); + + connection.addPacketListener(new PacketListener() { + public void processPacket(Packet packet) { + IQ result = (IQ)packet; + if (result.getType() == IQ.Type.RESULT) { + enabled_state = new_state; + } + connection.removePacketListener(this); + } + }, new PacketIDFilter(setIQ.getPacketID())); + + connection.sendPacket(setIQ); + } + + /** + * Notify server to change the carbons state. This method blocks + * some time until the server replies to the IQ and returns true on + * success. + * + * You should first check for support using isSupportedByServer(). + * + * @param new_state whether carbons should be enabled or disabled + * + * @return true if the operation was successful + */ + public boolean setCarbonsEnabled(final boolean new_state) { + if (enabled_state == new_state) + return true; + + IQ setIQ = carbonsEnabledIQ(new_state); + + PacketCollector collector = + connection.createPacketCollector(new PacketIDFilter(setIQ.getPacketID())); + connection.sendPacket(setIQ); + IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); + collector.cancel(); + + if (result != null && result.getType() == IQ.Type.RESULT) { + enabled_state = new_state; + return true; + } + return false; + } + + /** + * Helper method to enable carbons. + * + * @return true if the operation was successful + */ + public boolean enableCarbons() { + return setCarbonsEnabled(true); + } + + /** + * Helper method to disable carbons. + * + * @return true if the operation was successful + */ + public boolean disableCarbons() { + return setCarbonsEnabled(false); + } + + /** + * Check if carbons are enabled on this connection. + */ + public boolean getCarbonsEnabled() { + return this.enabled_state; + } + + /** + * Obtain a Carbon from a message, if available. + * + * @param msg Message object to check for carbons + * + * @return a Carbon if available, null otherwise. + */ + public static Carbon getCarbon(Message msg) { + Carbon cc = (Carbon)msg.getExtension("received", Carbon.NAMESPACE); + if (cc == null) + cc = (Carbon)msg.getExtension("sent", Carbon.NAMESPACE); + return cc; + } + + /** + * Mark a message as "private", so it will not be carbon-copied. + * + * @param msg Message object to mark private + */ + public static void disableCarbons(Message msg) { + msg.addExtension(new Carbon.Private()); + } +} diff --git a/experimental/source/org/jivesoftware/smackx/carbons/provider/CarbonManagerProvider.java b/experimental/source/org/jivesoftware/smackx/carbons/provider/CarbonManagerProvider.java new file mode 100644 index 000000000..f76f33b18 --- /dev/null +++ b/experimental/source/org/jivesoftware/smackx/carbons/provider/CarbonManagerProvider.java @@ -0,0 +1,53 @@ +/** + * Copyright 2013 Georg Lukas + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.carbons.provider; + +import org.jivesoftware.smack.packet.PacketExtension; +import org.jivesoftware.smack.provider.PacketExtensionProvider; +import org.jivesoftware.smack.util.PacketParserUtils; +import org.jivesoftware.smackx.carbons.Carbon; +import org.jivesoftware.smackx.carbons.Carbon.Direction; +import org.jivesoftware.smackx.forward.Forwarded; +import org.xmlpull.v1.XmlPullParser; + +/** + * This class implements the {@link PacketExtensionProvider} to parse + * cabon copied messages from a packet. It will return a {@link Carbon} packet extension. + * + * @author Georg Lukas + * + */ +public class CarbonManagerProvider implements PacketExtensionProvider { + + public PacketExtension parseExtension(XmlPullParser parser) throws Exception { + Direction dir = Direction.valueOf(parser.getName()); + Forwarded fwd = null; + + boolean done = false; + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG && parser.getName().equals("forwarded")) { + fwd = (Forwarded) PacketParserUtils.parsePacketExtension(Forwarded.ELEMENT_NAME, Forwarded.NAMESPACE, parser); + } + else if (eventType == XmlPullParser.END_TAG && dir == Direction.valueOf(parser.getName())) + done = true; + } + if (fwd == null) + throw new Exception("sent/received must contain exactly one tag"); + return new Carbon(dir, fwd); + } +} diff --git a/experimental/source/org/jivesoftware/smackx/experimental/ExperimentalProviderInitializer.java b/experimental/source/org/jivesoftware/smackx/experimental/ExperimentalProviderInitializer.java new file mode 100644 index 000000000..6d8abbc20 --- /dev/null +++ b/experimental/source/org/jivesoftware/smackx/experimental/ExperimentalProviderInitializer.java @@ -0,0 +1,33 @@ +/** + * Copyright 2013 Robin Collier + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.experimental; + +import org.jivesoftware.smack.provider.UrlProviderFileInitializer; + +/** + * Initializes the providers in the experimental code stream. + * + * @author Robin Collier + * + */ +public class ExperimentalProviderInitializer extends UrlProviderFileInitializer { + + @Override + protected String getFilePath() { + return "classpath:META-INF/experimental.providers"; + } +} diff --git a/experimental/test/org/jivesoftware/smackx/carbons/CarbonTest.java b/experimental/test/org/jivesoftware/smackx/carbons/CarbonTest.java new file mode 100644 index 000000000..f07afba57 --- /dev/null +++ b/experimental/test/org/jivesoftware/smackx/carbons/CarbonTest.java @@ -0,0 +1,110 @@ +/** + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smackx.carbons; + +import static org.junit.Assert.assertEquals; + +import java.util.Properties; + +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.smack.test.util.TestUtils; +import org.jivesoftware.smackx.carbons.provider.CarbonManagerProvider; +import org.jivesoftware.smackx.forward.Forwarded; +import org.jivesoftware.smackx.forward.provider.ForwardedProvider; +import org.junit.BeforeClass; +import org.junit.Test; +import org.xmlpull.v1.XmlPullParser; + +import com.jamesmurty.utils.XMLBuilder; + +public class CarbonTest { + + private static Properties outputProperties = new Properties(); + static { + outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes"); + } + + @BeforeClass + public static void setup() { + ProviderManager.getInstance().addExtensionProvider("forwarded", "urn:xmpp:forward:0", new ForwardedProvider()); + } + + @Test + public void carbonSentTest() throws Exception { + XmlPullParser parser; + String control; + Carbon cc; + Forwarded fwd; + + control = XMLBuilder.create("sent") + .e("forwarded") + .a("xmlns", "urn:xmpp:forwarded:0") + .e("message") + .a("from", "romeo@montague.com") + .asString(outputProperties); + + parser = TestUtils.getParser(control, "sent"); + cc = (Carbon) new CarbonManagerProvider().parseExtension(parser); + fwd = cc.getForwarded(); + + // meta + assertEquals(Carbon.Direction.sent, cc.getDirection()); + + // no delay in packet + assertEquals(null, fwd.getDelayInfo()); + + // check message + assertEquals("romeo@montague.com", fwd.getForwardedPacket().getFrom()); + + // check end of tag + assertEquals(XmlPullParser.END_TAG, parser.getEventType()); + assertEquals("sent", parser.getName()); + } + + @Test + public void carbonReceivedTest() throws Exception { + XmlPullParser parser; + String control; + Carbon cc; + + control = XMLBuilder.create("received") + .e("forwarded") + .a("xmlns", "urn:xmpp:forwarded:0") + .e("message") + .a("from", "romeo@montague.com") + .asString(outputProperties); + + parser = TestUtils.getParser(control, "received"); + cc = (Carbon) new CarbonManagerProvider().parseExtension(parser); + + assertEquals(Carbon.Direction.received, cc.getDirection()); + + // check end of tag + assertEquals(XmlPullParser.END_TAG, parser.getEventType()); + assertEquals("received", parser.getName()); + } + + @Test(expected=Exception.class) + public void carbonEmptyTest() throws Exception { + XmlPullParser parser; + String control; + + control = XMLBuilder.create("sent") + .a("xmlns", "urn:xmpp:forwarded:0") + .asString(outputProperties); + + parser = TestUtils.getParser(control, "sent"); + new CarbonManagerProvider().parseExtension(parser); + } +} diff --git a/source/org/jivesoftware/smack/AccountManager.java b/source/org/jivesoftware/smack/AccountManager.java index aa71c07ec..b90391c4b 100644 --- a/source/org/jivesoftware/smack/AccountManager.java +++ b/source/org/jivesoftware/smack/AccountManager.java @@ -32,6 +32,8 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Allows creation and management of accounts on an XMPP server. @@ -40,7 +42,8 @@ import java.util.Map; * @author Matt Tucker */ public class AccountManager { - + private static Logger logger = Logger.getLogger(AccountManager.class.getName()); + private Connection connection; private Registration info = null; @@ -134,7 +137,7 @@ public class AccountManager { } } catch (XMPPException xe) { - xe.printStackTrace(); + logger.log(Level.SEVERE, "Error retrieving account attributes from server", xe); } return Collections.emptySet(); } @@ -155,7 +158,7 @@ public class AccountManager { return info.getAttributes().get(name); } catch (XMPPException xe) { - xe.printStackTrace(); + logger.log(Level.SEVERE, "Error retrieving account attribute " + name + " info from server", xe); } return null; } @@ -175,6 +178,7 @@ public class AccountManager { return info.getInstructions(); } catch (XMPPException xe) { + logger.log(Level.SEVERE, "Error retrieving account instructions from server", xe); return null; } } diff --git a/source/org/jivesoftware/smack/Chat.java b/source/org/jivesoftware/smack/Chat.java index 66f5a54ba..c4ec1726d 100644 --- a/source/org/jivesoftware/smack/Chat.java +++ b/source/org/jivesoftware/smack/Chat.java @@ -170,7 +170,19 @@ public class Chat { } } - + @Override + public String toString() { + return "Chat [(participant=" + participant + "), (thread=" + threadID + ")]"; + } + + @Override + public int hashCode() { + int hash = 1; + hash = hash * 31 + threadID.hashCode(); + hash = hash * 31 + participant.hashCode(); + return hash; + } + @Override public boolean equals(Object obj) { return obj instanceof Chat diff --git a/source/org/jivesoftware/smack/ChatManager.java b/source/org/jivesoftware/smack/ChatManager.java index 1523b4fdc..90e68ab82 100644 --- a/source/org/jivesoftware/smack/ChatManager.java +++ b/source/org/jivesoftware/smack/ChatManager.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.WeakHashMap; import java.util.concurrent.CopyOnWriteArraySet; @@ -33,39 +34,59 @@ import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.filter.ThreadFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; +import org.jivesoftware.smack.packet.Message.Type; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.collections.ReferenceMap; /** * The chat manager keeps track of references to all current chats. It will not hold any references - * in memory on its own so it is neccesary to keep a reference to the chat object itself. To be + * in memory on its own so it is necessary to keep a reference to the chat object itself. To be * made aware of new chats, register a listener by calling {@link #addChatListener(ChatManagerListener)}. * * @author Alexander Wenckus */ public class ChatManager { - - /** - * Returns the next unique id. Each id made up of a short alphanumeric - * prefix along with a unique numeric value. - * - * @return the next id. + /* + * Sets the default behaviour for allowing 'normal' messages to be used in chats. As some clients don't set + * the message type to chat, the type normal has to be accepted to allow chats with these clients. */ - private static synchronized String nextID() { - return prefix + Long.toString(id++); + private static boolean defaultIsNormalInclude = true; + + /* + * Sets the default behaviour for how to match chats when there is NO thread id in the incoming message. + */ + private static MatchMode defaultMatchMode = MatchMode.BARE_JID; + + /** + * Defines the different modes under which a match will be attempted with an existing chat when + * the incoming message does not have a thread id. + */ + public enum MatchMode { + /** + * Will not attempt to match, always creates a new chat. + */ + NONE, + /** + * Will match on the JID in the from field of the message. + */ + SUPPLIED_JID, + /** + * Will attempt to match on the JID in the from field, and then attempt the base JID if no match was found. + * This is the most lenient matching. + */ + BARE_JID; } - - /** - * A prefix helps to make sure that ID's are unique across mutliple instances. + + /* + * Determines whether incoming messages of type normal can create chats. */ - private static String prefix = StringUtils.randomString(5); - - /** - * Keeps track of the current increment, which is appended to the prefix to - * forum a unique ID. + private boolean normalIncluded = defaultIsNormalInclude; + + /* + * Determines how incoming message with no thread will be matched to existing chats. */ - private static long id = 0; - + private MatchMode matchMode = defaultMatchMode; + /** * Maps thread ID to chat. */ @@ -101,11 +122,11 @@ public class ChatManager { return false; } Message.Type messageType = ((Message) packet).getType(); - return messageType != Message.Type.groupchat && - messageType != Message.Type.headline; + return (messageType == Type.chat) || (normalIncluded ? messageType == Type.normal : false); } }; - // Add a listener for all message packets so that we can deliver errant + + // Add a listener for all message packets so that we can deliver // messages to the best Chat instance available. connection.addPacketListener(new PacketListener() { public void processPacket(Packet packet) { @@ -116,10 +137,6 @@ public class ChatManager { } else { chat = getThreadChat(message.getThread()); - if (chat == null) { - // Try to locate the chat based on the sender of the message - chat = getUserChat(message.getFrom()); - } } if(chat == null) { @@ -130,6 +147,44 @@ public class ChatManager { }, filter); } + /** + * Determines whether incoming messages of type normal will be used for creating new chats or matching + * a message to existing ones. + * + * @return true if normal is allowed, false otherwise. + */ + public boolean isNormalIncluded() { + return normalIncluded; + } + + /** + * Sets whether to allow incoming messages of type normal to be used for creating new chats or matching + * a message to an existing one. + * + * @param normalIncluded true to allow normal, false otherwise. + */ + public void setNormalIncluded(boolean normalIncluded) { + this.normalIncluded = normalIncluded; + } + + /** + * Gets the current mode for matching messages with NO thread id to existing chats. + * + * @return The current mode. + */ + public MatchMode getMatchMode() { + return matchMode; + } + + /** + * Sets the mode for matching messages with NO thread id to existing chats. + * + * @param matchMode The mode to set. + */ + public void setMatchMode(MatchMode matchMode) { + this.matchMode = matchMode; + } + /** * Creates a new chat and returns it. * @@ -138,12 +193,7 @@ public class ChatManager { * @return the created chat. */ public Chat createChat(String userJID, MessageListener listener) { - String threadID; - do { - threadID = nextID(); - } while (threadChats.get(threadID) != null); - - return createChat(userJID, threadID, listener); + return createChat(userJID, null, listener); } /** @@ -155,7 +205,7 @@ public class ChatManager { * @return the created chat. */ public Chat createChat(String userJID, String thread, MessageListener listener) { - if(thread == null) { + if (thread == null) { thread = nextID(); } Chat chat = threadChats.get(thread); @@ -191,20 +241,25 @@ public class ChatManager { } /** - * Try to get a matching chat for the given user JID. Try the full - * JID map first, the try to match on the base JID if no match is - * found. + * Try to get a matching chat for the given user JID, based on the {@link MatchMode}. + *

    • NONE - return null + *
    • SUPPLIED_JID - match the jid in the from field of the message exactly. + *
    • BARE_JID - if not match for from field, try the bare jid. * - * @param userJID - * @return + * @param userJID jid in the from field of message. + * @return Matching chat, or null if no match found. */ private Chat getUserChat(String userJID) { - Chat match = jidChats.get(userJID); + if (matchMode == MatchMode.NONE) { + return null; + } + + Chat match = jidChats.get(userJID); - if (match == null) { - match = baseJidChats.get(StringUtils.parseBareAddress(userJID)); - } - return match; + if (match == null && (matchMode == MatchMode.BARE_JID)) { + match = baseJidChats.get(StringUtils.parseBareAddress(userJID)); + } + return match; } public Chat getThreadChat(String thread) { @@ -278,4 +333,21 @@ public class ChatManager { interceptors.put(packetInterceptor, filter); } } + + /** + * Returns a unique id. + * + * @return the next id. + */ + private static String nextID() { + return UUID.randomUUID().toString(); + } + + public static void setDefaultMatchMode(MatchMode mode) { + defaultMatchMode = mode; + } + + public static void setDefaultIsNormalIncluded(boolean allowNormal) { + defaultIsNormalInclude = allowNormal; + } } diff --git a/source/org/jivesoftware/smack/Connection.java b/source/org/jivesoftware/smack/Connection.java index d1d9cd41b..bd289e34a 100644 --- a/source/org/jivesoftware/smack/Connection.java +++ b/source/org/jivesoftware/smack/Connection.java @@ -34,6 +34,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; import org.jivesoftware.smack.compression.JzlibInputOutputStream; import org.jivesoftware.smack.compression.XMPPInputOutputStream; @@ -83,7 +84,8 @@ import org.jivesoftware.smack.packet.Presence; * @author Guenther Niess */ public abstract class Connection { - + private static Logger log = Logger.getLogger(Connection.class.getName()); + /** * Counter to uniquely identify connections that are created. */ @@ -593,10 +595,14 @@ public abstract class Connection { } /** - * Registers a packet listener with this connection. A packet filter determines + * Registers a packet listener with this connection. A packet listener will be invoked only + * when an incoming packet is received. A packet filter determines * which packets will be delivered to the listener. If the same packet listener * is added again with a different filter, only the new filter will be used. * + *

      + * NOTE: If you want get a similar callback for outgoing packets, see {@link #addPacketInterceptor(PacketInterceptor, PacketFilter)}. + * * @param packetListener the packet listener to notify of new received packets. * @param packetFilter the packet filter to use. */ @@ -681,6 +687,9 @@ public abstract class Connection { * invoked every time a packet is about to be sent by this connection. Interceptors * may modify the packet to be sent. A packet filter determines which packets * will be delivered to the interceptor. + * + *

      + * NOTE: For a similar functionality on incoming packets, see {@link #addPacketListener(PacketListener, PacketFilter)}. * * @param packetInterceptor the packet interceptor to notify of packets about to be sent. * @param packetFilter the packet filter to use. @@ -757,7 +766,7 @@ public abstract class Connection { debuggerClass = Class.forName(className); } catch (Exception e) { - e.printStackTrace(); + log.warning("Unabled to instantiate debugger class " + className); } } if (debuggerClass == null) { @@ -771,7 +780,7 @@ public abstract class Connection { Class.forName("org.jivesoftware.smack.debugger.LiteDebugger"); } catch (Exception ex2) { - ex2.printStackTrace(); + log.warning("Unabled to instantiate either Smack debugger class"); } } } diff --git a/source/org/jivesoftware/smack/LoggingInitializer.java b/source/org/jivesoftware/smack/LoggingInitializer.java new file mode 100644 index 000000000..ddc49d461 --- /dev/null +++ b/source/org/jivesoftware/smack/LoggingInitializer.java @@ -0,0 +1,28 @@ +package org.jivesoftware.smack; + +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.Logger; + +import org.jivesoftware.smack.util.FileUtils; + +/** + * Initializes the Java logging system. + * + * @author Robin Collier + * + */ +public class LoggingInitializer implements SmackInitializer { + + private static Logger log = Logger.getLogger(LoggingInitializer.class.getName()); + + @Override + public void initialize() { + try { + LogManager.getLogManager().readConfiguration(FileUtils.getStreamForUrl("classpath:META-INF/jul.properties", null)); + } + catch (Exception e) { + log .log(Level.WARNING, "Could not initialize Java Logging from default file.", e); + } + } +} diff --git a/source/org/jivesoftware/smack/PacketReader.java b/source/org/jivesoftware/smack/PacketReader.java index 3aaad38c6..a00f53c5a 100644 --- a/source/org/jivesoftware/smack/PacketReader.java +++ b/source/org/jivesoftware/smack/PacketReader.java @@ -34,6 +34,8 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.util.concurrent.*; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Listens for XML traffic from the XMPP server and parses it into packet objects. @@ -45,6 +47,8 @@ import java.util.concurrent.*; */ class PacketReader { + private static Logger log = Logger.getLogger(PacketReader.class.getName()); + private Thread readerThread; private ExecutorService listenerExecutor; @@ -134,7 +138,7 @@ class PacketReader { catch (Exception e) { // Catch and print any exception so we can recover // from a faulty listener and finish the shutdown process - e.printStackTrace(); + log.log(Level.SEVERE, "Error in listener while closing connection", e); } } } @@ -156,7 +160,7 @@ class PacketReader { parser.setInput(connection.reader); } catch (XmlPullParserException xppe) { - xppe.printStackTrace(); + log.log(Level.WARNING, "Error while resetting parser", xppe); } } @@ -451,8 +455,7 @@ class PacketReader { try { listenerWrapper.notifyListener(packet); } catch (Exception e) { - System.err.println("Exception in packet listener: " + e); - e.printStackTrace(); + log.log(Level.SEVERE, "Exception in packet listener", e); } } } diff --git a/source/org/jivesoftware/smack/PacketWriter.java b/source/org/jivesoftware/smack/PacketWriter.java index 7e347cb7d..6529ce330 100644 --- a/source/org/jivesoftware/smack/PacketWriter.java +++ b/source/org/jivesoftware/smack/PacketWriter.java @@ -26,6 +26,8 @@ import java.io.IOException; import java.io.Writer; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Writes packets to a XMPP server. Packets are sent using a dedicated thread. Packet @@ -38,7 +40,8 @@ import java.util.concurrent.BlockingQueue; * @author Matt Tucker */ class PacketWriter { - + private static Logger log = Logger.getLogger(PacketWriter.class.getName()); + private Thread writerThread; private Writer writer; private XMPPConnection connection; @@ -88,7 +91,7 @@ class PacketWriter { queue.put(packet); } catch (InterruptedException ie) { - ie.printStackTrace(); + log.log(Level.SEVERE, "Failed to queue packet to send to server: " + packet.toString(), ie); return; } synchronized (queue) { @@ -165,14 +168,14 @@ class PacketWriter { // we won't have time to entirely flush it before the socket is forced closed // by the shutdown process. try { - while (!queue.isEmpty()) { - Packet packet = queue.remove(); + while (!queue.isEmpty()) { + Packet packet = queue.remove(); writer.write(packet.toXML()); } writer.flush(); } catch (Exception e) { - e.printStackTrace(); + log.warning("Error flushing queue during shutdown, ignore and continue"); } // Delete the queue contents (hopefully nothing is left). diff --git a/source/org/jivesoftware/smack/ReconnectionManager.java b/source/org/jivesoftware/smack/ReconnectionManager.java index cc3e3af19..0f539b508 100644 --- a/source/org/jivesoftware/smack/ReconnectionManager.java +++ b/source/org/jivesoftware/smack/ReconnectionManager.java @@ -19,6 +19,7 @@ package org.jivesoftware.smack; import org.jivesoftware.smack.packet.StreamError; import java.util.Random; +import java.util.logging.Logger; /** * Handles the automatic reconnection process. Every time a connection is dropped without * the application explictly closing it, the manager automatically tries to reconnect to @@ -34,7 +35,8 @@ import java.util.Random; * @author Francisco Vives */ public class ReconnectionManager implements ConnectionListener { - + private static Logger log = Logger.getLogger(ReconnectionManager.class.getName()); + // Holds the connection to the server private Connection connection; private Thread reconnectionThread; @@ -132,8 +134,8 @@ public class ReconnectionManager implements ConnectionListener { ReconnectionManager.this .notifyAttemptToReconnectIn(remainingSeconds); } - catch (InterruptedException e1) { - e1.printStackTrace(); + catch (InterruptedException e1) { + log.warning("Sleeping thread interrupted"); // Notify the reconnection has failed ReconnectionManager.this.notifyReconnectionFailed(e1); } diff --git a/source/org/jivesoftware/smack/ServerTrustManager.java b/source/org/jivesoftware/smack/ServerTrustManager.java index 19faed90c..a9e45a308 100644 --- a/source/org/jivesoftware/smack/ServerTrustManager.java +++ b/source/org/jivesoftware/smack/ServerTrustManager.java @@ -29,6 +29,7 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.*; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -41,7 +42,8 @@ import java.util.regex.Pattern; * @author Gaston Dombiak */ class ServerTrustManager implements X509TrustManager { - + private static Logger log = Logger.getLogger(ServerTrustManager.class.getName()); + private static Pattern cnPattern = Pattern.compile("(?i)(cn=)([^,]*)"); private ConnectionConfiguration configuration; @@ -153,8 +155,7 @@ class ServerTrustManager implements X509TrustManager { trusted = trustStore.getCertificateAlias(x509Certificates[nSize - 1]) != null; if (!trusted && nSize == 1 && configuration.isSelfSignedCertificateEnabled()) { - System.out.println("Accepting self-signed certificate of remote server: " + - peerIdentities); + log.info("Accepting self-signed certificate of remote server: " + peerIdentities); trusted = true; } } @@ -268,7 +269,7 @@ class ServerTrustManager implements X509TrustManager { } } // Other types are not good for XMPP so ignore them - System.out.println("SubjectAltName of invalid type found: " + certificate); + log.info("SubjectAltName of invalid type found: " + certificate); }*/ } catch (CertificateParsingException e) { diff --git a/source/org/jivesoftware/smack/SmackConfiguration.java b/source/org/jivesoftware/smack/SmackConfiguration.java index 5395a1906..57ff2b76e 100644 --- a/source/org/jivesoftware/smack/SmackConfiguration.java +++ b/source/org/jivesoftware/smack/SmackConfiguration.java @@ -20,16 +20,18 @@ package org.jivesoftware.smack; +import java.io.IOException; import java.io.InputStream; -import java.net.URL; import java.util.ArrayList; import java.util.Collection; -import java.util.Enumeration; +import java.util.Collections; import java.util.List; -import java.util.Vector; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jivesoftware.smack.parsing.ExceptionThrowingCallback; import org.jivesoftware.smack.parsing.ParsingExceptionCallback; +import org.jivesoftware.smack.util.FileUtils; import org.xmlpull.mxp1.MXParser; import org.xmlpull.v1.XmlPullParser; @@ -49,16 +51,22 @@ import org.xmlpull.v1.XmlPullParser; * @author Gaston Dombiak */ public final class SmackConfiguration { - - private static final String SMACK_VERSION = "3.3.1"; - + private static final String SMACK_VERSION = "3.4.0"; + private static final String DEFAULT_CONFIG_FILE = "classpath:META-INF/smack-config.xml"; + + private static final Logger log = Logger.getLogger(SmackConfiguration.class.getName()); + + private static InputStream configFileStream; + private static int packetReplyTimeout = 5000; private static int keepAliveInterval = 30000; - private static Vector defaultMechs = new Vector(); + private static List defaultMechs = new ArrayList(); private static boolean localSocks5ProxyEnabled = true; private static int localSocks5ProxyPort = 7777; private static int packetCollectorSize = 5000; + + private static boolean initialized = false; /** * The default parsing exception callback is {@link ExceptionThrowingCallback} which will @@ -81,75 +89,39 @@ public final class SmackConfiguration { * 1) a set of classes will be loaded in order to execute their static init block * 2) retrieve and set the current Smack release */ - static { + + /** + * Sets the location of the config file on the classpath. Only required if changing from the default location of classpath:META-INF/smack-config.xml. + * + *

      + * This method must be called before accessing any other class in Smack. + * + * @param configFileUrl The location of the config file. + * @param loader The classloader to use if the URL has a protocol of classpath and the file is not located on the default classpath. + * This can be set to null to use defaults and is ignored for all other protocols. + * @throws IllegalArgumentException If the config URL is invalid in that it cannot open an {@link InputStream} + */ + public static void setConfigFileUrl(String configFileUrl, ClassLoader loader) { try { - // Get an array of class loaders to try loading the providers files from. - ClassLoader[] classLoaders = getClassLoaders(); - for (ClassLoader classLoader : classLoaders) { - Enumeration configEnum = classLoader.getResources("META-INF/smack-config.xml"); - while (configEnum.hasMoreElements()) { - URL url = configEnum.nextElement(); - InputStream systemStream = null; - try { - systemStream = url.openStream(); - XmlPullParser parser = new MXParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(systemStream, "UTF-8"); - int eventType = parser.getEventType(); - do { - if (eventType == XmlPullParser.START_TAG) { - if (parser.getName().equals("className")) { - // Attempt to load the class so that the class can get initialized - parseClassToLoad(parser); - } - else if (parser.getName().equals("packetReplyTimeout")) { - packetReplyTimeout = parseIntProperty(parser, packetReplyTimeout); - } - else if (parser.getName().equals("keepAliveInterval")) { - keepAliveInterval = parseIntProperty(parser, keepAliveInterval); - } - else if (parser.getName().equals("mechName")) { - defaultMechs.add(parser.nextText()); - } - else if (parser.getName().equals("localSocks5ProxyEnabled")) { - localSocks5ProxyEnabled = Boolean.parseBoolean(parser.nextText()); - } - else if (parser.getName().equals("localSocks5ProxyPort")) { - localSocks5ProxyPort = parseIntProperty(parser, localSocks5ProxyPort); - } - else if (parser.getName().equals("packetCollectorSize")) { - packetCollectorSize = parseIntProperty(parser, packetCollectorSize); - } - else if (parser.getName().equals("autoEnableEntityCaps")) { - autoEnableEntityCaps = Boolean.parseBoolean(parser.nextText()); - } - else if (parser.getName().equals("autoEnableEntityCaps")) { - autoEnableEntityCaps = Boolean.parseBoolean(parser.nextText()); - } - } - eventType = parser.next(); - } - while (eventType != XmlPullParser.END_DOCUMENT); - } - catch (Exception e) { - e.printStackTrace(); - } - finally { - try { - systemStream.close(); - } - catch (Exception e) { - // Ignore. - } - } - } - } - } + configFileStream = FileUtils.getStreamForUrl(configFileUrl, loader); + } catch (Exception e) { - e.printStackTrace(); - } + throw new IllegalArgumentException("Failed to create input stream from specified file URL ["+ configFileUrl + "]", e); + } + initialize(); } - + + /** + * Sets the {@link InputStream} representing the smack configuration file. This can be used to override the default with something that is not on the classpath. + *

      + * This method must be called before accessing any other class in Smack. + * @param configFile + */ + public static void setConfigFileStream(InputStream configFile) { + configFileStream = configFile; + initialize(); + } + /** * Returns the Smack version information, eg "1.3.0". * @@ -166,6 +138,8 @@ public final class SmackConfiguration { * @return the milliseconds to wait for a response from the server */ public static int getPacketReplyTimeout() { + initialize(); + // The timeout value must be greater than 0 otherwise we will answer the default value if (packetReplyTimeout <= 0) { packetReplyTimeout = 5000; @@ -180,6 +154,8 @@ public final class SmackConfiguration { * @param timeout the milliseconds to wait for a response from the server */ public static void setPacketReplyTimeout(int timeout) { + initialize(); + if (timeout <= 0) { throw new IllegalArgumentException(); } @@ -195,6 +171,7 @@ public final class SmackConfiguration { * no keep-alive should be sent. */ public static int getKeepAliveInterval() { + initialize(); return keepAliveInterval; } @@ -207,6 +184,7 @@ public final class SmackConfiguration { * or -1 if no keep-alive should be sent. */ public static void setKeepAliveInterval(int interval) { + initialize(); keepAliveInterval = interval; } @@ -217,6 +195,7 @@ public final class SmackConfiguration { * @return The number of packets to queue before deleting older packets. */ public static int getPacketCollectorSize() { + initialize(); return packetCollectorSize; } @@ -227,6 +206,7 @@ public final class SmackConfiguration { * @param The number of packets to queue before deleting older packets. */ public static void setPacketCollectorSize(int collectorSize) { + initialize(); packetCollectorSize = collectorSize; } @@ -236,6 +216,8 @@ public final class SmackConfiguration { * @param mech the SASL mechanism to be added */ public static void addSaslMech(String mech) { + initialize(); + if(! defaultMechs.contains(mech) ) { defaultMechs.add(mech); } @@ -247,6 +229,8 @@ public final class SmackConfiguration { * @param mechs the Collection of SASL mechanisms to be added */ public static void addSaslMechs(Collection mechs) { + initialize(); + for(String mech : mechs) { addSaslMech(mech); } @@ -258,9 +242,8 @@ public final class SmackConfiguration { * @param mech the SASL mechanism to be removed */ public static void removeSaslMech(String mech) { - if( defaultMechs.contains(mech) ) { - defaultMechs.remove(mech); - } + initialize(); + defaultMechs.remove(mech); } /** @@ -269,9 +252,8 @@ public final class SmackConfiguration { * @param mechs the Collection of SASL mechanisms to be removed */ public static void removeSaslMechs(Collection mechs) { - for(String mech : mechs) { - removeSaslMech(mech); - } + initialize(); + defaultMechs.removeAll(mechs); } /** @@ -282,7 +264,7 @@ public final class SmackConfiguration { * @return the list of SASL mechanisms to be used. */ public static List getSaslMechs() { - return defaultMechs; + return Collections.unmodifiableList(defaultMechs); } /** @@ -291,6 +273,7 @@ public final class SmackConfiguration { * @return if the local Socks5 proxy should be started */ public static boolean isLocalSocks5ProxyEnabled() { + initialize(); return localSocks5ProxyEnabled; } @@ -300,6 +283,7 @@ public final class SmackConfiguration { * @param localSocks5ProxyEnabled if the local Socks5 proxy should be started */ public static void setLocalSocks5ProxyEnabled(boolean localSocks5ProxyEnabled) { + initialize(); SmackConfiguration.localSocks5ProxyEnabled = localSocks5ProxyEnabled; } @@ -309,6 +293,7 @@ public final class SmackConfiguration { * @return the port of the local Socks5 proxy */ public static int getLocalSocks5ProxyPort() { + initialize(); return localSocks5ProxyPort; } @@ -319,26 +304,29 @@ public final class SmackConfiguration { * @param localSocks5ProxyPort the port of the local Socks5 proxy to set */ public static void setLocalSocks5ProxyPort(int localSocks5ProxyPort) { + initialize(); SmackConfiguration.localSocks5ProxyPort = localSocks5ProxyPort; } + /** + * Check if Entity Caps are enabled as default for every new connection + * @return + */ + public static boolean autoEnableEntityCaps() { + initialize(); + return autoEnableEntityCaps; + } + /** * Set if Entity Caps are enabled or disabled for every new connection * * @param true if Entity Caps should be auto enabled, false if not */ public static void setAutoEnableEntityCaps(boolean b) { + initialize(); autoEnableEntityCaps = b; } - /** - * Check if Entity Caps are enabled as default for every new connection - * @return - */ - public static boolean autoEnableEntityCaps() { - return autoEnableEntityCaps; - } - /** * Set the default parsing exception callback for all newly created connections * @@ -346,6 +334,7 @@ public final class SmackConfiguration { * @see ParsingExceptionCallback */ public static void setDefaultParsingExceptionCallback(ParsingExceptionCallback callback) { + initialize(); defaultCallback = callback; } @@ -356,6 +345,7 @@ public final class SmackConfiguration { * @see ParsingExceptionCallback */ public static ParsingExceptionCallback getDefaultParsingExceptionCallback() { + initialize(); return defaultCallback; } @@ -363,11 +353,15 @@ public final class SmackConfiguration { String className = parser.nextText(); // Attempt to load the class so that the class can get initialized try { - Class.forName(className); + Class initClass = Class.forName(className); + + if (SmackInitializer.class.isAssignableFrom(initClass)) { + SmackInitializer initializer = (SmackInitializer) initClass.newInstance(); + initializer.initialize(); + } } catch (ClassNotFoundException cnfe) { - System.err.println("Error! A startup class specified in smack-config.xml could " + - "not be loaded: " + className); + log.log(Level.WARNING, "A startup class [" + className + "] specified in smack-config.xml could not be loaded: "); } } @@ -378,27 +372,93 @@ public final class SmackConfiguration { return Integer.parseInt(parser.nextText()); } catch (NumberFormatException nfe) { - nfe.printStackTrace(); + log.log(Level.SEVERE, "Could not parse integer", nfe); return defaultValue; } } - /** - * Returns an array of class loaders to load resources from. - * - * @return an array of ClassLoader instances. + /* + * Order of precedence for config file is VM arg, setConfigXXX methods and embedded default file location. */ - private static ClassLoader[] getClassLoaders() { - ClassLoader[] classLoaders = new ClassLoader[2]; - classLoaders[0] = SmackConfiguration.class.getClassLoader(); - classLoaders[1] = Thread.currentThread().getContextClassLoader(); - // Clean up possible null values. Note that #getClassLoader may return a null value. - List loaders = new ArrayList(); - for (ClassLoader classLoader : classLoaders) { - if (classLoader != null) { - loaders.add(classLoader); + private static void initialize() { + if (initialized) { + return; + } + initialized = true; + + String configFileLocation = System.getProperty("smack.config.file"); + + if (configFileLocation != null) { + try { + configFileStream = FileUtils.getStreamForUrl(configFileLocation, null); + } + catch (Exception e) { + log.log(Level.SEVERE, "Error creating input stream for config file [" + configFileLocation + "] from VM argument", e); + } + } + + if (configFileStream == null) { + try { + configFileStream = FileUtils.getStreamForUrl(DEFAULT_CONFIG_FILE, null); + } + catch (Exception e) { + log.log(Level.INFO, "Could not create input stream for default config file [" + DEFAULT_CONFIG_FILE + "]", e); + } + } + + if (configFileStream != null) { + readFile(configFileStream); + } + else { + log.log(Level.INFO, "No configuration file found"); + } + } + + private static void readFile(InputStream cfgFileStream) { + XmlPullParser parser = new MXParser(); + try { + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + parser.setInput(cfgFileStream, "UTF-8"); + int eventType = parser.getEventType(); + do { + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("className")) { + // Attempt to load the class so that the class can get initialized + parseClassToLoad(parser); + } + else if (parser.getName().equals("packetReplyTimeout")) { + packetReplyTimeout = parseIntProperty(parser, packetReplyTimeout); + } + else if (parser.getName().equals("keepAliveInterval")) { + keepAliveInterval = parseIntProperty(parser, keepAliveInterval); + } + else if (parser.getName().equals("mechName")) { + defaultMechs.add(parser.nextText()); + } + else if (parser.getName().equals("localSocks5ProxyEnabled")) { + localSocks5ProxyEnabled = Boolean.parseBoolean(parser.nextText()); + } + else if (parser.getName().equals("localSocks5ProxyPort")) { + localSocks5ProxyPort = parseIntProperty(parser, localSocks5ProxyPort); + } + else if (parser.getName().equals("packetCollectorSize")) { + packetCollectorSize = parseIntProperty(parser, packetCollectorSize); + } + else if (parser.getName().equals("autoEnableEntityCaps")) { + autoEnableEntityCaps = Boolean.parseBoolean(parser.nextText()); + } + } + eventType = parser.next(); + } while (eventType != XmlPullParser.END_DOCUMENT); + } catch (Exception e) { + log.log(Level.SEVERE, "Error occurred while reading config file", e); + } + finally { + try { + cfgFileStream.close(); + } catch (IOException e) { + log.log(Level.INFO, "Error while closing config file input stream", e); } } - return loaders.toArray(new ClassLoader[loaders.size()]); } } diff --git a/source/org/jivesoftware/smack/SmackInitializer.java b/source/org/jivesoftware/smack/SmackInitializer.java new file mode 100644 index 000000000..d22aebc4b --- /dev/null +++ b/source/org/jivesoftware/smack/SmackInitializer.java @@ -0,0 +1,14 @@ +package org.jivesoftware.smack; + +/** + * Defines an initialization class that will be instantiated and invoked by the {@link SmackConfiguration} class during initialization. + * + *

      + * Any implementation of this class MUST have a default constructor. + * + * @author Robin Collier + * + */ +public interface SmackInitializer { + void initialize(); +} diff --git a/source/org/jivesoftware/smack/XMPPConnection.java b/source/org/jivesoftware/smack/XMPPConnection.java index f442e7386..13c16e1cd 100644 --- a/source/org/jivesoftware/smack/XMPPConnection.java +++ b/source/org/jivesoftware/smack/XMPPConnection.java @@ -788,7 +788,6 @@ public class XMPPConnection extends Connection { if(config.getCallbackHandler() == null) { ks = null; } else if (context == null) { - //System.out.println("Keystore type: "+configuration.getKeystoreType()); if(config.getKeystoreType().equals("NONE")) { ks = null; pcb = null; @@ -1043,10 +1042,13 @@ public class XMPPConnection extends Connection { */ synchronized void notifyConnectionError(Exception e) { // Listeners were already notified of the exception, return right here. - if (packetReader.done && packetWriter.done) return; + if ((packetReader == null || packetReader.done) && + (packetWriter == null || packetWriter.done)) return; - packetReader.done = true; - packetWriter.done = true; + if (packetReader != null) + packetReader.done = true; + if (packetWriter != null) + packetWriter.done = true; // Closes the connection temporary. A reconnection is possible shutdown(new Presence(Presence.Type.unavailable)); // Notify connection listeners of the error. diff --git a/source/org/jivesoftware/smack/packet/Message.java b/source/org/jivesoftware/smack/packet/Message.java index b2e25bf9c..a62b0e10a 100644 --- a/source/org/jivesoftware/smack/packet/Message.java +++ b/source/org/jivesoftware/smack/packet/Message.java @@ -80,7 +80,10 @@ public class Message extends Packet { */ public Message(String to, Type type) { setTo(to); - this.type = type; + + if (type != null) { + this.type = type; + } } /** diff --git a/source/org/jivesoftware/smack/packet/Packet.java b/source/org/jivesoftware/smack/packet/Packet.java index 041d8c892..aeae72fdf 100644 --- a/source/org/jivesoftware/smack/packet/Packet.java +++ b/source/org/jivesoftware/smack/packet/Packet.java @@ -27,6 +27,8 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Base class for XMPP packets. Every packet has a unique ID (which is automatically @@ -41,7 +43,8 @@ import java.util.concurrent.CopyOnWriteArrayList; * @author Matt Tucker */ public abstract class Packet { - + private static Logger log = Logger.getLogger(Packet.class.getName()); + protected static final String DEFAULT_LANGUAGE = java.util.Locale.getDefault().getLanguage().toLowerCase(); @@ -411,7 +414,7 @@ public abstract class Packet { buf.append(encodedVal).append(""); } catch (Exception e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error encoding java object", e); } finally { if (out != null) { @@ -452,6 +455,7 @@ public abstract class Packet { return DEFAULT_LANGUAGE; } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -472,6 +476,7 @@ public abstract class Packet { return !(xmlns != null ? !xmlns.equals(packet.xmlns) : packet.xmlns != null); } + @Override public int hashCode() { int result; result = (xmlns != null ? xmlns.hashCode() : 0); @@ -483,4 +488,9 @@ public abstract class Packet { result = 31 * result + (error != null ? error.hashCode() : 0); return result; } + + @Override + public String toString() { + return toXML(); + } } diff --git a/source/org/jivesoftware/smack/parsing/ExceptionLoggingCallback.java b/source/org/jivesoftware/smack/parsing/ExceptionLoggingCallback.java index 771913ebf..b9073c306 100644 --- a/source/org/jivesoftware/smack/parsing/ExceptionLoggingCallback.java +++ b/source/org/jivesoftware/smack/parsing/ExceptionLoggingCallback.java @@ -20,18 +20,21 @@ package org.jivesoftware.smack.parsing; +import java.util.logging.Level; +import java.util.logging.Logger; + /** - * Simple parsing exception callback that only logs the encountered parsing exception to stderr. + * Simple parsing exception callback that only logs the encountered parsing exception to java util logging. * * @author Florian Schmaus * */ public class ExceptionLoggingCallback extends ParsingExceptionCallback { - + private static Logger log = Logger.getLogger(ExceptionLoggingCallback.class.getName()); + @Override public void handleUnparsablePacket(UnparsablePacket unparsed) throws Exception { - System.err.print("Smack message parsing exception: " + unparsed.getParsingException().getMessage()); - unparsed.getParsingException().printStackTrace(); - System.err.println("Unparsed content: " + unparsed.getContent()); + log.log(Level.SEVERE, "Smack message parsing exception: ", unparsed.getParsingException()); + log.severe("Unparsed content: " + unparsed.getContent()); } } diff --git a/source/org/jivesoftware/smack/provider/AbstractProviderInfo.java b/source/org/jivesoftware/smack/provider/AbstractProviderInfo.java new file mode 100644 index 000000000..487f29463 --- /dev/null +++ b/source/org/jivesoftware/smack/provider/AbstractProviderInfo.java @@ -0,0 +1,26 @@ +package org.jivesoftware.smack.provider; + + +abstract class AbstractProviderInfo { + private String element; + private String ns; + private Object provider; + + AbstractProviderInfo(String elementName, String namespace, Object iqOrExtProvider) { + element = elementName; + ns = namespace; + provider = iqOrExtProvider; + } + + public String getElementName() { + return element; + } + + public String getNamespace() { + return ns; + } + + Object getProvider() { + return provider; + } +} diff --git a/source/org/jivesoftware/smack/provider/CoreInitializer.java b/source/org/jivesoftware/smack/provider/CoreInitializer.java new file mode 100644 index 000000000..b39aa0f82 --- /dev/null +++ b/source/org/jivesoftware/smack/provider/CoreInitializer.java @@ -0,0 +1,15 @@ +package org.jivesoftware.smack.provider; + +import org.jivesoftware.smack.SmackInitializer; + +/** + * Loads the default provider file for the Smack core on initialization. + * + * @author Robin Collier + * + */ +public class CoreInitializer extends UrlProviderFileInitializer implements SmackInitializer { + protected String getFilePath() { + return "classpath:META-INF/core.providers"; + } +} diff --git a/source/org/jivesoftware/smack/provider/ExtensionProviderInfo.java b/source/org/jivesoftware/smack/provider/ExtensionProviderInfo.java new file mode 100644 index 000000000..4d6333cd9 --- /dev/null +++ b/source/org/jivesoftware/smack/provider/ExtensionProviderInfo.java @@ -0,0 +1,33 @@ +package org.jivesoftware.smack.provider; + +/** + * Defines the information required to register a packet extension Provider with the {@link ProviderManager} when using the + * {@link ProviderLoader}. + * + * @author Robin Collier + * + */ +public final class ExtensionProviderInfo extends AbstractProviderInfo { + + /** + * Defines an extension provider which implements the PacketExtensionProvider interface. + * + * @param elementName Element that provider parses. + * @param namespace Namespace that provider parses. + * @param extProvider The provider implementation. + */ + public ExtensionProviderInfo(String elementName, String namespace, PacketExtensionProvider extProvider) { + super(elementName, namespace, extProvider); + } + + /** + * Defines an extension provider which is adheres to the JavaBean spec for parsing the extension. + * + * @param elementName Element that provider parses. + * @param namespace Namespace that provider parses. + * @param beanClass The provider bean class. + */ + public ExtensionProviderInfo(String elementName, String namespace, Class beanClass) { + super(elementName, namespace, beanClass); + } +} diff --git a/source/org/jivesoftware/smack/provider/IQProviderInfo.java b/source/org/jivesoftware/smack/provider/IQProviderInfo.java new file mode 100644 index 000000000..c707e61d3 --- /dev/null +++ b/source/org/jivesoftware/smack/provider/IQProviderInfo.java @@ -0,0 +1,35 @@ +package org.jivesoftware.smack.provider; + +import org.jivesoftware.smack.packet.IQ; + +/** + * Defines the information required to register an IQ Provider with the {@link ProviderManager} when using the + * {@link ProviderLoader}. + * + * @author Robin Collier + * + */ +public final class IQProviderInfo extends AbstractProviderInfo { + + /** + * Defines an IQ provider which implements the IQProvider interface. + * + * @param elementName Element that provider parses. + * @param namespace Namespace that provider parses. + * @param iqProvider The provider implementation. + */ + public IQProviderInfo(String elementName, String namespace, IQProvider iqProvider) { + super(elementName, namespace, iqProvider); + } + + /** + * Defines an IQ class which can be used as a provider via introspection. + * + * @param elementName Element that provider parses. + * @param namespace Namespace that provider parses. + * @param iqProviderClass The IQ class being parsed. + */ + public IQProviderInfo(String elementName, String namespace, Class iqProviderClass) { + super(elementName, namespace, iqProviderClass); + } +} diff --git a/source/org/jivesoftware/smack/provider/ProviderFileLoader.java b/source/org/jivesoftware/smack/provider/ProviderFileLoader.java new file mode 100644 index 000000000..57c9916fb --- /dev/null +++ b/source/org/jivesoftware/smack/provider/ProviderFileLoader.java @@ -0,0 +1,146 @@ +package org.jivesoftware.smack.provider; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.PacketExtension; +import org.xmlpull.mxp1.MXParser; +import org.xmlpull.v1.XmlPullParser; + +/** + * Loads the {@link IQProvider} and {@link PacketExtensionProvider} information from a standard provider file in preparation + * for loading into the {@link ProviderManager}. + * + * @author Robin Collier + * + */ +public class ProviderFileLoader implements ProviderLoader { + private final static Logger log = Logger.getLogger(ProviderFileLoader.class.getName()); + + private Collection iqProviders; + private Collection extProviders; + private InputStream providerStream; + + public ProviderFileLoader(InputStream providerFileInputStream) { + setInputStream(providerFileInputStream); + } + + public ProviderFileLoader() { + } + + @Override + public Collection getIQProviderInfo() { + initialize(); + return iqProviders; + } + + @Override + public Collection getExtensionProviderInfo() { + initialize(); + return extProviders; + } + + @SuppressWarnings("unchecked") + private synchronized void initialize() { + // Check to see if already initialized + if (iqProviders != null) { + return; + } + + if (providerStream == null) { + throw new IllegalArgumentException("No input stream set for loader"); + } + iqProviders = new ArrayList(); + extProviders = new ArrayList(); + + // Load processing providers. + try { + XmlPullParser parser = new MXParser(); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + parser.setInput(providerStream, "UTF-8"); + int eventType = parser.getEventType(); + do { + if (eventType == XmlPullParser.START_TAG) { + String typeName = parser.getName(); + + try { + if (!"smackProviders".equals(typeName)) { + parser.next(); + parser.next(); + String elementName = parser.nextText(); + parser.next(); + parser.next(); + String namespace = parser.nextText(); + parser.next(); + parser.next(); + String className = parser.nextText(); + + try { + // Attempt to load the provider class and then create + // a new instance if it's an IQProvider. Otherwise, if it's + // an IQ class, add the class object itself, then we'll use + // reflection later to create instances of the class. + if ("iqProvider".equals(typeName)) { + // Add the provider to the map. + Class provider = Class.forName(className); + + if (IQProvider.class.isAssignableFrom(provider)) { + iqProviders.add(new IQProviderInfo(elementName, namespace, (IQProvider) provider.newInstance())); + } + else if (IQ.class.isAssignableFrom(provider)) { + iqProviders.add(new IQProviderInfo(elementName, namespace, (Class)provider)); + } + } + else { + // Attempt to load the provider class and then create + // a new instance if it's an ExtensionProvider. Otherwise, if it's + // a PacketExtension, add the class object itself and + // then we'll use reflection later to create instances + // of the class. + Class provider = Class.forName(className); + if (PacketExtensionProvider.class.isAssignableFrom(provider)) { + extProviders.add(new ExtensionProviderInfo(elementName, namespace, (PacketExtensionProvider) provider.newInstance())); + } + else if (PacketExtension.class.isAssignableFrom(provider)) { + extProviders.add(new ExtensionProviderInfo(elementName, namespace, provider)); + } + } + } + catch (ClassNotFoundException cnfe) { + log.log(Level.SEVERE, "Could not find provider class", cnfe); + } + } + } + catch (IllegalArgumentException illExc) { + log.log(Level.SEVERE, "Invalid provider type found [" + typeName + "] when expecting iqProvider or extensionProvider", illExc); + } + } + eventType = parser.next(); + } + while (eventType != XmlPullParser.END_DOCUMENT); + } + catch (Exception e){ + log.log(Level.SEVERE, "Unknown error occurred while parsing provider file", e); + } + finally { + try { + providerStream.close(); + } + catch (Exception e) { + // Ignore. + } + } + } + + public void setInputStream(InputStream providerFileInput) { + if (providerFileInput == null) { + throw new IllegalArgumentException("InputStream cannot be null"); + } + providerStream = providerFileInput; + initialize(); + } +} diff --git a/source/org/jivesoftware/smack/provider/ProviderLoader.java b/source/org/jivesoftware/smack/provider/ProviderLoader.java new file mode 100644 index 000000000..fd813b74b --- /dev/null +++ b/source/org/jivesoftware/smack/provider/ProviderLoader.java @@ -0,0 +1,23 @@ +package org.jivesoftware.smack.provider; + +import java.util.Collection; + +/** + * Used to load providers into the {@link ProviderManager}. + * + * @author Robin Collier + */ +public interface ProviderLoader { + + /** + * Provides the IQ provider info for the creation of IQ providers to be added to the ProviderManager. + * @return The IQ provider info to load. + */ + Collection getIQProviderInfo(); + + /** + * Provides the extension providers for the creation of extension providers to be added to the ProviderManager. + * @return The extension provider info to load. + */ + Collection getExtensionProviderInfo(); +} diff --git a/source/org/jivesoftware/smack/provider/ProviderManager.java b/source/org/jivesoftware/smack/provider/ProviderManager.java index fda6b1b81..fb1ba19b6 100644 --- a/source/org/jivesoftware/smack/provider/ProviderManager.java +++ b/source/org/jivesoftware/smack/provider/ProviderManager.java @@ -20,16 +20,13 @@ package org.jivesoftware.smack.provider; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.PacketExtension; -import org.xmlpull.mxp1.MXParser; -import org.xmlpull.v1.XmlPullParser; - -import java.io.InputStream; -import java.net.URL; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.jivesoftware.smack.packet.IQ; + /** * Manages providers for parsing custom XML sub-documents of XMPP packets. Two types of * providers exist:

        @@ -102,20 +99,14 @@ import java.util.concurrent.ConcurrentHashMap; * can either implement the PacketExtensionProvider interface or be a standard Java Bean. In * the former case, each extension provider is responsible for parsing the raw XML stream to * contruct an object. In the latter case, bean introspection is used to try to automatically - * set the properties of the class using the values in the packet extension sub-element. When an + * set the properties of th class using the values in the packet extension sub-element. When an * extension provider is not registered for an element name and namespace combination, Smack will * store all top-level elements of the sub-packet in DefaultPacketExtension object and then * attach it to the packet.

        * - * It is possible to provide a custom provider manager instead of the default implementation - * provided by Smack. If you want to provide your own provider manager then you need to do it - * before creating any {@link org.jivesoftware.smack.Connection} by sending the static - * {@link #setInstance(ProviderManager)} message. Trying to change the provider manager after - * an Connection was created will result in an {@link IllegalStateException} error. - * * @author Matt Tucker */ -public class ProviderManager { +public final class ProviderManager { private static ProviderManager instance; @@ -123,9 +114,7 @@ public class ProviderManager { private Map iqProviders = new ConcurrentHashMap(); /** - * Returns the only ProviderManager valid instance. Use {@link #setInstance(ProviderManager)} - * to configure your own provider manager. If non was provided then an instance of this - * class will be used. + * Returns the ProviderManager instance. * * @return the only ProviderManager valid instance. */ @@ -136,130 +125,28 @@ public class ProviderManager { return instance; } - /** - * Sets the only ProviderManager valid instance to be used by all Connections. If you - * want to provide your own provider manager then you need to do it before creating - * any Connection. Otherwise an IllegalStateException will be thrown. - * - * @param providerManager the only ProviderManager valid instance to be used. - * @throws IllegalStateException if a provider manager was already configued. - */ - public static synchronized void setInstance(ProviderManager providerManager) { - if (instance != null) { - throw new IllegalStateException("ProviderManager singleton already set"); - } - instance = providerManager; + private ProviderManager() { + super(); } - protected void initialize() { - // Load IQ processing providers. - try { - // Get an array of class loaders to try loading the providers files from. - ClassLoader[] classLoaders = getClassLoaders(); - for (ClassLoader classLoader : classLoaders) { - Enumeration providerEnum = classLoader.getResources( - "META-INF/smack.providers"); - while (providerEnum.hasMoreElements()) { - URL url = providerEnum.nextElement(); - InputStream providerStream = null; - try { - providerStream = url.openStream(); - XmlPullParser parser = new MXParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(providerStream, "UTF-8"); - int eventType = parser.getEventType(); - do { - if (eventType == XmlPullParser.START_TAG) { - if (parser.getName().equals("iqProvider")) { - parser.next(); - parser.next(); - String elementName = parser.nextText(); - parser.next(); - parser.next(); - String namespace = parser.nextText(); - parser.next(); - parser.next(); - String className = parser.nextText(); - // Only add the provider for the namespace if one isn't - // already registered. - String key = getProviderKey(elementName, namespace); - if (!iqProviders.containsKey(key)) { - // Attempt to load the provider class and then create - // a new instance if it's an IQProvider. Otherwise, if it's - // an IQ class, add the class object itself, then we'll use - // reflection later to create instances of the class. - try { - // Add the provider to the map. - Class provider = Class.forName(className); - if (IQProvider.class.isAssignableFrom(provider)) { - iqProviders.put(key, provider.newInstance()); - } - else if (IQ.class.isAssignableFrom(provider)) { - iqProviders.put(key, provider); - } - } - catch (ClassNotFoundException cnfe) { - cnfe.printStackTrace(); - } - } - } - else if (parser.getName().equals("extensionProvider")) { - parser.next(); - parser.next(); - String elementName = parser.nextText(); - parser.next(); - parser.next(); - String namespace = parser.nextText(); - parser.next(); - parser.next(); - String className = parser.nextText(); - // Only add the provider for the namespace if one isn't - // already registered. - String key = getProviderKey(elementName, namespace); - if (!extensionProviders.containsKey(key)) { - // Attempt to load the provider class and then create - // a new instance if it's a Provider. Otherwise, if it's - // a PacketExtension, add the class object itself and - // then we'll use reflection later to create instances - // of the class. - try { - // Add the provider to the map. - Class provider = Class.forName(className); - if (PacketExtensionProvider.class.isAssignableFrom( - provider)) { - extensionProviders.put(key, provider.newInstance()); - } - else if (PacketExtension.class.isAssignableFrom( - provider)) { - extensionProviders.put(key, provider); - } - } - catch (ClassNotFoundException cnfe) { - cnfe.printStackTrace(); - } - } - } - } - eventType = parser.next(); - } - while (eventType != XmlPullParser.END_DOCUMENT); - } - finally { - try { - providerStream.close(); - } - catch (Exception e) { - // Ignore. - } - } - } + public void addLoader(ProviderLoader loader) { + if (loader == null) { + throw new IllegalArgumentException("loader cannot be null"); + } + + if (loader.getIQProviderInfo() != null) { + for (IQProviderInfo info : loader.getIQProviderInfo()) { + iqProviders.put(getProviderKey(info.getElementName(), info.getNamespace()), info.getProvider()); } } - catch (Exception e) { - e.printStackTrace(); + + if (loader.getExtensionProviderInfo() != null) { + for (ExtensionProviderInfo info : loader.getExtensionProviderInfo()) { + extensionProviders.put(getProviderKey(info.getElementName(), info.getNamespace()), info.getProvider()); + } } } - + /** * Returns the IQ provider registered to the specified XML element name and namespace. * For example, if a provider was registered to the element name "query" and the @@ -411,28 +298,4 @@ public class ProviderManager { buf.append("<").append(elementName).append("/><").append(namespace).append("/>"); return buf.toString(); } - - /** - * Returns an array of class loaders to load resources from. - * - * @return an array of ClassLoader instances. - */ - private ClassLoader[] getClassLoaders() { - ClassLoader[] classLoaders = new ClassLoader[2]; - classLoaders[0] = ProviderManager.class.getClassLoader(); - classLoaders[1] = Thread.currentThread().getContextClassLoader(); - // Clean up possible null values. Note that #getClassLoader may return a null value. - List loaders = new ArrayList(); - for (ClassLoader classLoader : classLoaders) { - if (classLoader != null) { - loaders.add(classLoader); - } - } - return loaders.toArray(new ClassLoader[loaders.size()]); - } - - private ProviderManager() { - super(); - initialize(); - } } \ No newline at end of file diff --git a/source/org/jivesoftware/smack/provider/UrlProviderFileInitializer.java b/source/org/jivesoftware/smack/provider/UrlProviderFileInitializer.java new file mode 100644 index 000000000..68cbfe5c6 --- /dev/null +++ b/source/org/jivesoftware/smack/provider/UrlProviderFileInitializer.java @@ -0,0 +1,54 @@ +package org.jivesoftware.smack.provider; + +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.Level; +import java.util.logging.Logger; + +import org.jivesoftware.smack.SmackInitializer; +import org.jivesoftware.smack.util.FileUtils; + +/** + * Loads the provider file defined by the URL returned by {@link #getFilePath()}. This file will be loaded on Smack initialization. + * + * @author Robin Collier + * + */ +public abstract class UrlProviderFileInitializer implements SmackInitializer { + private static final Logger log = Logger.getLogger(UrlProviderFileInitializer.class.getName()); + + @Override + public void initialize() { + String filePath = getFilePath(); + + try { + InputStream is = FileUtils.getStreamForUrl(filePath, getClassLoader()); + + if (is != null) { + log.log(Level.INFO, "Loading providers for file [" + filePath + "]"); + ProviderManager.getInstance().addLoader(new ProviderFileLoader(is)); + } + else { + log.log(Level.WARNING, "No input stream created for " + filePath); + } + } + catch (Exception e) { + log.log(Level.SEVERE, "Error trying to load provider file " + filePath, e); + } + } + + protected abstract String getFilePath(); + + /** + * Returns an array of class loaders to load resources from. + * + * @return an array of ClassLoader instances. + */ + protected ClassLoader getClassLoader() { + return null; + } +} diff --git a/source/org/jivesoftware/smack/provider/VmArgInitializer.java b/source/org/jivesoftware/smack/provider/VmArgInitializer.java new file mode 100644 index 000000000..54e1be9cf --- /dev/null +++ b/source/org/jivesoftware/smack/provider/VmArgInitializer.java @@ -0,0 +1,23 @@ +package org.jivesoftware.smack.provider; + + +/** + * Looks for a provider file location based on the VM argument smack.provider.file. If it is supplied, its value will + * be used as a file location for a providers file and loaded into the {@link ProviderManager} on Smack initialization. + * + * @author Robin Collier + * + */ +public class VmArgInitializer extends UrlProviderFileInitializer { + + protected String getFilePath() { + return System.getProperty("smack.provider.file"); + } + + @Override + public void initialize() { + if (getFilePath() != null) { + super.initialize(); + } + } +} diff --git a/source/org/jivesoftware/smack/util/Base64.java b/source/org/jivesoftware/smack/util/Base64.java index ba6eb371f..2ddd0138f 100644 --- a/source/org/jivesoftware/smack/util/Base64.java +++ b/source/org/jivesoftware/smack/util/Base64.java @@ -5,6 +5,9 @@ * */ package org.jivesoftware.smack.util; + +import java.util.logging.Level; +import java.util.logging.Logger; /** *

        Encodes and decodes to and from Base64 notation.

        @@ -17,9 +20,9 @@ package org.jivesoftware.smack.util; */ public class Base64 { - -/* ******** P U B L I C F I E L D S ******** */ - + private static Logger log = Logger.getLogger(Base64.class.getName()); + + /* ******** P U B L I C F I E L D S ******** */ /** No options specified. Value is zero. */ public final static int NO_OPTIONS = 0; @@ -311,18 +314,6 @@ public class Base64 /** Defeats instantiation. */ private Base64(){} - /** - * Prints command line usage. - * - * @param msg A message to include with usage info. - */ - private final static void usage( String msg ) - { - System.err.println( msg ); - System.err.println( "Usage: java Base64 -e|-d inputfile outputfile" ); - } // end usage - - /* ******** E N C O D I N G M E T H O D S ******** */ @@ -494,7 +485,7 @@ public class Base64 } // end try catch( java.io.IOException e ) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error encoding object", e); return null; } // end catch finally @@ -623,7 +614,7 @@ public class Base64 } // end try catch( java.io.IOException e ) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error encoding bytes", e); return null; } // end catch finally @@ -777,11 +768,12 @@ public class Base64 destination[ destOffset + 2 ] = (byte)( outBuff ); return 3; - }catch( Exception e){ - System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) ); - System.out.println(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) ); - System.out.println(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) ); - System.out.println(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) ); + }catch( Exception e){ + log.log(Level.SEVERE, e.getMessage(), e); + log.severe(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) ); + log.severe(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) ); + log.severe(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) ); + log.severe(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) ); return -1; } // end catch } @@ -839,7 +831,7 @@ public class Base64 } // end if: white space, equals sign or better else { - System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" ); + log.warning("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)"); return null; } // end else: } // each input character @@ -967,12 +959,12 @@ public class Base64 } // end try catch( java.io.IOException e ) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error reading object", e); obj = null; } // end catch catch( java.lang.ClassNotFoundException e ) { - e.printStackTrace(); + log.log(Level.SEVERE, "Class not found for encoded object", e); obj = null; } // end catch finally @@ -1079,7 +1071,7 @@ public class Base64 // Check for size of file if( file.length() > Integer.MAX_VALUE ) { - System.err.println( "File is too big for this convenience method (" + file.length() + " bytes)." ); + log.warning("File is too big for this convenience method (" + file.length() + " bytes)."); return null; } // end if: file too big for int index buffer = new byte[ (int)file.length() ]; @@ -1100,7 +1092,7 @@ public class Base64 } // end try catch( java.io.IOException e ) { - System.err.println( "Error decoding from file " + filename ); + log.log(Level.SEVERE, "Error decoding from file " + filename, e); } // end catch: IOException finally { @@ -1148,7 +1140,7 @@ public class Base64 } // end try catch( java.io.IOException e ) { - System.err.println( "Error encoding from file " + filename ); + log.log(Level.SEVERE, "Error encoding from file " + filename, e); } // end catch: IOException finally { @@ -1175,7 +1167,7 @@ public class Base64 out.write( encoded.getBytes("US-ASCII") ); // Strict, 7-bit output. } // end try catch( java.io.IOException ex ) { - ex.printStackTrace(); + log.log(Level.SEVERE, "Error encoding file " + infile, ex); } // end catch finally { try { out.close(); } @@ -1201,7 +1193,7 @@ public class Base64 out.write( decoded ); } // end try catch( java.io.IOException ex ) { - ex.printStackTrace(); + log.log(Level.SEVERE, "Error decoding file " + infile, ex); } // end catch finally { try { out.close(); } diff --git a/source/org/jivesoftware/smack/util/Cache.java b/source/org/jivesoftware/smack/util/Cache.java index 964ac2382..5426a4ad8 100644 --- a/source/org/jivesoftware/smack/util/Cache.java +++ b/source/org/jivesoftware/smack/util/Cache.java @@ -22,6 +22,7 @@ package org.jivesoftware.smack.util; import org.jivesoftware.smack.util.collections.AbstractMapEntry; import java.util.*; +import java.util.logging.Logger; /** * A specialized Map that is size-limited (using an LRU algorithm) and @@ -49,7 +50,7 @@ import java.util.*; * @author Matt Tucker */ public class Cache implements Map { - + private static Logger log = Logger.getLogger(Cache.class.getName()); /** * The map the keys and values are stored in. */ @@ -382,8 +383,7 @@ public class Cache implements Map { while (expireTime > node.timestamp) { if (remove(node.object, true) == null) { - System.err.println("Error attempting to remove(" + node.object.toString() + - ") - cacheObject not found in cache!"); + log.warning("Error attempting to remove(" + node.object.toString() + ") - cacheObject not found in cache!"); // remove from the ageList node.remove(); } @@ -417,9 +417,7 @@ public class Cache implements Map { for (int i=map.size(); i>desiredSize; i--) { // Get the key and invoke the remove method on it. if (remove(lastAccessedList.getLast().object, true) == null) { - System.err.println("Error attempting to cullCache with remove(" + - lastAccessedList.getLast().object.toString() + ") - " + - "cacheObject not found in cache!"); + log.warning("Error attempting to cullCache with remove(" + lastAccessedList.getLast().object.toString() + ") - cacheObject not found in cache!"); lastAccessedList.getLast().remove(); } } diff --git a/source/org/jivesoftware/smack/util/FileUtils.java b/source/org/jivesoftware/smack/util/FileUtils.java new file mode 100644 index 000000000..e400230e3 --- /dev/null +++ b/source/org/jivesoftware/smack/util/FileUtils.java @@ -0,0 +1,59 @@ +package org.jivesoftware.smack.util; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +public final class FileUtils { + + private FileUtils() { + } + + public static InputStream getStreamForUrl(String url, ClassLoader loader) throws MalformedURLException, IOException { + URI fileUri = URI.create(url); + + if (fileUri.getScheme() == null) { + throw new MalformedURLException("No protocol found in file URL: " + url); + } + + if (fileUri.getScheme().equals("classpath")) { + // Get an array of class loaders to try loading the providers files from. + ClassLoader[] classLoaders = getClassLoaders(); + for (ClassLoader classLoader : classLoaders) { + InputStream is = classLoader.getResourceAsStream(fileUri.getSchemeSpecificPart()); + + if (is != null) { + return is; + } + } + } + else { + return fileUri.toURL().openStream(); + } + return null; + } + + /** + * Returns default classloaders. + * + * @return an array of ClassLoader instances. + */ + public static ClassLoader[] getClassLoaders() { + ClassLoader[] classLoaders = new ClassLoader[2]; + classLoaders[0] = FileUtils.class.getClassLoader(); + classLoaders[1] = Thread.currentThread().getContextClassLoader(); + // Clean up possible null values. Note that #getClassLoader may return a null value. + List loaders = new ArrayList(); + + for (ClassLoader classLoader : classLoaders) { + if (classLoader != null) { + loaders.add(classLoader); + } + } + return loaders.toArray(new ClassLoader[loaders.size()]); + } + +} diff --git a/source/org/jivesoftware/smack/util/PacketParserUtils.java b/source/org/jivesoftware/smack/util/PacketParserUtils.java index 7fba71f90..a8d6b9e36 100644 --- a/source/org/jivesoftware/smack/util/PacketParserUtils.java +++ b/source/org/jivesoftware/smack/util/PacketParserUtils.java @@ -29,6 +29,8 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jivesoftware.smack.Connection; import org.jivesoftware.smack.packet.Authentication; @@ -57,7 +59,8 @@ import org.xmlpull.v1.XmlPullParserException; * @author Gaston Dombiak */ public class PacketParserUtils { - + private static Logger logger = Logger.getLogger(PacketParserUtils.class.getName()); + /** * Namespace used to store packet properties. */ @@ -198,7 +201,7 @@ public class PacketParserUtils { type = Presence.Type.valueOf(typeString); } catch (IllegalArgumentException iae) { - System.err.println("Found invalid presence type " + typeString); + logger.warning("Found invalid presence type " + typeString); } } Presence presence = new Presence(type); @@ -242,7 +245,7 @@ public class PacketParserUtils { presence.setMode(Presence.Mode.valueOf(modeText)); } catch (IllegalArgumentException iae) { - System.err.println("Found invalid presence mode " + modeText); + logger.warning("Found invalid presence mode " + modeText); } } else if (elementName.equals("error")) { @@ -263,7 +266,7 @@ public class PacketParserUtils { presence.addExtension(PacketParserUtils.parsePacketExtension(elementName, namespace, parser)); } catch (Exception e) { - System.err.println("Failed to parse extension packet in Presence packet."); + logger.warning("Failed to parse extension packet in Presence packet."); } } } @@ -639,7 +642,7 @@ public class PacketParserUtils { value = in.readObject(); } catch (Exception e) { - e.printStackTrace(); + logger.log(Level.SEVERE, "Error parsing java object", e); } } if (name != null && value != null) { @@ -782,8 +785,7 @@ public class PacketParserUtils { } } catch (IllegalArgumentException iae) { - // Print stack trace. We shouldn't be getting an illegal error type. - iae.printStackTrace(); + logger.log(Level.SEVERE, "Could not find error type for " + type.toUpperCase(), iae); } return new XMPPError(Integer.parseInt(errorCode), errorType, condition, message, extensions); } diff --git a/source/org/jivesoftware/smack/util/StringUtils.java b/source/org/jivesoftware/smack/util/StringUtils.java index 7e3cfdc73..eecd84dda 100644 --- a/source/org/jivesoftware/smack/util/StringUtils.java +++ b/source/org/jivesoftware/smack/util/StringUtils.java @@ -34,6 +34,8 @@ import java.util.Date; import java.util.List; import java.util.Random; import java.util.TimeZone; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -41,7 +43,8 @@ import java.util.regex.Pattern; * A collection of utility methods for String objects. */ public class StringUtils { - + private static Logger log = Logger.getLogger(StringUtils.class.getName()); + /** * Date format as defined in XEP-0082 - XMPP Date and Time Profiles. The time zone is set to * UTC. @@ -619,8 +622,7 @@ public class StringUtils { digest = MessageDigest.getInstance("SHA-1"); } catch (NoSuchAlgorithmException nsae) { - System.err.println("Failed to load the SHA-1 MessageDigest. " + - "Jive will be unable to function normally."); + log.log(Level.SEVERE, "Failed to load the SHA-1 MessageDigest. Smack will be unable to function normally.", nsae); } } // Now, compute hash. @@ -628,7 +630,7 @@ public class StringUtils { digest.update(data.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { - System.err.println(e); + log.log(Level.SEVERE, "Error computing hash", e); } return encodeHex(digest.digest()); } @@ -664,7 +666,7 @@ public class StringUtils { bytes = data.getBytes("ISO-8859-1"); } catch (UnsupportedEncodingException uee) { - uee.printStackTrace(); + throw new IllegalStateException(uee); } return encodeBase64(bytes); } diff --git a/source/org/jivesoftware/smackx/MessageEventManager.java b/source/org/jivesoftware/smackx/MessageEventManager.java index 3502509d4..900914b3d 100644 --- a/source/org/jivesoftware/smackx/MessageEventManager.java +++ b/source/org/jivesoftware/smackx/MessageEventManager.java @@ -25,6 +25,8 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.Connection; @@ -42,7 +44,8 @@ import org.jivesoftware.smackx.packet.MessageEvent; * @author Gaston Dombiak */ public class MessageEventManager { - + private static Logger log = Logger.getLogger(MessageEventManager.class.getName()); + private List messageEventNotificationListeners = new ArrayList(); private List messageEventRequestListeners = new ArrayList(); @@ -157,12 +160,8 @@ public class MessageEventManager { for (int i = 0; i < listeners.length; i++) { method.invoke(listeners[i], new Object[] { from, packetID, this }); } - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); + } catch (Exception e) { + log.log(Level.SEVERE, "Error while invoking MessageEventRequestListener", e); } } @@ -188,12 +187,8 @@ public class MessageEventManager { for (int i = 0; i < listeners.length; i++) { method.invoke(listeners[i], new Object[] { from, packetID }); } - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); + } catch (Exception e) { + log.log(Level.SEVERE, "Error while invoking MessageEventNotificationListener", e); } } diff --git a/source/org/jivesoftware/smackx/MultipleRecipientManager.java b/source/org/jivesoftware/smackx/MultipleRecipientManager.java index 83afaceb8..2fb525aea 100644 --- a/source/org/jivesoftware/smackx/MultipleRecipientManager.java +++ b/source/org/jivesoftware/smackx/MultipleRecipientManager.java @@ -33,6 +33,8 @@ import org.jivesoftware.smackx.packet.MultipleAddresses; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * A MultipleRecipientManager allows to send packets to multiple recipients by making use of @@ -42,7 +44,8 @@ import java.util.List; * @author Gaston Dombiak */ public class MultipleRecipientManager { - + private static Logger log = Logger.getLogger(MultipleRecipientManager.class.getName()); + /** * Create a cache to hold the 100 most recently accessed elements for a period of * 24 hours. @@ -309,13 +312,12 @@ public class MultipleRecipientManager { break; } } - } // Cache the discovered information services.put(serviceName, serviceAddress == null ? "" : serviceAddress); } catch (XMPPException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error occurred retrieving multiple recipients service", e); } } } diff --git a/source/org/jivesoftware/smackx/PEPListener.java b/source/org/jivesoftware/smackx/PEPListener.java index 1d3948438..bfe81cedb 100644 --- a/source/org/jivesoftware/smackx/PEPListener.java +++ b/source/org/jivesoftware/smackx/PEPListener.java @@ -29,6 +29,7 @@ import org.jivesoftware.smackx.packet.PEPEvent; * * @author Jeff Williams */ +@Deprecated public interface PEPListener { /** diff --git a/source/org/jivesoftware/smackx/PEPManager.java b/source/org/jivesoftware/smackx/PEPManager.java index 159b1d378..c30ee88a5 100644 --- a/source/org/jivesoftware/smackx/PEPManager.java +++ b/source/org/jivesoftware/smackx/PEPManager.java @@ -60,6 +60,7 @@ import org.jivesoftware.smackx.packet.PEPPubSub; * * @author Jeff Williams */ +@Deprecated public class PEPManager { private List pepListeners = new ArrayList(); diff --git a/source/org/jivesoftware/smackx/XHTMLManager.java b/source/org/jivesoftware/smackx/XHTMLManager.java index a446819c4..d77c2e2d0 100644 --- a/source/org/jivesoftware/smackx/XHTMLManager.java +++ b/source/org/jivesoftware/smackx/XHTMLManager.java @@ -28,6 +28,8 @@ import org.jivesoftware.smackx.packet.DiscoverInfo; import org.jivesoftware.smackx.packet.XHTMLExtension; import java.util.Iterator; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Manages XHTML formatted texts within messages. A XHTMLManager provides a high level access to @@ -38,6 +40,8 @@ import java.util.Iterator; */ public class XHTMLManager { + private static Logger log = Logger.getLogger(XHTMLManager.class.getName()); + private final static String namespace = "http://jabber.org/protocol/xhtml-im"; // Enable the XHTML support on every established connection @@ -137,7 +141,7 @@ public class XHTMLManager { return result.containsFeature(namespace); } catch (XMPPException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error checking if service is available", e); return false; } } diff --git a/source/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java b/source/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java index a33682c87..115ece714 100644 --- a/source/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java +++ b/source/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java @@ -594,7 +594,7 @@ public class InBandBytestreamSession implements BytestreamSession { * Constructor. */ public IBBOutputStream() { - this.buffer = new byte[(byteStreamRequest.getBlockSize()/4)*3]; + this.buffer = new byte[byteStreamRequest.getBlockSize()]; } /** diff --git a/source/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java b/source/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java index 11ef7a9c5..cbafd4115 100644 --- a/source/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java +++ b/source/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java @@ -29,6 +29,8 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jivesoftware.smack.SmackConfiguration; import org.jivesoftware.smack.XMPPException; @@ -67,7 +69,8 @@ import org.jivesoftware.smack.XMPPException; * @author Henning Staib */ public class Socks5Proxy { - + private static Logger log = Logger.getLogger(Socks5Proxy.class.getName()); + /* SOCKS5 proxy singleton */ private static Socks5Proxy socks5Server; @@ -150,8 +153,7 @@ public class Socks5Proxy { } catch (IOException e) { // couldn't setup server - System.err.println("couldn't setup local SOCKS5 proxy on port " - + SmackConfiguration.getLocalSocks5ProxyPort() + ": " + e.getMessage()); + log.log(Level.SEVERE, "couldn't setup local SOCKS5 proxy on port " + SmackConfiguration.getLocalSocks5ProxyPort(), e); } } diff --git a/source/org/jivesoftware/smackx/commands/AdHocCommandManager.java b/source/org/jivesoftware/smackx/commands/AdHocCommandManager.java index 28401d67d..64159aea9 100755 --- a/source/org/jivesoftware/smackx/commands/AdHocCommandManager.java +++ b/source/org/jivesoftware/smackx/commands/AdHocCommandManager.java @@ -46,6 +46,7 @@ import java.util.List; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Logger; /** * An AdHocCommandManager is responsible for keeping the list of available @@ -58,7 +59,6 @@ import java.util.concurrent.ConcurrentHashMap; * @author Gabriel Guardincerri */ public class AdHocCommandManager { - private static final String DISCO_NAMESPACE = "http://jabber.org/protocol/commands"; private static final String discoNode = DISCO_NAMESPACE; @@ -470,7 +470,6 @@ public class AdHocCommandManager { executingCommands.remove(sessionId); } respondError(response, error); - e.printStackTrace(); } } else { @@ -527,7 +526,7 @@ public class AdHocCommandManager { } try { - // TODO: Check that all the requierd fields of the form are + // TODO: Check that all the required fields of the form are // TODO: filled, if not throw an exception. This will simplify the // TODO: construction of new commands @@ -585,8 +584,6 @@ public class AdHocCommandManager { executingCommands.remove(sessionId); } respondError(response, error); - - e.printStackTrace(); } } } @@ -650,12 +647,10 @@ public class AdHocCommandManager { command.setNode(commandInfo.getNode()); } catch (InstantiationException e) { - e.printStackTrace(); throw new XMPPException(new XMPPError( XMPPError.Condition.interna_server_error)); } catch (IllegalAccessException e) { - e.printStackTrace(); throw new XMPPException(new XMPPError( XMPPError.Condition.interna_server_error)); } diff --git a/source/org/jivesoftware/smackx/debugger/EnhancedDebugger.java b/source/org/jivesoftware/smackx/debugger/EnhancedDebugger.java index ab9c29c4a..55aec6060 100644 --- a/source/org/jivesoftware/smackx/debugger/EnhancedDebugger.java +++ b/source/org/jivesoftware/smackx/debugger/EnhancedDebugger.java @@ -52,6 +52,8 @@ import java.io.Writer; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.logging.Level; +import java.util.logging.Logger; /** * The EnhancedDebugger is a debugger that allows to debug sent, received and interpreted messages @@ -64,6 +66,8 @@ import java.util.Date; */ public class EnhancedDebugger implements SmackDebugger { + private static Logger log = Logger.getLogger(EnhancedDebugger.class.getName()); + private static final String NEWLINE = "\n"; private static ImageIcon packetReceivedIcon; @@ -427,7 +431,7 @@ public class EnhancedDebugger implements SmackDebugger { receivedText.replaceRange("", 0, receivedText.getLineEndOffset(0)); } catch (BadLocationException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error with line offset, MAX_TABLE_ROWS is set too low: " + EnhancedDebuggerWindow.MAX_TABLE_ROWS, e); } } receivedText.append(str.substring(0, index + 1)); @@ -462,7 +466,7 @@ public class EnhancedDebugger implements SmackDebugger { sentText.replaceRange("", 0, sentText.getLineEndOffset(0)); } catch (BadLocationException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error with line offset, MAX_TABLE_ROWS is set too low: " + EnhancedDebuggerWindow.MAX_TABLE_ROWS, e); } } @@ -895,28 +899,10 @@ public class EnhancedDebugger implements SmackDebugger { } catch (TransformerConfigurationException tce) { - // Error generated by the parser - System.out.println("\n** Transformer Factory error"); - System.out.println(" " + tce.getMessage()); - - // Use the contained exception, if any - Throwable x = tce; - if (tce.getException() != null) - x = tce.getException(); - x.printStackTrace(); - + log.log(Level.SEVERE, "Transformer Factory error", tce); } catch (TransformerException te) { - // Error generated by the parser - System.out.println("\n** Transformation error"); - System.out.println(" " + te.getMessage()); - - // Use the contained exception, if any - Throwable x = te; - if (te.getException() != null) - x = te.getException(); - x.printStackTrace(); - + log.log(Level.SEVERE, "Transformation error", te); } return str; } diff --git a/source/org/jivesoftware/smackx/entitycaps/cache/SimpleDirectoryPersistentCache.java b/source/org/jivesoftware/smackx/entitycaps/cache/SimpleDirectoryPersistentCache.java index 5d2365463..5be6f264d 100644 --- a/source/org/jivesoftware/smackx/entitycaps/cache/SimpleDirectoryPersistentCache.java +++ b/source/org/jivesoftware/smackx/entitycaps/cache/SimpleDirectoryPersistentCache.java @@ -24,6 +24,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.Reader; import java.io.StringReader; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.provider.IQProvider; @@ -39,13 +41,14 @@ import org.xmlpull.v1.XmlPullParserException; /** * Simple implementation of an EntityCapsPersistentCache that uses a directory * to store the Caps information for every known node. Every node is represented - * by an file. + * by a file. * * @author Florian Schmaus * */ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache { - + private static Logger log = Logger.getLogger(SimpleDirectoryPersistentCache.class.getName()); + private File cacheDir; private StringEncoder filenameEncoder; @@ -54,7 +57,7 @@ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache * cacheDir exists and that it's an directory. *

        * Default filename encoder {@link Base32Encoder}, as this will work on all - * filesystems, both case sensitive and case insensitive. It does however + * file systems, both case sensitive and case insensitive. It does however * produce longer filenames. * * @param cacheDir @@ -91,7 +94,7 @@ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache if (nodeFile.createNewFile()) writeInfoToFile(nodeFile, info); } catch (IOException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Failed to write disco info to file", e); } } @@ -160,7 +163,7 @@ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); parser.setInput(reader); } catch (XmlPullParserException xppe) { - xppe.printStackTrace(); + log.log(Level.SEVERE, "Exception initializing parser", xppe); return null; } diff --git a/source/org/jivesoftware/smackx/forward/Forwarded.java b/source/org/jivesoftware/smackx/forward/Forwarded.java new file mode 100644 index 000000000..16ab403b7 --- /dev/null +++ b/source/org/jivesoftware/smackx/forward/Forwarded.java @@ -0,0 +1,97 @@ +/** + * Copyright 2013 Georg Lukas + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.forward; + +import org.jivesoftware.smack.packet.Packet; +import org.jivesoftware.smack.packet.PacketExtension; +import org.jivesoftware.smackx.packet.DelayInfo; + +/** + * Packet extension for XEP-0297: Stanza Forwarding. + * + * @author Georg Lukas + */ +public class Forwarded implements PacketExtension { + public static final String NAMESPACE = "urn:xmpp:forward:0"; + public static final String ELEMENT_NAME = "forwarded"; + + private DelayInfo delay; + private Packet forwardedPacket; + + /** + * Creates a new Forwarded packet extension. + * + * @param delay an optional {@link DelayInfo} timestamp of the packet. + * @param fwdPacket the packet that is forwarded (required). + */ + public Forwarded(DelayInfo delay, Packet fwdPacket) { + this.delay = delay; + this.forwardedPacket = fwdPacket; + } + + /** + * Creates a new Forwarded packet extension. + * + * @param delay an optional {@link DelayInfo} timestamp of the packet. + * @param fwdPacket the packet that is forwarded (required). + */ + public Forwarded(Packet fwdPacket) { + this.forwardedPacket = fwdPacket; + } + + @Override + public String getElementName() { + return ELEMENT_NAME; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String toXML() { + StringBuilder buf = new StringBuilder(); + buf.append("<").append(getElementName()).append(" xmlns=\"") + .append(getNamespace()).append("\">"); + + if (delay != null) + buf.append(delay.toXML()); + buf.append(forwardedPacket.toXML()); + + buf.append(""); + return buf.toString(); + } + + /** + * get the packet forwarded by this stanza. + * + * @return the {@link Packet} instance (typically a message) that was forwarded. + */ + public Packet getForwardedPacket() { + return forwardedPacket; + } + + /** + * get the timestamp of the forwarded packet. + * + * @return the {@link DelayInfo} representing the time when the original packet was sent. May be null. + */ + public DelayInfo getDelayInfo() { + return delay; + } +} diff --git a/source/org/jivesoftware/smackx/forward/provider/ForwardedProvider.java b/source/org/jivesoftware/smackx/forward/provider/ForwardedProvider.java new file mode 100644 index 000000000..e2bef78c8 --- /dev/null +++ b/source/org/jivesoftware/smackx/forward/provider/ForwardedProvider.java @@ -0,0 +1,55 @@ +/** + * Copyright 2013 Georg Lukas + * + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.smackx.forward.provider; + +import org.jivesoftware.smack.packet.Packet; +import org.jivesoftware.smack.packet.PacketExtension; +import org.jivesoftware.smack.provider.PacketExtensionProvider; +import org.jivesoftware.smack.util.PacketParserUtils; +import org.jivesoftware.smackx.forward.Forwarded; +import org.jivesoftware.smackx.packet.DelayInfo; +import org.xmlpull.v1.XmlPullParser; + +/** + * This class implements the {@link PacketExtensionProvider} to parse + * forwarded messages from a packet. It will return a {@link Forwarded} packet extension. + * + * @author Georg Lukas + */ +public class ForwardedProvider implements PacketExtensionProvider { + public PacketExtension parseExtension(XmlPullParser parser) throws Exception { + DelayInfo di = null; + Packet packet = null; + + boolean done = false; + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("delay")) + di = (DelayInfo)PacketParserUtils.parsePacketExtension(parser.getName(), parser.getNamespace(), parser); + else if (parser.getName().equals("message")) + packet = PacketParserUtils.parseMessage(parser); + else throw new Exception("Unsupported forwarded packet type: " + parser.getName()); + } + else if (eventType == XmlPullParser.END_TAG && parser.getName().equals(Forwarded.ELEMENT_NAME)) + done = true; + } + if (packet == null) + throw new Exception("forwarded extension must contain a packet"); + return new Forwarded(di, packet); + } +} \ No newline at end of file diff --git a/source/org/jivesoftware/smackx/muc/MultiUserChat.java b/source/org/jivesoftware/smackx/muc/MultiUserChat.java index d657ee711..db8a80f73 100644 --- a/source/org/jivesoftware/smackx/muc/MultiUserChat.java +++ b/source/org/jivesoftware/smackx/muc/MultiUserChat.java @@ -31,6 +31,8 @@ import java.util.List; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.ConnectionCreationListener; @@ -76,7 +78,8 @@ import org.jivesoftware.smackx.packet.MUCUser; * @author Gaston Dombiak, Larry Kirschner */ public class MultiUserChat { - + private static Logger log = Logger.getLogger(MultiUserChat.class.getName()); + private final static String discoNamespace = "http://jabber.org/protocol/muc"; private final static String discoNode = "http://jabber.org/protocol/muc#rooms"; @@ -179,7 +182,7 @@ public class MultiUserChat { return result.containsFeature(discoNamespace); } catch (XMPPException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error checking user [" + user + "] for MUC support", e); return false; } } @@ -222,7 +225,7 @@ public class MultiUserChat { return answer.iterator(); } catch (XMPPException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error getting joined rooms for user [" + user + "]", e); // Return an iterator on an empty collection return new ArrayList().iterator(); } @@ -953,13 +956,12 @@ public class MultiUserChat { DiscoverInfo.Identity identity = identities.next(); return identity.getName(); } - // If no Identity was found then the user does not have a reserved room nickname - return null; } catch (XMPPException e) { - e.printStackTrace(); - return null; + log.log(Level.SEVERE, "Error retrieving room nickname", e); } + // If no Identity was found then the user does not have a reserved room nickname + return null; } /** @@ -2061,11 +2063,11 @@ public class MultiUserChat { method.invoke(listener, params); } } catch (NoSuchMethodException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Failed to invoke method on UserStatusListener", e); } catch (InvocationTargetException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Failed to invoke method on UserStatusListener", e); } catch (IllegalAccessException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Failed to invoke method on UserStatusListener", e); } } @@ -2112,11 +2114,11 @@ public class MultiUserChat { method.invoke(listener, params.toArray()); } } catch (NoSuchMethodException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Failed to invoke method on ParticipantStatusListener", e); } catch (InvocationTargetException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Failed to invoke method on ParticipantStatusListener", e); } catch (IllegalAccessException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Failed to invoke method on ParticipantStatusListener", e); } } diff --git a/source/org/jivesoftware/smackx/packet/DiscoverInfo.java b/source/org/jivesoftware/smackx/packet/DiscoverInfo.java index 884c1f529..c3dc063fc 100644 --- a/source/org/jivesoftware/smackx/packet/DiscoverInfo.java +++ b/source/org/jivesoftware/smackx/packet/DiscoverInfo.java @@ -337,6 +337,7 @@ public class DiscoverInfo extends IQ { * 'type' attribute refer to Jabber::Registrar * * @param type the identity's type. + * @deprecated As per the spec, this field is mandatory and the 3 argument constructor should be used instead. */ public void setType(String type) { this.type = type; diff --git a/source/org/jivesoftware/smackx/packet/PEPEvent.java b/source/org/jivesoftware/smackx/packet/PEPEvent.java index 48f1de25a..e9dab0e84 100644 --- a/source/org/jivesoftware/smackx/packet/PEPEvent.java +++ b/source/org/jivesoftware/smackx/packet/PEPEvent.java @@ -30,6 +30,7 @@ import org.jivesoftware.smack.packet.PacketExtension; * * @author Jeff Williams */ +@Deprecated public class PEPEvent implements PacketExtension { PEPItem item; diff --git a/source/org/jivesoftware/smackx/packet/PEPItem.java b/source/org/jivesoftware/smackx/packet/PEPItem.java index c3ff6f4f0..b216ebb66 100644 --- a/source/org/jivesoftware/smackx/packet/PEPItem.java +++ b/source/org/jivesoftware/smackx/packet/PEPItem.java @@ -30,6 +30,7 @@ import org.jivesoftware.smack.packet.PacketExtension; * * @author Jeff Williams */ +@Deprecated public abstract class PEPItem implements PacketExtension { String id; diff --git a/source/org/jivesoftware/smackx/packet/PEPPubSub.java b/source/org/jivesoftware/smackx/packet/PEPPubSub.java index 420ce6127..780bea210 100644 --- a/source/org/jivesoftware/smackx/packet/PEPPubSub.java +++ b/source/org/jivesoftware/smackx/packet/PEPPubSub.java @@ -30,6 +30,7 @@ import org.jivesoftware.smack.packet.IQ; * * @author Jeff Williams */ +@Deprecated public class PEPPubSub extends IQ { PEPItem item; diff --git a/source/org/jivesoftware/smackx/packet/Time.java b/source/org/jivesoftware/smackx/packet/Time.java index 5294e77c3..fddc86998 100644 --- a/source/org/jivesoftware/smackx/packet/Time.java +++ b/source/org/jivesoftware/smackx/packet/Time.java @@ -27,6 +27,8 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; +import java.util.logging.Level; +import java.util.logging.Logger; /** * A Time IQ packet, which is used by XMPP clients to exchange their respective local @@ -61,7 +63,8 @@ import java.util.TimeZone; * @author Matt Tucker */ public class Time extends IQ { - + private static Logger log = Logger.getLogger(Time.class.getName()); + private static SimpleDateFormat utcFormat = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss"); private static DateFormat displayFormat = DateFormat.getDateTimeInstance(); @@ -94,7 +97,7 @@ public class Time extends IQ { /** * Returns the local time or null if the time hasn't been set. * - * @return the lcocal time. + * @return the local time. */ public Date getTime() { if (utc == null) { @@ -109,7 +112,7 @@ public class Time extends IQ { date = cal.getTime(); } catch (Exception e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error getting local time", e); } return date; } diff --git a/source/org/jivesoftware/smackx/packet/VCard.java b/source/org/jivesoftware/smackx/packet/VCard.java index c9aa65856..98598915d 100644 --- a/source/org/jivesoftware/smackx/packet/VCard.java +++ b/source/org/jivesoftware/smackx/packet/VCard.java @@ -33,6 +33,8 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jivesoftware.smack.Connection; import org.jivesoftware.smack.PacketCollector; @@ -85,6 +87,8 @@ import org.jivesoftware.smack.util.StringUtils; * @author Kirill Maximov (kir@maxkir.com) */ public class VCard extends IQ { + private static Logger log = Logger.getLogger(VCard.class.getName()); + private static final String DEFAULT_MIME_TYPE = "image/jpeg"; /** @@ -332,7 +336,7 @@ public class VCard extends IQ { bytes = getBytes(avatarURL); } catch (IOException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error getting bytes from URL: " + avatarURL, e); } setAvatar(bytes); @@ -489,7 +493,7 @@ public class VCard extends IQ { digest = MessageDigest.getInstance("SHA-1"); } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Failed to get message digest", e); return null; } @@ -582,7 +586,7 @@ public class VCard extends IQ { result = (VCard) packet; } catch (ClassCastException e) { - System.out.println("No VCard for " + user); + log.log(Level.SEVERE, "No VCard for " + user, e); return; } diff --git a/source/org/jivesoftware/smackx/provider/ExtensionInitializer.java b/source/org/jivesoftware/smackx/provider/ExtensionInitializer.java new file mode 100644 index 000000000..3a907ddba --- /dev/null +++ b/source/org/jivesoftware/smackx/provider/ExtensionInitializer.java @@ -0,0 +1,16 @@ +package org.jivesoftware.smackx.provider; + +import org.jivesoftware.smack.provider.UrlProviderFileInitializer; + +/** + * Loads the default provider file for the Smack extensions on initialization. + * + * @author Robin Collier + * + */ +public class ExtensionInitializer extends UrlProviderFileInitializer { + @Override + protected String getFilePath() { + return "classpath:META-INF/extension.providers"; + } +} diff --git a/source/org/jivesoftware/smackx/provider/StreamInitiationProvider.java b/source/org/jivesoftware/smackx/provider/StreamInitiationProvider.java index 11ab33976..bd2d54ee1 100644 --- a/source/org/jivesoftware/smackx/provider/StreamInitiationProvider.java +++ b/source/org/jivesoftware/smackx/provider/StreamInitiationProvider.java @@ -21,6 +21,8 @@ package org.jivesoftware.smackx.provider; import java.text.ParseException; import java.util.Date; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.provider.IQProvider; @@ -37,7 +39,8 @@ import org.xmlpull.v1.XmlPullParser; * */ public class StreamInitiationProvider implements IQProvider { - + private static Logger log = Logger.getLogger(StreamInitiationProvider.class.getName()); + public IQ parseIQ(final XmlPullParser parser) throws Exception { boolean done = false; @@ -90,7 +93,7 @@ public class StreamInitiationProvider implements IQProvider { fileSize = Long.parseLong(size); } catch (NumberFormatException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Failed to parse file size from " + fileSize, e); } } diff --git a/source/org/jivesoftware/smackx/provider/VCardProvider.java b/source/org/jivesoftware/smackx/provider/VCardProvider.java index 8fa04211d..25c7110a2 100644 --- a/source/org/jivesoftware/smackx/provider/VCardProvider.java +++ b/source/org/jivesoftware/smackx/provider/VCardProvider.java @@ -34,6 +34,8 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * vCard provider. @@ -42,7 +44,8 @@ import java.util.List; * @author Derek DeMoro */ public class VCardProvider implements IQProvider { - + private static Logger log = Logger.getLogger(VCardProvider.class.getName()); + private static final String PREFERRED_ENCODING = "UTF-8"; public IQ parseIQ(XmlPullParser parser) throws Exception { @@ -71,10 +74,10 @@ public class VCardProvider implements IQProvider { } } catch (XmlPullParserException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Exception parsing VCard", e); } catch (IOException e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Exception parsing VCard", e); } String xmlText = sb.toString(); diff --git a/test-unit/org/jivesoftware/smack/ChatConnectionTest.java b/test-unit/org/jivesoftware/smack/ChatConnectionTest.java index 3ded1ca44..72d56ff50 100644 --- a/test-unit/org/jivesoftware/smack/ChatConnectionTest.java +++ b/test-unit/org/jivesoftware/smack/ChatConnectionTest.java @@ -22,267 +22,419 @@ package org.jivesoftware.smack; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import org.jivesoftware.smack.ChatManager.MatchMode; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Message.Type; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.PacketExtension; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; -/** - * Tests that verifies the correct behavior of the {@see Roster} implementation. - * - * @see Roster - * @see Roster Management - * @author Guenther Niess - */ public class ChatConnectionTest { private DummyConnection connection; @Before public void setUp() throws Exception { - // Uncomment this to enable debug output - //Connection.DEBUG_ENABLED = true; - - connection = new DummyConnection(); - connection.connect(); - connection.login("me", "secret"); + connection = getConnection(); } @After public void tearDown() throws Exception { - if (connection != null) - connection.disconnect(); + if (connection != null) + connection.disconnect(); + } + + @Test + public void validateDefaultSetNormalIncluded() { + ChatManager.setDefaultIsNormalIncluded(false); + assertFalse(getConnection().getChatManager().isNormalIncluded()); + + ChatManager.setDefaultIsNormalIncluded(true); + assertTrue(getConnection().getChatManager().isNormalIncluded()); + } + + @Test + public void validateDefaultSetMatchMode() { + ChatManager.setDefaultMatchMode(MatchMode.NONE); + assertEquals(MatchMode.NONE, getConnection().getChatManager().getMatchMode()); + + ChatManager.setDefaultMatchMode(MatchMode.BARE_JID); + assertEquals(MatchMode.BARE_JID, getConnection().getChatManager().getMatchMode()); + } + + @Test + public void validateMessageTypeWithDefaults() { + DummyConnection dc = getConnection(); + ChatManager cm = dc.getChatManager(); + TestChatManagerListener listener = new TestChatManagerListener(); + cm.addChatListener(listener); + Message incomingChat = createChatPacket("134", true); + incomingChat.setType(Type.chat); + processServerMessage(incomingChat, dc); + assertNotNull(listener.getNewChat()); + + dc = getConnection(); + cm = dc.getChatManager(); + listener = new TestChatManagerListener(); + cm.addChatListener(listener); + incomingChat = createChatPacket("134", true); + incomingChat.setType(Type.normal); + processServerMessage(incomingChat, dc); + assertNotNull(listener.getNewChat()); + + dc = getConnection(); + cm = dc.getChatManager(); + listener = new TestChatManagerListener(); + cm.addChatListener(listener); + incomingChat = createChatPacket("134", true); + incomingChat.setType(Type.groupchat); + processServerMessage(incomingChat, dc); + assertNull(listener.getNewChat()); + + dc = getConnection(); + cm = dc.getChatManager(); + listener = new TestChatManagerListener(); + cm.addChatListener(listener); + incomingChat = createChatPacket("134", true); + incomingChat.setType(Type.headline); + processServerMessage(incomingChat, dc); + assertNull(listener.getNewChat()); + } + + @Test + public void validateMessageTypeWithNoNormal() { + ChatManager.setDefaultIsNormalIncluded(false); + DummyConnection dc = getConnection(); + ChatManager cm = dc.getChatManager(); + TestChatManagerListener listener = new TestChatManagerListener(); + cm.addChatListener(listener); + Message incomingChat = createChatPacket("134", true); + incomingChat.setType(Type.chat); + processServerMessage(incomingChat, dc); + assertNotNull(listener.getNewChat()); + + dc = getConnection(); + cm = dc.getChatManager(); + listener = new TestChatManagerListener(); + cm.addChatListener(listener); + incomingChat = createChatPacket("134", true); + incomingChat.setType(Type.normal); + processServerMessage(incomingChat, dc); + assertNull(listener.getNewChat()); + } + + // No thread behaviour + @Test + public void chatMatchedOnJIDWhenNoThreadBareMode() { + // MatchMode.BARE_JID is the default, so setting required. + DummyConnection con = getConnection(); + TestMessageListener msgListener = new TestMessageListener(); + TestChatManagerListener listener = new TestChatManagerListener(msgListener); + con.getChatManager().addChatListener(listener); + Packet incomingChat = createChatPacket(null, true); + processServerMessage(incomingChat, con); + Chat newChat = listener.getNewChat(); + assertNotNull(newChat); + + // Should match on chat with full jid + incomingChat = createChatPacket(null, true); + processServerMessage(incomingChat, con); + assertEquals(2, msgListener.getNumMessages()); + + // Should match on chat with bare jid + incomingChat = createChatPacket(null, false); + processServerMessage(incomingChat, con); + assertEquals(3, msgListener.getNumMessages()); + } + + @Test + public void chatMatchedOnJIDWhenNoThreadJidMode() { + DummyConnection con = getConnection(); + TestMessageListener msgListener = new TestMessageListener(); + TestChatManagerListener listener = new TestChatManagerListener(msgListener); + ChatManager cm = con.getChatManager(); + cm.setMatchMode(MatchMode.SUPPLIED_JID); + cm.addChatListener(listener); + Packet incomingChat = createChatPacket(null, true); + processServerMessage(incomingChat, con); + Chat newChat = listener.getNewChat(); + assertNotNull(newChat); + cm.removeChatListener(listener); + + // Should match on chat with full jid + incomingChat = createChatPacket(null, true); + processServerMessage(incomingChat, con); + assertEquals(2, msgListener.getNumMessages()); + + // Should not match on chat with bare jid + TestChatManagerListener listener2 = new TestChatManagerListener(); + cm.addChatListener(listener2); + incomingChat = createChatPacket(null, false); + processServerMessage(incomingChat, con); + assertEquals(2, msgListener.getNumMessages()); + assertNotNull(listener2.getNewChat()); + } + + @Test + public void chatMatchedOnJIDWhenNoThreadNoneMode() { + DummyConnection con = getConnection(); + TestMessageListener msgListener = new TestMessageListener(); + TestChatManagerListener listener = new TestChatManagerListener(msgListener); + ChatManager cm = con.getChatManager(); + cm.setMatchMode(MatchMode.NONE); + cm.addChatListener(listener); + Packet incomingChat = createChatPacket(null, true); + processServerMessage(incomingChat, con); + Chat newChat = listener.getNewChat(); + assertNotNull(newChat); + assertEquals(1, msgListener.getNumMessages()); + cm.removeChatListener(listener); + + // Should not match on chat with full jid + TestChatManagerListener listener2 = new TestChatManagerListener(); + cm.addChatListener(listener2); + incomingChat = createChatPacket(null, true); + processServerMessage(incomingChat, con); + assertEquals(1, msgListener.getNumMessages()); + assertNotNull(newChat); + cm.removeChatListener(listener2); + + // Should not match on chat with bare jid + TestChatManagerListener listener3 = new TestChatManagerListener(); + cm.addChatListener(listener3); + incomingChat = createChatPacket(null, false); + processServerMessage(incomingChat, con); + assertEquals(1, msgListener.getNumMessages()); + assertNotNull(listener3.getNewChat()); } /** - * Confirm that a new chat is created when a chat message is received but - * there is no thread id for a user with only a base jid. + * Confirm that an existing chat created with a base jid is matched to an incoming chat message that has no thread + * id and the user is a full jid. */ @Test - public void chatCreatedWithIncomingChatNoThreadBaseJid() - { - TestChatManagerListener listener = new TestChatManagerListener(); - connection.getChatManager().addChatListener(listener); + public void chatFoundWhenNoThreadFullJid() { + TestChatManagerListener listener = new TestChatManagerListener(); + connection.getChatManager().addChatListener(listener); + Chat outgoing = connection.getChatManager().createChat("you@testserver", null); - Packet incomingChat = createChatPacket(null, false); - processServerMessage(incomingChat); + Packet incomingChat = createChatPacket(null, true); + processServerMessage(incomingChat); - Chat newChat = listener.getNewChat(); - assertNotNull(newChat); + Chat newChat = listener.getNewChat(); + assertNotNull(newChat); + assertTrue(newChat == outgoing); } /** - * Confirm that a new chat is created when a chat message is received but - * there is no thread id for a user with a full jid. + * Confirm that an existing chat created with a base jid is matched to an incoming chat message that has no thread + * id and the user is a base jid. */ @Test - public void chatCreatedWhenIncomingChatNoThreadFullJid() - { - TestChatManagerListener listener = new TestChatManagerListener(); - connection.getChatManager().addChatListener(listener); + public void chatFoundWhenNoThreadBaseJid() { + TestChatManagerListener listener = new TestChatManagerListener(); + connection.getChatManager().addChatListener(listener); + Chat outgoing = connection.getChatManager().createChat("you@testserver", null); - Packet incomingChat = createChatPacket(null, true); - processServerMessage(incomingChat); + Packet incomingChat = createChatPacket(null, false); + processServerMessage(incomingChat); - Chat newChat = listener.getNewChat(); - assertNotNull(newChat); + Chat newChat = listener.getNewChat(); + assertNotNull(newChat); + assertTrue(newChat == outgoing); } /** - * Confirm that an existing chat created with a base jid is matched to an - * incoming chat message that has no thread id and the user is a full jid. + * Confirm that an existing chat created with a base jid is matched to an incoming chat message that has the same id + * and the user is a full jid. */ @Test - public void chatFoundWhenNoThreadFullJid() - { - TestChatManagerListener listener = new TestChatManagerListener(); - connection.getChatManager().addChatListener(listener); - Chat outgoing = connection.getChatManager().createChat("you@testserver", null); + public void chatFoundWithSameThreadFullJid() { + TestChatManagerListener listener = new TestChatManagerListener(); + connection.getChatManager().addChatListener(listener); + Chat outgoing = connection.getChatManager().createChat("you@testserver", null); - Packet incomingChat = createChatPacket(null, true); - processServerMessage(incomingChat); + Packet incomingChat = createChatPacket(outgoing.getThreadID(), true); + processServerMessage(incomingChat); - Chat newChat = listener.getNewChat(); - assertNotNull(newChat); - assertTrue(newChat == outgoing); + Chat newChat = listener.getNewChat(); + assertNotNull(newChat); + assertTrue(newChat == outgoing); } /** - * Confirm that an existing chat created with a base jid is matched to an - * incoming chat message that has no thread id and the user is a base jid. + * Confirm that an existing chat created with a base jid is matched to an incoming chat message that has the same id + * and the user is a base jid. */ @Test - public void chatFoundWhenNoThreadBaseJid() - { - TestChatManagerListener listener = new TestChatManagerListener(); - connection.getChatManager().addChatListener(listener); - Chat outgoing = connection.getChatManager().createChat("you@testserver", null); + public void chatFoundWithSameThreadBaseJid() { + TestChatManagerListener listener = new TestChatManagerListener(); + connection.getChatManager().addChatListener(listener); + Chat outgoing = connection.getChatManager().createChat("you@testserver", null); - Packet incomingChat = createChatPacket(null, false); - processServerMessage(incomingChat); + Packet incomingChat = createChatPacket(outgoing.getThreadID(), false); + processServerMessage(incomingChat); - Chat newChat = listener.getNewChat(); - assertNotNull(newChat); - assertTrue(newChat == outgoing); + Chat newChat = listener.getNewChat(); + assertNotNull(newChat); + assertTrue(newChat == outgoing); } /** - * Confirm that an existing chat created with a base jid is matched to an - * incoming chat message that has the same id and the user is a full jid. + * Confirm that an existing chat created with a base jid is not matched to an incoming chat message that has a + * different id and the same user as a base jid. */ @Test - public void chatFoundWithSameThreadFullJid() - { - TestChatManagerListener listener = new TestChatManagerListener(); - connection.getChatManager().addChatListener(listener); - Chat outgoing = connection.getChatManager().createChat("you@testserver", null); + public void chatNotFoundWithDiffThreadBaseJid() { + TestChatManagerListener listener = new TestChatManagerListener(); + connection.getChatManager().addChatListener(listener); + Chat outgoing = connection.getChatManager().createChat("you@testserver", null); - Packet incomingChat = createChatPacket(outgoing.getThreadID(), true); - processServerMessage(incomingChat); + Packet incomingChat = createChatPacket(outgoing.getThreadID() + "ff", false); + processServerMessage(incomingChat); - Chat newChat = listener.getNewChat(); - assertNotNull(newChat); - assertTrue(newChat == outgoing); + Chat newChat = listener.getNewChat(); + assertNotNull(newChat); + assertFalse(newChat == outgoing); } /** - * Confirm that an existing chat created with a base jid is matched to an - * incoming chat message that has the same id and the user is a base jid. + * Confirm that an existing chat created with a base jid is not matched to an incoming chat message that has a + * different id and the same base jid. */ @Test - public void chatFoundWithSameThreadBaseJid() - { - TestChatManagerListener listener = new TestChatManagerListener(); - connection.getChatManager().addChatListener(listener); - Chat outgoing = connection.getChatManager().createChat("you@testserver", null); + public void chatNotFoundWithDiffThreadFullJid() { + TestChatManagerListener listener = new TestChatManagerListener(); + connection.getChatManager().addChatListener(listener); + Chat outgoing = connection.getChatManager().createChat("you@testserver", null); - Packet incomingChat = createChatPacket(outgoing.getThreadID(), false); - processServerMessage(incomingChat); + Packet incomingChat = createChatPacket(outgoing.getThreadID() + "ff", true); + processServerMessage(incomingChat); - Chat newChat = listener.getNewChat(); - assertNotNull(newChat); - assertTrue(newChat == outgoing); + Chat newChat = listener.getNewChat(); + assertNotNull(newChat); + assertFalse(newChat == outgoing); } - /** - * Confirm that an existing chat created with a base jid is not matched to - * an incoming chat message that has a different id and the same user as a - * base jid. - */ - @Ignore @Test - public void chatNotFoundWithDiffThreadBaseJid() - { - TestChatManagerListener listener = new TestChatManagerListener(); - connection.getChatManager().addChatListener(listener); - Chat outgoing = connection.getChatManager().createChat("you@testserver", null); + public void chatNotMatchedWithTypeNormal() { + TestChatManagerListener listener = new TestChatManagerListener(); + DummyConnection con = getConnection(); + ChatManager cm = con.getChatManager(); + cm.setNormalIncluded(false); + cm.addChatListener(listener); - Packet incomingChat = createChatPacket(outgoing.getThreadID() + "ff", false); - processServerMessage(incomingChat); + Message incomingChat = createChatPacket(null, false); + incomingChat.setType(Type.normal); + processServerMessage(incomingChat); - Chat newChat = listener.getNewChat(); - assertNotNull(newChat); - assertFalse(newChat == outgoing); + assertNull(listener.getNewChat()); } - /** - * Confirm that an existing chat created with a base jid is not matched to - * an incoming chat message that has a different id and the same base jid. - */ - @Ignore - @Test - public void chatNotFoundWithDiffThreadFullJid() - { - TestChatManagerListener listener = new TestChatManagerListener(); - connection.getChatManager().addChatListener(listener); - Chat outgoing = connection.getChatManager().createChat("you@testserver", null); + private ChatManager getChatManager(boolean includeNormal, MatchMode mode) { + ChatManager cm = getConnection().getChatManager(); + cm.setMatchMode(mode); + cm.setNormalIncluded(includeNormal); + return cm; + } + + private DummyConnection getConnection() { + DummyConnection con = new DummyConnection(); + + try { + con.connect(); + con.login("me", "secret"); + } catch (XMPPException e) { + // No need for handling in a dummy connection. + } + return con; + } + private Message createChatPacket(final String threadId, final boolean isFullJid) { + Message chatMsg = new Message("me@testserver", Message.Type.chat); + chatMsg.setBody("the body message - " + System.currentTimeMillis()); + chatMsg.setFrom("you@testserver" + (isFullJid ? "/resource" : "")); - Packet incomingChat = createChatPacket(outgoing.getThreadID() + "ff", true); - processServerMessage(incomingChat); - - Chat newChat = listener.getNewChat(); - assertNotNull(newChat); - assertFalse(newChat == outgoing); + if (threadId != null) + chatMsg.setThread(threadId); + return chatMsg; } - private Packet createChatPacket(final String threadId, final boolean isFullJid) - { - Message chatMsg = new Message("me@testserver", Message.Type.chat); - chatMsg.setBody("the body message"); - chatMsg.setFrom("you@testserver" + (isFullJid ? "/resource" : "")); - - if (threadId != null) - chatMsg.addExtension(new PacketExtension() - { - @Override - public String toXML() - { - return "" + threadId + ""; - } - - @Override - public String getNamespace() - { - return null; - } - - @Override - public String getElementName() - { - return "thread"; - } - }); - return chatMsg; + private void processServerMessage(Packet incomingChat) { + processServerMessage(incomingChat, connection); + } + + private void processServerMessage(Packet incomingChat, DummyConnection con) { + TestChatServer chatServer = new TestChatServer(incomingChat, con); + chatServer.start(); + try { + chatServer.join(); + } catch (InterruptedException e) { + fail(); + } } - private void processServerMessage(Packet incomingChat) - { - TestChatServer chatServer = new TestChatServer(incomingChat); - chatServer.start(); - try - { - chatServer.join(); - } catch (InterruptedException e) - { - fail(); - } + class TestChatManagerListener implements ChatManagerListener { + private Chat newChat; + private MessageListener listener; + + public TestChatManagerListener(TestMessageListener msgListener) { + listener = msgListener; + } + + public TestChatManagerListener() { + } + + @Override + public void chatCreated(Chat chat, boolean createdLocally) { + newChat = chat; + + if (listener != null) + newChat.addMessageListener(listener); + } + + public Chat getNewChat() { + return newChat; + } + } + + private class TestChatServer extends Thread { + private Packet chatPacket; + private DummyConnection con; + + TestChatServer(Packet chatMsg, DummyConnection conect) { + chatPacket = chatMsg; + con = conect; + } + + @Override + public void run() { + con.processPacket(chatPacket); + } } - class TestChatManagerListener implements ChatManagerListener - { - private Chat newChat; - - @Override - public void chatCreated(Chat chat, boolean createdLocally) - { - newChat = chat; - } - - public Chat getNewChat() - { - return newChat; - } - } - - private class TestChatServer extends Thread - { - private Packet chatPacket; - - TestChatServer(Packet chatMsg) - { - chatPacket = chatMsg; - } - - @Override - public void run() - { - connection.processPacket(chatPacket); - } - } + private class TestMessageListener implements MessageListener { + private Chat msgChat; + private int counter = 0; + + @Override + public void processMessage(Chat chat, Message message) { + msgChat = chat; + counter++; + } + + public Chat getChat() { + return msgChat; + } + + public int getNumMessages() { + return counter; + } + }; } diff --git a/test-unit/org/jivesoftware/smack/DummyConnection.java b/test-unit/org/jivesoftware/smack/DummyConnection.java index 57753a1ba..308644a49 100644 --- a/test-unit/org/jivesoftware/smack/DummyConnection.java +++ b/test-unit/org/jivesoftware/smack/DummyConnection.java @@ -26,6 +26,14 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import org.jivesoftware.smack.Connection; +import org.jivesoftware.smack.ConnectionConfiguration; +import org.jivesoftware.smack.ConnectionCreationListener; +import org.jivesoftware.smack.ConnectionListener; +import org.jivesoftware.smack.PacketCollector; +import org.jivesoftware.smack.Roster; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.Connection.ListenerWrapper; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.Presence; diff --git a/test-unit/org/jivesoftware/smack/keepalive/KeepaliveTest.java b/test-unit/org/jivesoftware/smack/keepalive/KeepaliveTest.java index 937bcebbb..240f9160b 100644 --- a/test-unit/org/jivesoftware/smack/keepalive/KeepaliveTest.java +++ b/test-unit/org/jivesoftware/smack/keepalive/KeepaliveTest.java @@ -1,7 +1,6 @@ package org.jivesoftware.smack.keepalive; import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.Properties; @@ -13,16 +12,13 @@ import org.jivesoftware.smack.DummyConnection; import org.jivesoftware.smack.PacketInterceptor; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.SmackConfiguration; -import org.jivesoftware.smack.TestUtils; import org.jivesoftware.smack.ThreadedDummyConnection; import org.jivesoftware.smack.filter.IQTypeFilter; import org.jivesoftware.smack.filter.PacketTypeFilter; -import org.jivesoftware.smack.keepalive.KeepAliveManager; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.ping.PingFailedListener; import org.jivesoftware.smack.ping.packet.Ping; -import org.jivesoftware.smack.util.PacketParserUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/test-unit/org/jivesoftware/smack/packet/StreamErrorTest.java b/test-unit/org/jivesoftware/smack/packet/StreamErrorTest.java index 9c3e9dfc6..302ef0e7d 100644 --- a/test-unit/org/jivesoftware/smack/packet/StreamErrorTest.java +++ b/test-unit/org/jivesoftware/smack/packet/StreamErrorTest.java @@ -2,8 +2,8 @@ package org.jivesoftware.smack.packet; import static org.junit.Assert.*; -import org.jivesoftware.smack.TestUtils; import org.jivesoftware.smack.packet.StreamError; +import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smack.util.PacketParserUtils; import org.junit.Test; import org.xmlpull.v1.XmlPullParser; diff --git a/test-unit/org/jivesoftware/smack/parsing/ParsingExceptionTest.java b/test-unit/org/jivesoftware/smack/parsing/ParsingExceptionTest.java index fd674ae0c..121d1e2a1 100644 --- a/test-unit/org/jivesoftware/smack/parsing/ParsingExceptionTest.java +++ b/test-unit/org/jivesoftware/smack/parsing/ParsingExceptionTest.java @@ -3,11 +3,11 @@ package org.jivesoftware.smack.parsing; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import org.jivesoftware.smack.TestUtils; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.provider.PacketExtensionProvider; import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smack.util.PacketParserUtils; import org.junit.After; import org.junit.Before; diff --git a/test-unit/org/jivesoftware/smack/TestUtils.java b/test-unit/org/jivesoftware/smack/test/util/TestUtils.java similarity index 98% rename from test-unit/org/jivesoftware/smack/TestUtils.java rename to test-unit/org/jivesoftware/smack/test/util/TestUtils.java index 0eae51e35..7d240bb03 100644 --- a/test-unit/org/jivesoftware/smack/TestUtils.java +++ b/test-unit/org/jivesoftware/smack/test/util/TestUtils.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.smack; +package org.jivesoftware.smack.test.util; import java.io.IOException; import java.io.StringReader; diff --git a/test-unit/org/jivesoftware/smack/util/PacketParserUtilsTest.java b/test-unit/org/jivesoftware/smack/util/PacketParserUtilsTest.java index e7c25161a..5b4025ba4 100644 --- a/test-unit/org/jivesoftware/smack/util/PacketParserUtilsTest.java +++ b/test-unit/org/jivesoftware/smack/util/PacketParserUtilsTest.java @@ -24,10 +24,10 @@ import java.util.TimeZone; import org.custommonkey.xmlunit.DetailedDiff; import org.custommonkey.xmlunit.Diff; -import org.jivesoftware.smack.TestUtils; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smackx.packet.DelayInformation; import org.junit.Ignore; import org.junit.Test; diff --git a/test-unit/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionMessageTest.java b/test-unit/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionMessageTest.java index 5789bbb25..75450f3ab 100644 --- a/test-unit/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionMessageTest.java +++ b/test-unit/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionMessageTest.java @@ -57,7 +57,6 @@ public class InBandBytestreamSessionMessageTest { String sessionID = "session_id"; int blockSize = 10; - int dataSize = blockSize/4 * 3; // protocol verifier Protocol protocol; @@ -120,7 +119,7 @@ public class InBandBytestreamSessionMessageTest { protocol.addResponse(null, incrementingSequence); protocol.addResponse(null, incrementingSequence); - byte[] controlData = new byte[dataSize * 3]; + byte[] controlData = new byte[blockSize * 3]; OutputStream outputStream = session.getOutputStream(); outputStream.write(controlData); @@ -145,7 +144,7 @@ public class InBandBytestreamSessionMessageTest { protocol.addResponse(null, incrementingSequence); protocol.addResponse(null, incrementingSequence); - byte[] controlData = new byte[dataSize * 3]; + byte[] controlData = new byte[blockSize * 3]; OutputStream outputStream = session.getOutputStream(); for (byte b : controlData) { @@ -172,11 +171,11 @@ public class InBandBytestreamSessionMessageTest { protocol.addResponse(null, incrementingSequence); protocol.addResponse(null, incrementingSequence); - byte[] controlData = new byte[(dataSize * 3) - 2]; + byte[] controlData = new byte[(blockSize * 3) - 2]; OutputStream outputStream = session.getOutputStream(); int off = 0; - for (int i = 1; off+i <= controlData.length; i++) { + for (int i = 1; i <= 7; i++) { outputStream.write(controlData, off, i); off += i; } @@ -193,7 +192,7 @@ public class InBandBytestreamSessionMessageTest { */ @Test public void shouldSendThirtyDataPackets() throws Exception { - byte[] controlData = new byte[dataSize * 3]; + byte[] controlData = new byte[blockSize * 3]; InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); @@ -220,7 +219,7 @@ public class InBandBytestreamSessionMessageTest { */ @Test public void shouldSendNothingOnSuccessiveCallsToFlush() throws Exception { - byte[] controlData = new byte[dataSize * 3]; + byte[] controlData = new byte[blockSize * 3]; InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); @@ -291,7 +290,7 @@ public class InBandBytestreamSessionMessageTest { public void shouldReadAllReceivedData1() throws Exception { // create random data Random rand = new Random(); - byte[] controlData = new byte[3 * dataSize]; + byte[] controlData = new byte[3 * blockSize]; rand.nextBytes(controlData); // get IBB sessions data packet listener @@ -301,8 +300,8 @@ public class InBandBytestreamSessionMessageTest { PacketListener listener = Whitebox.getInternalState(inputStream, PacketListener.class); // verify data packet and notify listener - for (int i = 0; i < controlData.length / dataSize; i++) { - String base64Data = StringUtils.encodeBase64(controlData, i * dataSize, dataSize, + for (int i = 0; i < controlData.length / blockSize; i++) { + String base64Data = StringUtils.encodeBase64(controlData, i * blockSize, blockSize, false); DataPacketExtension dpe = new DataPacketExtension(sessionID, i, base64Data); Message dataMessage = new Message(); @@ -310,14 +309,14 @@ public class InBandBytestreamSessionMessageTest { listener.processPacket(dataMessage); } - byte[] bytes = new byte[3 * dataSize]; + byte[] bytes = new byte[3 * blockSize]; int read = 0; - read = inputStream.read(bytes, 0, dataSize); - assertEquals(dataSize, read); - read = inputStream.read(bytes, dataSize, dataSize); - assertEquals(dataSize, read); - read = inputStream.read(bytes, dataSize*2, dataSize); - assertEquals(dataSize, read); + read = inputStream.read(bytes, 0, blockSize); + assertEquals(blockSize, read); + read = inputStream.read(bytes, 10, blockSize); + assertEquals(blockSize, read); + read = inputStream.read(bytes, 20, blockSize); + assertEquals(blockSize, read); // verify data for (int i = 0; i < bytes.length; i++) { @@ -337,7 +336,7 @@ public class InBandBytestreamSessionMessageTest { public void shouldReadAllReceivedData2() throws Exception { // create random data Random rand = new Random(); - byte[] controlData = new byte[3 * dataSize]; + byte[] controlData = new byte[3 * blockSize]; rand.nextBytes(controlData); // get IBB sessions data packet listener @@ -347,8 +346,8 @@ public class InBandBytestreamSessionMessageTest { PacketListener listener = Whitebox.getInternalState(inputStream, PacketListener.class); // verify data packet and notify listener - for (int i = 0; i < controlData.length / dataSize; i++) { - String base64Data = StringUtils.encodeBase64(controlData, i * dataSize, dataSize, + for (int i = 0; i < controlData.length / blockSize; i++) { + String base64Data = StringUtils.encodeBase64(controlData, i * blockSize, blockSize, false); DataPacketExtension dpe = new DataPacketExtension(sessionID, i, base64Data); Message dataMessage = new Message(); @@ -357,7 +356,7 @@ public class InBandBytestreamSessionMessageTest { } // read data - byte[] bytes = new byte[3 * dataSize]; + byte[] bytes = new byte[3 * blockSize]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) inputStream.read(); } diff --git a/test-unit/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionTest.java b/test-unit/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionTest.java index b715af10a..5754b1031 100644 --- a/test-unit/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionTest.java +++ b/test-unit/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSessionTest.java @@ -57,8 +57,7 @@ public class InBandBytestreamSessionTest { String xmppServer = "xmpp-server"; String sessionID = "session_id"; - int blockSize = 20; - int dataSize = blockSize/4 * 3; + int blockSize = 10; // protocol verifier Protocol protocol; @@ -120,7 +119,7 @@ public class InBandBytestreamSessionTest { protocol.addResponse(resultIQ, incrementingSequence); protocol.addResponse(resultIQ, incrementingSequence); - byte[] controlData = new byte[dataSize * 3]; + byte[] controlData = new byte[blockSize * 3]; OutputStream outputStream = session.getOutputStream(); outputStream.write(controlData); @@ -146,7 +145,7 @@ public class InBandBytestreamSessionTest { protocol.addResponse(resultIQ, incrementingSequence); protocol.addResponse(resultIQ, incrementingSequence); - byte[] controlData = new byte[dataSize * 3]; + byte[] controlData = new byte[blockSize * 3]; OutputStream outputStream = session.getOutputStream(); for (byte b : controlData) { @@ -174,11 +173,11 @@ public class InBandBytestreamSessionTest { protocol.addResponse(resultIQ, incrementingSequence); protocol.addResponse(resultIQ, incrementingSequence); - byte[] controlData = new byte[(dataSize * 3) - 2]; + byte[] controlData = new byte[(blockSize * 3) - 2]; OutputStream outputStream = session.getOutputStream(); int off = 0; - for (int i = 1; i+off <= controlData.length; i++) { + for (int i = 1; i <= 7; i++) { outputStream.write(controlData, off, i); off += i; } @@ -195,7 +194,7 @@ public class InBandBytestreamSessionTest { */ @Test public void shouldSendThirtyDataPackets() throws Exception { - byte[] controlData = new byte[dataSize * 3]; + byte[] controlData = new byte[blockSize * 3]; InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); @@ -223,7 +222,7 @@ public class InBandBytestreamSessionTest { */ @Test public void shouldSendNothingOnSuccessiveCallsToFlush() throws Exception { - byte[] controlData = new byte[dataSize * 3]; + byte[] controlData = new byte[blockSize * 3]; InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); @@ -254,7 +253,7 @@ public class InBandBytestreamSessionTest { public void shouldSendDataCorrectly() throws Exception { // create random data Random rand = new Random(); - final byte[] controlData = new byte[256 * dataSize]; + final byte[] controlData = new byte[256 * blockSize]; rand.nextBytes(controlData); // compares the data of each packet with the control data @@ -264,7 +263,7 @@ public class InBandBytestreamSessionTest { byte[] decodedData = request.getDataPacketExtension().getDecodedData(); int seq = (int) request.getDataPacketExtension().getSeq(); for (int i = 0; i < decodedData.length; i++) { - assertEquals(controlData[(seq * dataSize) + i], decodedData[i]); + assertEquals(controlData[(seq * blockSize) + i], decodedData[i]); } } @@ -272,7 +271,7 @@ public class InBandBytestreamSessionTest { // set acknowledgments for the data packets IQ resultIQ = IBBPacketUtils.createResultIQ(initiatorJID, targetJID); - for (int i = 0; i < controlData.length / dataSize; i++) { + for (int i = 0; i < controlData.length / blockSize; i++) { protocol.addResponse(resultIQ, incrementingSequence, dataVerification); } @@ -480,7 +479,7 @@ public class InBandBytestreamSessionTest { public void shouldReadAllReceivedData1() throws Exception { // create random data Random rand = new Random(); - byte[] controlData = new byte[3 * dataSize]; + byte[] controlData = new byte[3 * blockSize]; rand.nextBytes(controlData); IQ resultIQ = IBBPacketUtils.createResultIQ(initiatorJID, targetJID); @@ -491,24 +490,24 @@ public class InBandBytestreamSessionTest { InputStream inputStream = session.getInputStream(); PacketListener listener = Whitebox.getInternalState(inputStream, PacketListener.class); - // set data packet acknowledgement and notify listener - for (int i = 0; i < controlData.length / dataSize; i++) { + // set data packet acknowledgment and notify listener + for (int i = 0; i < controlData.length / blockSize; i++) { protocol.addResponse(resultIQ); - String base64Data = StringUtils.encodeBase64(controlData, i * dataSize, dataSize, + String base64Data = StringUtils.encodeBase64(controlData, i * blockSize, blockSize, false); DataPacketExtension dpe = new DataPacketExtension(sessionID, i, base64Data); Data data = new Data(dpe); listener.processPacket(data); } - byte[] bytes = new byte[3 * dataSize]; + byte[] bytes = new byte[3 * blockSize]; int read = 0; - read = inputStream.read(bytes, 0, dataSize); - assertEquals(dataSize, read); - read = inputStream.read(bytes, dataSize, dataSize); - assertEquals(dataSize, read); - read = inputStream.read(bytes, dataSize*2, dataSize); - assertEquals(dataSize, read); + read = inputStream.read(bytes, 0, blockSize); + assertEquals(blockSize, read); + read = inputStream.read(bytes, 10, blockSize); + assertEquals(blockSize, read); + read = inputStream.read(bytes, 20, blockSize); + assertEquals(blockSize, read); // verify data for (int i = 0; i < bytes.length; i++) { @@ -528,7 +527,7 @@ public class InBandBytestreamSessionTest { public void shouldReadAllReceivedData2() throws Exception { // create random data Random rand = new Random(); - byte[] controlData = new byte[3 * dataSize]; + byte[] controlData = new byte[3 * blockSize]; rand.nextBytes(controlData); IQ resultIQ = IBBPacketUtils.createResultIQ(initiatorJID, targetJID); @@ -540,9 +539,9 @@ public class InBandBytestreamSessionTest { PacketListener listener = Whitebox.getInternalState(inputStream, PacketListener.class); // set data packet acknowledgment and notify listener - for (int i = 0; i < controlData.length / dataSize; i++) { + for (int i = 0; i < controlData.length / blockSize; i++) { protocol.addResponse(resultIQ); - String base64Data = StringUtils.encodeBase64(controlData, i * dataSize, dataSize, + String base64Data = StringUtils.encodeBase64(controlData, i * blockSize, blockSize, false); DataPacketExtension dpe = new DataPacketExtension(sessionID, i, base64Data); Data data = new Data(dpe); @@ -550,7 +549,7 @@ public class InBandBytestreamSessionTest { } // read data - byte[] bytes = new byte[3 * dataSize]; + byte[] bytes = new byte[3 * blockSize]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) inputStream.read(); } diff --git a/test-unit/org/jivesoftware/smackx/forward/ForwardedTest.java b/test-unit/org/jivesoftware/smackx/forward/ForwardedTest.java new file mode 100644 index 000000000..7cea6539f --- /dev/null +++ b/test-unit/org/jivesoftware/smackx/forward/ForwardedTest.java @@ -0,0 +1,86 @@ +/** + * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smackx.forward; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.StringReader; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Properties; +import java.util.TimeZone; + +import org.jivesoftware.smack.packet.Packet; +import org.jivesoftware.smack.test.util.TestUtils; +import org.jivesoftware.smackx.packet.DelayInfo; +import org.jivesoftware.smackx.packet.DelayInformation; +import org.jivesoftware.smackx.forward.Forwarded; +import org.jivesoftware.smackx.forward.provider.ForwardedProvider; +import org.junit.Test; +import org.xmlpull.mxp1.MXParser; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import com.jamesmurty.utils.XMLBuilder; + +public class ForwardedTest { + + private static Properties outputProperties = new Properties(); + static { + outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes"); + } + + @Test + public void forwardedTest() throws Exception { + XmlPullParser parser; + String control; + Forwarded fwd; + + control = XMLBuilder.create("forwarded") + .a("xmlns", "urn:xmpp:forwarded:0") + .e("message") + .a("from", "romeo@montague.com") + .asString(outputProperties); + + parser = TestUtils.getParser(control, "forwarded"); + fwd = (Forwarded) new ForwardedProvider().parseExtension(parser); + + // no delay in packet + assertEquals(null, fwd.getDelayInfo()); + + // check message + assertEquals("romeo@montague.com", fwd.getForwardedPacket().getFrom()); + + // check end of tag + assertEquals(XmlPullParser.END_TAG, parser.getEventType()); + assertEquals("forwarded", parser.getName()); + + } + + @Test(expected=Exception.class) + public void forwardedEmptyTest() throws Exception { + XmlPullParser parser; + String control; + + control = XMLBuilder.create("forwarded") + .a("xmlns", "urn:xmpp:forwarded:0") + .asString(outputProperties); + + parser = TestUtils.getParser(control, "forwarded"); + new ForwardedProvider().parseExtension(parser); + } +} diff --git a/test-unit/org/jivesoftware/smackx/ping/PingTest.java b/test-unit/org/jivesoftware/smackx/ping/PingTest.java index c127f18dc..7058e89a1 100644 --- a/test-unit/org/jivesoftware/smackx/ping/PingTest.java +++ b/test-unit/org/jivesoftware/smackx/ping/PingTest.java @@ -15,19 +15,21 @@ */ package org.jivesoftware.smackx.ping; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import org.jivesoftware.smack.DummyConnection; -import org.jivesoftware.smack.TestUtils; import org.jivesoftware.smack.ThreadedDummyConnection; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.ping.packet.Ping; +import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smackx.packet.DiscoverInfo; import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; - public class PingTest { private DummyConnection dummyCon; private ThreadedDummyConnection threadedCon; diff --git a/test-unit/org/jivesoftware/smackx/provider/ProviderConfigTest.java b/test-unit/org/jivesoftware/smackx/provider/ProviderConfigTest.java new file mode 100644 index 000000000..473a1f19e --- /dev/null +++ b/test-unit/org/jivesoftware/smackx/provider/ProviderConfigTest.java @@ -0,0 +1,55 @@ +package org.jivesoftware.smackx.provider; + +import java.util.ArrayList; +import java.util.Collection; + +import junit.framework.Assert; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.provider.ExtensionProviderInfo; +import org.jivesoftware.smack.provider.IQProvider; +import org.jivesoftware.smack.provider.IQProviderInfo; +import org.jivesoftware.smack.provider.ProviderFileLoader; +import org.jivesoftware.smack.provider.ProviderLoader; +import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.smack.util.FileUtils; +import org.junit.Test; +import org.xmlpull.v1.XmlPullParser; + +public class ProviderConfigTest { + + @Test + public void addGenericLoaderProvider() { + ProviderManager.getInstance().addLoader(new ProviderLoader() { + + @Override + public Collection getIQProviderInfo() { + ArrayList l = new ArrayList(1); + l.add(new IQProviderInfo("provider", "test:provider", new TestIQProvider())); + return l; + } + + @Override + public Collection getExtensionProviderInfo() { + return null; + } + }); + + Assert.assertNotNull(ProviderManager.getInstance().getIQProvider("provider", "test:provider")); + } + + @Test + public void addClasspathFileLoaderProvider() throws Exception{ + ProviderManager.getInstance().addLoader(new ProviderFileLoader(FileUtils.getStreamForUrl("classpath:org/jivesoftware/smackx/provider/test.providers", null))); + Assert.assertNotNull(ProviderManager.getInstance().getIQProvider("provider", "test:file_provider")); + } + + public static class TestIQProvider implements IQProvider { + + @Override + public IQ parseIQ(XmlPullParser parser) throws Exception { + return null; + } + + } +} diff --git a/test-unit/org/jivesoftware/smackx/provider/test.providers b/test-unit/org/jivesoftware/smackx/provider/test.providers new file mode 100644 index 000000000..90bafc4f7 --- /dev/null +++ b/test-unit/org/jivesoftware/smackx/provider/test.providers @@ -0,0 +1,11 @@ + + + + + + provider + test:file_provider + org.jivesoftware.smackx.provider.ProviderConfigTest$TestIQProvider + + + diff --git a/test-unit/org/jivesoftware/smackx/pubsub/ConfigureFormTest.java b/test-unit/org/jivesoftware/smackx/pubsub/ConfigureFormTest.java index 784c56f39..68834d6b8 100644 --- a/test-unit/org/jivesoftware/smackx/pubsub/ConfigureFormTest.java +++ b/test-unit/org/jivesoftware/smackx/pubsub/ConfigureFormTest.java @@ -22,7 +22,7 @@ package org.jivesoftware.smackx.pubsub; import static org.junit.Assert.assertEquals; import org.jivesoftware.smack.SmackConfiguration; -import org.jivesoftware.smack.ThreadedDummyConnection; +import org.jivesoftware.smack.ThreadedDummyConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.PacketExtension; diff --git a/test-unit/org/jivesoftware/smackx/pubsub/ItemValidationTest.java b/test-unit/org/jivesoftware/smackx/pubsub/ItemValidationTest.java index eb967e5f7..b28b6b9ae 100644 --- a/test-unit/org/jivesoftware/smackx/pubsub/ItemValidationTest.java +++ b/test-unit/org/jivesoftware/smackx/pubsub/ItemValidationTest.java @@ -26,10 +26,10 @@ import static org.junit.Assert.assertTrue; import java.io.Reader; import java.io.StringReader; -import org.jivesoftware.smack.TestUtils; import org.jivesoftware.smack.ThreadedDummyConnection; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.PacketExtension; +import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace; import org.jivesoftware.smackx.pubsub.provider.ItemsProvider; diff --git a/test-unit/org/jivesoftware/smack/util/DNSUtilTest.java b/test/org/jivesoftware/smack/util/DNSUtilTest.java similarity index 100% rename from test-unit/org/jivesoftware/smack/util/DNSUtilTest.java rename to test/org/jivesoftware/smack/util/DNSUtilTest.java diff --git a/workgroup/resources/META-INF/workgroup.providers b/workgroup/resources/META-INF/workgroup.providers new file mode 100644 index 000000000..cc7085085 --- /dev/null +++ b/workgroup/resources/META-INF/workgroup.providers @@ -0,0 +1,214 @@ + + + + + + offer + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.OfferRequestProvider + + + + offer-revoke + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.OfferRevokeProvider + + + + agent-status-request + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.AgentStatusRequest$Provider + + + + transcripts + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.TranscriptsProvider + + + + transcript + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.TranscriptProvider + + + + workgroups + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.AgentWorkgroups$Provider + + + + agent-info + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.AgentInfo$Provider + + + + transcript-search + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.TranscriptSearch$Provider + + + + occupants-info + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.OccupantsInfo$Provider + + + + chat-settings + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.settings.ChatSettings$InternalProvider + + + + chat-notes + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.ext.notes.ChatNotes$Provider + + + + chat-sessions + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.ext.history.AgentChatHistory$InternalProvider + + + + offline-settings + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.settings.OfflineSettings$InternalProvider + + + + sound-settings + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.settings.SoundSettings$InternalProvider + + + + workgroup-properties + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.settings.WorkgroupProperties$InternalProvider + + + + + search-settings + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.settings.SearchSettings$InternalProvider + + + + workgroup-form + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.ext.forms.WorkgroupForm$InternalProvider + + + + macros + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.ext.macros.Macros$InternalProvider + + + + chat-metadata + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.ext.history.ChatMetadata$Provider + + + + generic-metadata + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.settings.GenericSettings$InternalProvider + + + + monitor + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.MonitorPacket$InternalProvider + + + + + queue-status + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.QueueUpdate$Provider + + + + workgroup + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.WorkgroupInformation$Provider + + + + metadata + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.MetaDataProvider + + + + session + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.SessionID$Provider + + + + user + http://jivesoftware.com/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.UserID$Provider + + + + agent-status + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.AgentStatus$Provider + + + + notify-queue-details + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.QueueDetails$Provider + + + + notify-queue + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.QueueOverview$Provider + + + + invite + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.RoomInvitation$Provider + + + + transfer + http://jabber.org/protocol/workgroup + org.jivesoftware.smackx.workgroup.packet.RoomTransfer$Provider + + + diff --git a/source/org/jivesoftware/smackx/workgroup/MetaData.java b/workgroup/source/org/jivesoftware/smackx/workgroup/MetaData.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/MetaData.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/MetaData.java diff --git a/source/org/jivesoftware/smackx/workgroup/QueueUser.java b/workgroup/source/org/jivesoftware/smackx/workgroup/QueueUser.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/QueueUser.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/QueueUser.java diff --git a/source/org/jivesoftware/smackx/workgroup/WorkgroupInvitation.java b/workgroup/source/org/jivesoftware/smackx/workgroup/WorkgroupInvitation.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/WorkgroupInvitation.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/WorkgroupInvitation.java diff --git a/source/org/jivesoftware/smackx/workgroup/WorkgroupInvitationListener.java b/workgroup/source/org/jivesoftware/smackx/workgroup/WorkgroupInvitationListener.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/WorkgroupInvitationListener.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/WorkgroupInvitationListener.java diff --git a/workgroup/source/org/jivesoftware/smackx/workgroup/WorkgroupProviderInitializer.java b/workgroup/source/org/jivesoftware/smackx/workgroup/WorkgroupProviderInitializer.java new file mode 100644 index 000000000..a198a32e6 --- /dev/null +++ b/workgroup/source/org/jivesoftware/smackx/workgroup/WorkgroupProviderInitializer.java @@ -0,0 +1,11 @@ +package org.jivesoftware.smackx.workgroup; + +import org.jivesoftware.smack.provider.UrlProviderFileInitializer; + +public class WorkgroupProviderInitializer extends UrlProviderFileInitializer { + + @Override + protected String getFilePath() { + return "classpath:META-INF/workgroup.providers"; + } +} diff --git a/source/org/jivesoftware/smackx/workgroup/agent/Agent.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/Agent.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/Agent.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/Agent.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java similarity index 96% rename from source/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java index 70c95ee2e..0dd74b16f 100644 --- a/source/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java +++ b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java @@ -37,6 +37,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.logging.Logger; /** * Manges information about the agents in a workgroup and their presence. @@ -45,7 +46,7 @@ import java.util.Set; * @see AgentSession#getAgentRoster() */ public class AgentRoster { - + private static Logger log = Logger.getLogger(AgentRoster.class.getName()); private static final int EVENT_AGENT_ADDED = 0; private static final int EVENT_AGENT_REMOVED = 1; private static final int EVENT_PRESENCE_CHANGED = 2; @@ -284,7 +285,7 @@ public class AgentRoster { String from = presence.getFrom(); if (from == null) { // TODO Check if we need to ignore these presences or this is a server bug? - System.out.println("Presence with no FROM: " + presence.toXML()); + log.warning("Presence with no FROM: " + presence.toXML()); return; } String key = getPresenceMapKey(from); diff --git a/source/org/jivesoftware/smackx/workgroup/agent/AgentRosterListener.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/AgentRosterListener.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/AgentRosterListener.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/AgentRosterListener.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/AgentSession.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/AgentSession.java similarity index 97% rename from source/org/jivesoftware/smackx/workgroup/agent/AgentSession.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/AgentSession.java index 46d19d0d5..16499f1bb 100644 --- a/source/org/jivesoftware/smackx/workgroup/agent/AgentSession.java +++ b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/AgentSession.java @@ -40,6 +40,8 @@ import org.jivesoftware.smackx.ReportedData; import org.jivesoftware.smackx.packet.MUCUser; import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; /** * This class embodies the agent's active presence within a given workgroup. The application @@ -53,7 +55,8 @@ import java.util.*; * @author Derek DeMoro */ public class AgentSession { - + private static Logger log = Logger.getLogger(AgentSession.class.getName()); + private Connection connection; private String workgroupJID; @@ -118,7 +121,7 @@ public class AgentSession { handlePacket(packet); } catch (Exception e) { - e.printStackTrace(); + log.log(Level.SEVERE, "Error processing packet", e); } } }; diff --git a/source/org/jivesoftware/smackx/workgroup/agent/InvitationRequest.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/InvitationRequest.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/InvitationRequest.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/InvitationRequest.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/Offer.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/Offer.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/Offer.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/Offer.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/OfferConfirmation.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/OfferConfirmation.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/OfferConfirmation.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/OfferConfirmation.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/OfferConfirmationListener.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/OfferConfirmationListener.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/OfferConfirmationListener.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/OfferConfirmationListener.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/OfferContent.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/OfferContent.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/OfferContent.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/OfferContent.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/OfferListener.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/OfferListener.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/OfferListener.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/OfferListener.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/QueueUsersListener.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/QueueUsersListener.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/QueueUsersListener.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/QueueUsersListener.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/RevokedOffer.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/RevokedOffer.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/RevokedOffer.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/RevokedOffer.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/TranscriptManager.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/TranscriptManager.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/TranscriptManager.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/TranscriptManager.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/TranscriptSearchManager.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/TranscriptSearchManager.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/TranscriptSearchManager.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/TranscriptSearchManager.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/TransferRequest.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/TransferRequest.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/TransferRequest.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/TransferRequest.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/UserRequest.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/UserRequest.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/UserRequest.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/UserRequest.java diff --git a/source/org/jivesoftware/smackx/workgroup/agent/WorkgroupQueue.java b/workgroup/source/org/jivesoftware/smackx/workgroup/agent/WorkgroupQueue.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/agent/WorkgroupQueue.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/agent/WorkgroupQueue.java diff --git a/source/org/jivesoftware/smackx/workgroup/ext/forms/WorkgroupForm.java b/workgroup/source/org/jivesoftware/smackx/workgroup/ext/forms/WorkgroupForm.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/ext/forms/WorkgroupForm.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/ext/forms/WorkgroupForm.java diff --git a/source/org/jivesoftware/smackx/workgroup/ext/history/AgentChatHistory.java b/workgroup/source/org/jivesoftware/smackx/workgroup/ext/history/AgentChatHistory.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/ext/history/AgentChatHistory.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/ext/history/AgentChatHistory.java diff --git a/source/org/jivesoftware/smackx/workgroup/ext/history/AgentChatSession.java b/workgroup/source/org/jivesoftware/smackx/workgroup/ext/history/AgentChatSession.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/ext/history/AgentChatSession.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/ext/history/AgentChatSession.java diff --git a/source/org/jivesoftware/smackx/workgroup/ext/history/ChatMetadata.java b/workgroup/source/org/jivesoftware/smackx/workgroup/ext/history/ChatMetadata.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/ext/history/ChatMetadata.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/ext/history/ChatMetadata.java diff --git a/source/org/jivesoftware/smackx/workgroup/ext/macros/Macro.java b/workgroup/source/org/jivesoftware/smackx/workgroup/ext/macros/Macro.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/ext/macros/Macro.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/ext/macros/Macro.java diff --git a/source/org/jivesoftware/smackx/workgroup/ext/macros/MacroGroup.java b/workgroup/source/org/jivesoftware/smackx/workgroup/ext/macros/MacroGroup.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/ext/macros/MacroGroup.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/ext/macros/MacroGroup.java diff --git a/source/org/jivesoftware/smackx/workgroup/ext/macros/Macros.java b/workgroup/source/org/jivesoftware/smackx/workgroup/ext/macros/Macros.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/ext/macros/Macros.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/ext/macros/Macros.java diff --git a/source/org/jivesoftware/smackx/workgroup/ext/notes/ChatNotes.java b/workgroup/source/org/jivesoftware/smackx/workgroup/ext/notes/ChatNotes.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/ext/notes/ChatNotes.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/ext/notes/ChatNotes.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/AgentInfo.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/AgentInfo.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/AgentInfo.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/AgentInfo.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/AgentStatus.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/AgentStatus.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/AgentStatus.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/AgentStatus.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/AgentStatusRequest.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/AgentStatusRequest.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/AgentStatusRequest.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/AgentStatusRequest.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/AgentWorkgroups.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/AgentWorkgroups.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/AgentWorkgroups.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/AgentWorkgroups.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/DepartQueuePacket.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/DepartQueuePacket.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/DepartQueuePacket.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/DepartQueuePacket.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/MetaDataProvider.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/MetaDataProvider.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/MetaDataProvider.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/MetaDataProvider.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/MonitorPacket.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/MonitorPacket.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/MonitorPacket.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/MonitorPacket.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/OccupantsInfo.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/OccupantsInfo.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/OccupantsInfo.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/OccupantsInfo.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/OfferRequestProvider.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/OfferRequestProvider.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/OfferRequestProvider.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/OfferRequestProvider.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/OfferRevokeProvider.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/OfferRevokeProvider.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/OfferRevokeProvider.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/OfferRevokeProvider.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java similarity index 94% rename from source/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java index 86b3673e8..230ceba6a 100644 --- a/source/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java +++ b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java @@ -29,13 +29,15 @@ import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import java.util.logging.Logger; /** * Queue details packet extension, which contains details about the users * currently in a queue. */ public class QueueDetails implements PacketExtension { - + private static Logger log = Logger.getLogger(QueueDetails.class.getName()); + /** * Element name of the packet extension. */ @@ -178,7 +180,7 @@ public class QueueDetails implements PacketExtension { } else if( parser.getName().equals( "waitTime" ) ) { Date wait = dateFormat.parse(parser.nextText()); - System.out.println( wait ); + log.fine(wait.toString()); } eventType = parser.next(); diff --git a/source/org/jivesoftware/smackx/workgroup/packet/QueueOverview.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/QueueOverview.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/QueueOverview.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/QueueOverview.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/QueueUpdate.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/QueueUpdate.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/QueueUpdate.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/QueueUpdate.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/RoomInvitation.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/RoomInvitation.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/RoomInvitation.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/RoomInvitation.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/RoomTransfer.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/RoomTransfer.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/RoomTransfer.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/RoomTransfer.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/SessionID.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/SessionID.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/SessionID.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/SessionID.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/Transcript.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/Transcript.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/Transcript.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/Transcript.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/TranscriptProvider.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/TranscriptProvider.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/TranscriptProvider.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/TranscriptProvider.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/TranscriptSearch.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/TranscriptSearch.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/TranscriptSearch.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/TranscriptSearch.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/Transcripts.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/Transcripts.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/Transcripts.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/Transcripts.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/TranscriptsProvider.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/TranscriptsProvider.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/TranscriptsProvider.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/TranscriptsProvider.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/UserID.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/UserID.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/UserID.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/UserID.java diff --git a/source/org/jivesoftware/smackx/workgroup/packet/WorkgroupInformation.java b/workgroup/source/org/jivesoftware/smackx/workgroup/packet/WorkgroupInformation.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/packet/WorkgroupInformation.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/packet/WorkgroupInformation.java diff --git a/source/org/jivesoftware/smackx/workgroup/settings/ChatSetting.java b/workgroup/source/org/jivesoftware/smackx/workgroup/settings/ChatSetting.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/settings/ChatSetting.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/settings/ChatSetting.java diff --git a/source/org/jivesoftware/smackx/workgroup/settings/ChatSettings.java b/workgroup/source/org/jivesoftware/smackx/workgroup/settings/ChatSettings.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/settings/ChatSettings.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/settings/ChatSettings.java diff --git a/source/org/jivesoftware/smackx/workgroup/settings/GenericSettings.java b/workgroup/source/org/jivesoftware/smackx/workgroup/settings/GenericSettings.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/settings/GenericSettings.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/settings/GenericSettings.java diff --git a/source/org/jivesoftware/smackx/workgroup/settings/OfflineSettings.java b/workgroup/source/org/jivesoftware/smackx/workgroup/settings/OfflineSettings.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/settings/OfflineSettings.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/settings/OfflineSettings.java diff --git a/source/org/jivesoftware/smackx/workgroup/settings/SearchSettings.java b/workgroup/source/org/jivesoftware/smackx/workgroup/settings/SearchSettings.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/settings/SearchSettings.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/settings/SearchSettings.java diff --git a/source/org/jivesoftware/smackx/workgroup/settings/SoundSettings.java b/workgroup/source/org/jivesoftware/smackx/workgroup/settings/SoundSettings.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/settings/SoundSettings.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/settings/SoundSettings.java diff --git a/source/org/jivesoftware/smackx/workgroup/settings/WorkgroupProperties.java b/workgroup/source/org/jivesoftware/smackx/workgroup/settings/WorkgroupProperties.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/settings/WorkgroupProperties.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/settings/WorkgroupProperties.java diff --git a/source/org/jivesoftware/smackx/workgroup/user/QueueListener.java b/workgroup/source/org/jivesoftware/smackx/workgroup/user/QueueListener.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/user/QueueListener.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/user/QueueListener.java diff --git a/source/org/jivesoftware/smackx/workgroup/user/Workgroup.java b/workgroup/source/org/jivesoftware/smackx/workgroup/user/Workgroup.java similarity index 96% rename from source/org/jivesoftware/smackx/workgroup/user/Workgroup.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/user/Workgroup.java index 237337f00..d19c6d669 100644 --- a/source/org/jivesoftware/smackx/workgroup/user/Workgroup.java +++ b/workgroup/source/org/jivesoftware/smackx/workgroup/user/Workgroup.java @@ -849,20 +849,4 @@ public class Workgroup { } return Form.getFormFrom(response); } - - /* - public static void main(String args[]) throws Exception { - Connection con = new XMPPConnection("anteros"); - con.connect(); - con.loginAnonymously(); - - Workgroup workgroup = new Workgroup("demo@workgroup.anteros", con); - WorkgroupProperties props = workgroup.getWorkgroupProperties("derek@anteros.com"); - - System.out.print(props); - con.disconnect(); - } - */ - - } \ No newline at end of file diff --git a/source/org/jivesoftware/smackx/workgroup/util/ListenerEventDispatcher.java b/workgroup/source/org/jivesoftware/smackx/workgroup/util/ListenerEventDispatcher.java similarity index 91% rename from source/org/jivesoftware/smackx/workgroup/util/ListenerEventDispatcher.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/util/ListenerEventDispatcher.java index 533b9a132..1c7f5beec 100644 --- a/source/org/jivesoftware/smackx/workgroup/util/ListenerEventDispatcher.java +++ b/workgroup/source/org/jivesoftware/smackx/workgroup/util/ListenerEventDispatcher.java @@ -19,6 +19,8 @@ package org.jivesoftware.smackx.workgroup.util; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.ListIterator; +import java.util.logging.Level; +import java.util.logging.Logger; /** * This class is a very flexible event dispatcher which implements Runnable so that it can @@ -32,8 +34,8 @@ import java.util.ListIterator; * * @author loki der quaeler */ -public class ListenerEventDispatcher - implements Runnable { +public class ListenerEventDispatcher implements Runnable { + private static Logger log = Logger.getLogger(ListenerEventDispatcher.class.getName()); protected transient ArrayList triplets; @@ -93,9 +95,7 @@ public class ListenerEventDispatcher try { tc.getListenerMethod().invoke(tc.getListenerInstance(), tc.getMethodArguments()); } catch (Exception e) { - System.err.println("Exception dispatching an event: " + e); - - e.printStackTrace(); + log.log(Level.SEVERE, "Exception dispatching an event", e); } } diff --git a/source/org/jivesoftware/smackx/workgroup/util/MetaDataUtils.java b/workgroup/source/org/jivesoftware/smackx/workgroup/util/MetaDataUtils.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/util/MetaDataUtils.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/util/MetaDataUtils.java diff --git a/source/org/jivesoftware/smackx/workgroup/util/ModelUtil.java b/workgroup/source/org/jivesoftware/smackx/workgroup/util/ModelUtil.java similarity index 100% rename from source/org/jivesoftware/smackx/workgroup/util/ModelUtil.java rename to workgroup/source/org/jivesoftware/smackx/workgroup/util/ModelUtil.java