1f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com/** 2f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * $RCSfile$ 3f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * $Revision$ 4f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * $Date$ 5f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * 6f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * Copyright 2005-2007 Jive Software. 7f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * 8f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 9f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * you may not use this file except in compliance with the License. 10f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * You may obtain a copy of the License at 11f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * 12f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * http://www.apache.org/licenses/LICENSE-2.0 13f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * 14f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * Unless required by applicable law or agreed to in writing, software 15f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * distributed under the License is distributed on an "AS IS" BASIS, 16f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * See the License for the specific language governing permissions and 18f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * limitations under the License. 19f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com */ 20f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 21f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.compackage org.jivesoftware.smackx.commands; 22f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 23f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.comimport org.jivesoftware.smack.PacketCollector; 24f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.comimport org.jivesoftware.smack.SmackConfiguration; 25f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.comimport org.jivesoftware.smack.Connection; 26f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.comimport org.jivesoftware.smack.XMPPException; 27f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.comimport org.jivesoftware.smack.filter.PacketIDFilter; 28f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.comimport org.jivesoftware.smack.packet.IQ; 29f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.comimport org.jivesoftware.smack.packet.Packet; 30f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.comimport org.jivesoftware.smackx.Form; 31f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.comimport org.jivesoftware.smackx.packet.AdHocCommandData; 32f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 33f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com/** 34f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * Represents a command that is in a remote location. Invoking one of the 35f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * {@link AdHocCommand.Action#execute execute}, {@link AdHocCommand.Action#next next}, 36f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * {@link AdHocCommand.Action#prev prev}, {@link AdHocCommand.Action#cancel cancel} or 37f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * {@link AdHocCommand.Action#complete complete} actions results in executing that 38f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * action in the remote location. In response to that action the internal state 39f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * of the this command instance will change. For example, if the command is a 40f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * single stage command, then invoking the execute action will execute this 41f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * action in the remote location. After that the local instance will have a 42f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * state of "completed" and a form or notes that applies. 43f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * 44f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * @author Gabriel Guardincerri 45f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * 46f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com */ 47f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.compublic class RemoteCommand extends AdHocCommand { 48f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 49f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com /** 50f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * The connection that is used to execute this command 51f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com */ 52f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com private Connection connection; 53f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 54f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com /** 55f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * The full JID of the command host 56f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com */ 57f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com private String jid; 58f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 59f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com /** 60f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * The session ID of this execution. 61f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com */ 62f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com private String sessionID; 63f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 64f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 65f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com /** 66f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * The number of milliseconds to wait for a response from the server 67f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * The default value is the default packet reply timeout (5000 ms). 68f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com */ 69f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com private long packetReplyTimeout; 70f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 71f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com /** 72f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * Creates a new RemoteCommand that uses an specific connection to execute a 73f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * command identified by <code>node</code> in the host identified by 74f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * <code>jid</code> 75f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * 76f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * @param connection the connection to use for the execution. 77f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * @param node the identifier of the command. 78f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * @param jid the JID of the host. 79f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com */ 80f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com protected RemoteCommand(Connection connection, String node, String jid) { 81f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com super(); 82f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com this.connection = connection; 83f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com this.jid = jid; 84f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com this.setNode(node); 85f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com this.packetReplyTimeout = SmackConfiguration.getPacketReplyTimeout(); 86f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com } 87f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 88f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com @Override 89f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com public void cancel() throws XMPPException { 90f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com executeAction(Action.cancel, packetReplyTimeout); 91f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com } 92f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 93f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com @Override 94f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com public void complete(Form form) throws XMPPException { 95f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com executeAction(Action.complete, form, packetReplyTimeout); 96f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com } 97f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 98f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com @Override 99f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com public void execute() throws XMPPException { 100f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com executeAction(Action.execute, packetReplyTimeout); 101f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com } 102f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 103f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com /** 104f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * Executes the default action of the command with the information provided 105f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * in the Form. This form must be the anwser form of the previous stage. If 106f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * there is a problem executing the command it throws an XMPPException. 107f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * 108f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * @param form the form anwser of the previous stage. 109f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com * @throws XMPPException if an error occurs. 110f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com */ 111f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com public void execute(Form form) throws XMPPException { 112f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com executeAction(Action.execute, form, packetReplyTimeout); 113f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com } 114f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 115f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com @Override 116f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com public void next(Form form) throws XMPPException { 117f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com executeAction(Action.next, form, packetReplyTimeout); 118f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com } 119f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 120f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com @Override 121f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com public void prev() throws XMPPException { 122f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com executeAction(Action.prev, packetReplyTimeout); 123f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com } 124f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com 125f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com private void executeAction(Action action, long packetReplyTimeout) throws XMPPException { 126f3b789787b93945c974e2cc517b7dc352b28354etanjent@gmail.com executeAction(action, null, packetReplyTimeout); 127f67ce942f6432ceb7ced0c3d12370b6376c05c09tanjent@gmail.com } 128 129 /** 130 * Executes the <code>action</codo> with the <code>form</code>. 131 * The action could be any of the available actions. The form must 132 * be the anwser of the previous stage. It can be <tt>null</tt> if it is the first stage. 133 * 134 * @param action the action to execute. 135 * @param form the form with the information. 136 * @param timeout the amount of time to wait for a reply. 137 * @throws XMPPException if there is a problem executing the command. 138 */ 139 private void executeAction(Action action, Form form, long timeout) throws XMPPException { 140 // TODO: Check that all the required fields of the form were filled, if 141 // TODO: not throw the corresponding exeption. This will make a faster response, 142 // TODO: since the request is stoped before it's sent. 143 AdHocCommandData data = new AdHocCommandData(); 144 data.setType(IQ.Type.SET); 145 data.setTo(getOwnerJID()); 146 data.setNode(getNode()); 147 data.setSessionID(sessionID); 148 data.setAction(action); 149 150 if (form != null) { 151 data.setForm(form.getDataFormToSend()); 152 } 153 154 PacketCollector collector = connection.createPacketCollector( 155 new PacketIDFilter(data.getPacketID())); 156 157 connection.sendPacket(data); 158 159 Packet response = collector.nextResult(timeout); 160 161 // Cancel the collector. 162 collector.cancel(); 163 if (response == null) { 164 throw new XMPPException("No response from server on status set."); 165 } 166 if (response.getError() != null) { 167 throw new XMPPException(response.getError()); 168 } 169 170 AdHocCommandData responseData = (AdHocCommandData) response; 171 this.sessionID = responseData.getSessionID(); 172 super.setData(responseData); 173 } 174 175 @Override 176 public String getOwnerJID() { 177 return jid; 178 } 179 180 /** 181 * Returns the number of milliseconds to wait for a respone. The 182 * {@link SmackConfiguration#getPacketReplyTimeout default} value 183 * should be adjusted for commands that can take a long time to execute. 184 * 185 * @return the number of milliseconds to wait for responses. 186 */ 187 public long getPacketReplyTimeout() { 188 return packetReplyTimeout; 189 } 190 191 /** 192 * Returns the number of milliseconds to wait for a respone. The 193 * {@link SmackConfiguration#getPacketReplyTimeout default} value 194 * should be adjusted for commands that can take a long time to execute. 195 * 196 * @param packetReplyTimeout the number of milliseconds to wait for responses. 197 */ 198 public void setPacketReplyTimeout(long packetReplyTimeout) { 199 this.packetReplyTimeout = packetReplyTimeout; 200 } 201}