1 /*------------------------------------------------------------------------------
2 Name: Client.java
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 ------------------------------------------------------------------------------*/
6
7 package org.xmlBlaster.test.util;
8
9 import java.util.ArrayList;
10 import java.util.logging.Level;
11 import java.util.logging.Logger;
12
13 import org.xmlBlaster.client.I_Callback;
14 import org.xmlBlaster.client.I_XmlBlasterAccess;
15 import org.xmlBlaster.client.key.EraseKey;
16 import org.xmlBlaster.client.key.PublishKey;
17 import org.xmlBlaster.client.key.SubscribeKey;
18 import org.xmlBlaster.client.key.UpdateKey;
19 import org.xmlBlaster.client.protocol.socket.SocketCallbackImpl;
20 import org.xmlBlaster.client.qos.ConnectQos;
21 import org.xmlBlaster.client.qos.DisconnectQos;
22 import org.xmlBlaster.client.qos.EraseQos;
23 import org.xmlBlaster.client.qos.PublishQos;
24 import org.xmlBlaster.client.qos.SubscribeQos;
25 import org.xmlBlaster.client.qos.UpdateQos;
26 import org.xmlBlaster.util.Global;
27 import org.xmlBlaster.util.MsgUnit;
28 import org.xmlBlaster.util.SessionName;
29 import org.xmlBlaster.util.XmlBlasterException;
30 import org.xmlBlaster.util.def.ErrorCode;
31 import org.xmlBlaster.util.qos.TopicProperty;
32
33 public class Client implements I_Callback {
34
35 public enum Shutdown {
36 LEAVE_SERVER,
37 LOGOUT,
38 KEEP_LOGGED_IN
39 }
40
41 private String ME = "Client-";
42 private Global global;
43 private static Logger log = Logger.getLogger(Client.class.getName());
44 private I_XmlBlasterAccess accessor;
45 private String name;
46 private String publishOid;
47 private String subscribeOid;
48 private boolean consumable;
49 private ArrayList responses; // object to notify about updates
50 private XmlBlasterException updateException;
51
52 /**
53 * A helper client to be used when testing
54 * @param global
55 * @param name the name to be given to this instance
56 * @param responses the ArrayList object to which to add an entry (the name) when an update
57 * happens. You can pass 'null' here and nobody will be notified.
58 */
59 public Client(Global global, String name, ArrayList responses) {
60 this.global = global.getClone(null);
61
62 this.accessor = this.global.getXmlBlasterAccess();
63 this.name = name;
64 this.ME += this.name;
65 this.responses = responses;
66 if (log.isLoggable(Level.FINER)) log.finer("constructor");
67 }
68
69 /**
70 * Initializes this client which either can be a publisher, a subscriber or both depending
71 * on the parameters passed here.
72 * @param publishOid The oid to which to publish messages. If you pass 'null', then no message
73 * will be published by this instance.
74 * @param subscribeOid the oid to which to subscribe. If you pass null here no
75 * subscription will be node.
76 * @param consumable if this flag is set to true, then the publishing oid will be
77 * consumable, otherwise it is a normal (non consumable) topic.
78 * @param session the session of this instance as an integer (either positive or negative).
79 * @throws XmlBlasterException
80 */
81 public void init(String publishOid, String subscribeOid, boolean consumable, int session) throws XmlBlasterException {
82 if (log.isLoggable(Level.FINER)) log.finer("init");
83 this.consumable = consumable;
84 ConnectQos connectQos = new ConnectQos(this.global, name, "secret");
85 if (session > 0) {
86 SessionName sessionName = new SessionName(this.global, name + "/" + session);
87 connectQos.setSessionName(sessionName);
88 }
89 this.accessor.connect(connectQos, this);
90 this.publishOid = publishOid;
91 this.subscribeOid = subscribeOid;
92 if (this.subscribeOid != null) {
93 SubscribeQos subQos = new SubscribeQos(this.global);
94 this.accessor.subscribe(new SubscribeKey(this.global, this.subscribeOid), subQos);
95 }
96 }
97
98 /**
99 * Publishes one entry on the oid specified by the init method. If you passed
100 * null there, then you will get an exceptio here. This client just sends strings
101 * @param content the content of the message to send (a string).
102 * @throws XmlBlasterException
103 */
104 public void publish(String content) throws XmlBlasterException {
105 if (log.isLoggable(Level.FINER)) log.finer("publish");
106 if (this.publishOid == null)
107 throw new XmlBlasterException(this.global, ErrorCode.USER_CLIENTCODE, ME, "no oid configured for publishing");
108 if (content == null)
109 throw new XmlBlasterException(this.global, ErrorCode.USER_CLIENTCODE, ME, "no content passed");
110
111 PublishQos pubQos = new PublishQos(this.global);
112 TopicProperty topicProp = new TopicProperty(this.global);
113 topicProp.setMsgDistributor("ConsumableQueue,1.0");
114 if (this.consumable) pubQos.setTopicProperty(topicProp);
115 MsgUnit msgUnit = new MsgUnit(new PublishKey(this.global, this.publishOid), content, pubQos);
116 this.accessor.publish(msgUnit);
117 }
118
119 /**
120 * Disconnect the client from xmlBlaster with an optional previous deletion of the publishing topic.
121 * @param doEraseTopic if true, the topic on which this client publishes is erased. If this
122 * client is not a publisher, then erase will not be done.
123 * @throws XmlBlasterException
124 */
125 public void shutdown(boolean doEraseTopic) throws XmlBlasterException {
126 if (log.isLoggable(Level.FINER)) log.finer("shutdown");
127 if (this.publishOid != null && doEraseTopic) {
128 this.accessor.erase(new EraseKey(this.global, this.publishOid), new EraseQos(this.global));
129 }
130 this.accessor.disconnect(new DisconnectQos(this.global));
131 }
132
133 /**
134 * Sets an exception to be thrown the next time an update event comes. After
135 * that it is reset to null.
136 * @param ex
137 */
138 public void setUpdateException(XmlBlasterException ex) {
139 this.updateException = ex;
140 }
141
142 /**
143 * Enforced by I_Callback. If you passed a responses array list, then it will notify the
144 * thread waiting for it (and will add an entry with this istance's name).
145 * If updateException is not null, then an exception is thrown here and
146 * updateException is reset to null.
147 * @param cbSessionId
148 * @param updateKey
149 * @param content
150 * @param updateQos
151 * @return
152 * @throws XmlBlasterException
153 */
154 public String update(String cbSessionId, UpdateKey updateKey, byte[] content, UpdateQos updateQos)
155 throws XmlBlasterException {
156 if (log.isLoggable(Level.FINER)) log.finer("update '" + cbSessionId + "' content='" + new String(content) + "'");
157
158 if (this.responses != null) {
159 synchronized(responses) {
160 try {
161 this.responses.add(this.name);
162 XmlBlasterException ex = this.updateException;
163 this.updateException = null;
164 if (ex != null) throw ex;
165 }
166 finally {
167 this.responses.notify();
168 }
169 }
170 }
171 else {
172 XmlBlasterException ex = this.updateException;
173 this.updateException = null;
174 if (ex != null) throw ex;
175 }
176
177 return "OK";
178 }
179
180 public static boolean isSeparateCallbackServer(Global glob) {
181 return !isSocket(glob);
182 // TODO: Check if XMLRPC is in tunneling mode
183 }
184
185 public static boolean isSocket(Global glob) {
186 String driverType = glob.getProperty().get("client.protocol", (String)null);
187 if (driverType == null)
188 driverType = glob.getProperty().get("protocol", (String)null);
189 if (driverType == null)
190 return true; // SOCKET is default
191 if (driverType.equalsIgnoreCase("SOCKET"))
192 return true;
193 String plugin = glob.getProperty().get("ClientProtocolPlugin["+driverType+"][1.0]", "");
194 if (plugin.equals("org.xmlBlaster.client.protocol.socket.SocketConnection"))
195 return true;
196 return false;
197 }
198
199 public static boolean isSocket(I_XmlBlasterAccess conn) {
200 boolean isSocket = (conn.getCbServer() instanceof SocketCallbackImpl);
201 return isSocket;
202 }
203
204 /**
205 * Returns true if it shot down, false if it did a leave Server.
206 * @param conn
207 * @return
208 */
209 public static boolean shutdownCb(I_XmlBlasterAccess conn, Shutdown whatToDo) throws XmlBlasterException {
210 boolean isSocket = (conn.getCbServer() instanceof SocketCallbackImpl);
211 if (isSocket) {
212 conn.getCbServer().shutdown();
213 // xmlBlaster destroys our first session:
214 if (whatToDo.equals(Shutdown.LEAVE_SERVER))
215 conn.leaveServer(null);
216 else if (whatToDo.equals(Shutdown.LOGOUT))
217 conn.disconnect(null);
218 else if (whatToDo.equals(Shutdown.KEEP_LOGGED_IN)) {
219 log.info("Leave server of first client by keeping logged in.");
220 }
221 log.info("Leave server of first client.");
222 return false;
223 }
224 else { // "IOR"
225 conn.getCbServer().shutdown();
226 return true;
227 }
228
229
230 }
231
232 }
syntax highlighted by Code2HTML, v. 0.9.1