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