summaryrefslogtreecommitdiffstats
blob: c5c9999c0c1dc6705cb4c25fa3600a3d8458ac87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
 * Copyright (c) 2010-2014, Isode Limited, London, England.
 * All rights reserved.
 */
/*
 * Copyright (c) 2010, Remko Tronçon.
 * All rights reserved.
 */

package com.isode.stroke.queries;

import com.isode.stroke.elements.ErrorPayload;
import com.isode.stroke.elements.IQ;
import com.isode.stroke.elements.IQ.Type;
import com.isode.stroke.elements.Payload;
import com.isode.stroke.elements.RawXMLPayload;
import com.isode.stroke.jid.JID;
import java.util.logging.Logger;

/**
 * Base class for IQ requests.
 */
public abstract class Request implements IQHandler {
    protected Type type_;
    protected IQRouter router_;
    protected JID receiver_ = new JID();
	protected JID sender_ = new JID();
    private boolean sent_;
    private Payload payload_;
    private String id_ = "";
	private Logger logger_ = Logger.getLogger(this.getClass().getName());

	/**
	 * Constructs a request of a certain type to a specific receiver.
	 */
    public Request(IQ.Type type, JID receiver, IQRouter router) {
        this(type, null, receiver, null, router);
    }

	/**
	 * Constructs a request of a certain type to a specific receiver, and attaches the given
	 * payload.
	 */
    public Request(IQ.Type type, JID receiver, Payload payload, IQRouter router) {
        this(type, null, receiver, payload, router);
    }

	/**
	 * Constructs a request of a certain type to a specific receiver from a specific sender.
	 */
    public Request(IQ.Type type, JID sender, JID receiver, IQRouter router) {
    	this(type, sender, receiver, null, router);
    }

	/**
	 * Constructs a request of a certain type to a specific receiver from a specific sender, and attaches the given
	 * payload.
	 */
    public Request(IQ.Type type, JID sender, JID receiver, Payload payload, IQRouter router) {
        type_ = type;
        router_ = router;
        receiver_ = receiver;
        payload_ = payload;
        sender_ = sender;
        sent_ = false;
    }

    public String send() {
        assert payload_ != null;
		assert !sent_;
		sent_ = true;

		IQ iq = new IQ(type_);
		iq.setTo(receiver_);
		iq.setFrom(sender_);
		iq.addPayload(payload_);
		id_ = router_.getNewIQID();
		iq.setID(id_);

		router_.addHandler(this);

		router_.sendIQ(iq);
    	return id_;
    }

    protected void setPayload(Payload payload) {
        payload_ = payload;
    }

    protected Payload getPayload() {
        return payload_;
    }

    protected abstract void handleResponse(Payload payload, ErrorPayload error);

    public boolean handleIQ(IQ iq) {
        boolean handled = false;
        if (iq.getType() == IQ.Type.Result || iq.getType() == IQ.Type.Error) {
	        if (sent_ && iq.getID().equals(id_)) {
		    	if (isCorrectSender(iq.getFrom())) {
			
					if (iq.getType().equals(IQ.Type.Result)) {
						Payload payload = iq.getPayload(payload_);
						if (payload == null && (payload_ instanceof RawXMLPayload) && !iq.getPayloads().isEmpty()) {
							payload = iq.getPayloads().firstElement();
						}
			    		handleResponse(payload, null);
					} else {
			    		ErrorPayload errorPayload = iq.getPayload(new ErrorPayload());
			    		if (errorPayload != null) {
							handleResponse(null, errorPayload);
			    		} else {
							handleResponse(null, new ErrorPayload(ErrorPayload.Condition.UndefinedCondition));
			    		}
					}
					router_.removeHandler(this);
					handled = true;
		    	}
			}
		}
        return handled;
    }

    private boolean isCorrectSender(final JID jid) {
    	if (router_.isAccountJID(receiver_)) {
			if (jid.isValid() && jid.compare(router_.getJID(), JID.CompareType.WithResource) == 0) {
				// This unspecified behavior seems to happen in ejabberd versions (e.g. 2.0.5)
				logger_.warning("Server responded to an account request with a full JID, which is not allowed. Handling it anyway.");
				return true;
			}
			return router_.isAccountJID(jid);
		}
		else {
			return jid.compare(receiver_, JID.CompareType.WithResource) == 0;
		}
    }
	       
	public JID getReceiver() {
		return receiver_;
	}

	/**
	 * Returns the ID of this request.
	 * This will only be set after send() is called.
	 */
	public String getID() {
		return id_;
	}
}