001    /**
002     * Copyright 2007 Mike Kroutikov.
003     *
004     * This program is free software; you can redistribute it and/or modify
005     *   it under the terms of the Lesser GNU General Public License as 
006     *   published by the Free Software Foundation; either version 3 of
007     *   the License, or (at your option) any later version.
008     *
009     *   This program is distributed in the hope that it will be useful,
010     *   but WITHOUT ANY WARRANTY; without even the implied warranty of
011     *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012     *   Lesser GNU General Public License for more details.
013     *
014     *   You should have received a copy of the Lesser GNU General Public License
015     *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
016     */
017    
018    package org.otfeed.support;
019    
020    import java.util.LinkedList;
021    import java.util.List;
022    
023    import org.otfeed.IConnection;
024    import org.otfeed.IConnectionFactory;
025    import org.otfeed.IRequest;
026    import org.otfeed.event.IConnectionStateListener;
027    import org.otfeed.protocol.ICommand;
028    
029    /**
030     * Class that runs a list of commands, then waits 
031     * for the completion. Sometimes useful in scripts.
032     */
033    public class CommandRunner {
034    
035            /**
036             * Creates new CommandRunner.
037             */
038            public CommandRunner() { }
039    
040            /**
041             * Creates new CommandRunner from a given connection 
042             * factory, with the given list of commands.
043             * 
044             * @param cf connection factory.
045             * @param commands list of commands.
046             */
047            public CommandRunner(IConnectionFactory cf, List<ICommand> commands) {
048                    setConnectionFactory(cf);
049                    setCommandList(commands);
050            }
051            
052            private IConnectionFactory connectionFactory;
053            
054            /**
055             * Connection factory to use.
056             * 
057             * @return connection factory.
058             */
059            public IConnectionFactory getConnectionFactory() {
060                    return connectionFactory;
061            }
062            
063            /**
064             * Sets the connection factory.
065             * 
066             * @param val connection factory.
067             */
068            public void setConnectionFactory(IConnectionFactory val) {
069                    connectionFactory = val;
070            }
071            
072            private List<ICommand> commandList = new LinkedList<ICommand>();
073            
074            /**
075             * List of commands to execute.
076             * If empty, the runner will just do connect, login, and disconnect.
077             * 
078             * @return lsit of commands.
079             */
080            public List<ICommand> getCommandList() {
081                    return commandList;
082            }
083            
084            /**
085             * Sets list of commands.
086             * 
087             * @param val list of commands.
088             */
089            public void setCommandList(List<ICommand> val) {
090                    commandList = val;
091            }
092            
093            private IConnectionStateListener connectionStateListener
094                    = new SimpleConnectionStateListener();
095    
096            /**
097             * Listener that watches connection-level events.
098             * Defaul is an instance of {@link SimpleConnectionStateListener},
099             * which will print the events to the System.err.
100             * 
101             * @return connection state listener. 
102             */
103            public IConnectionStateListener getConnectionStateListener() {
104                    return connectionStateListener;
105            }
106    
107            /**
108             * Sets connection state listener.
109             * 
110             * @param val connection state listener.
111             */
112            public void setConnectionStateListener(IConnectionStateListener val) {
113                    connectionStateListener = val;
114            }
115            
116            /**
117             * Main method: connects to the server and executes all
118             * commands. Blocks untill the processing is finished.
119             *
120             * @throws Exception is something is not 
121             * configured correctly, or something goes extremely
122             * wrong at the runtime.
123             */
124            public void runCommands() throws Exception {
125                    runCommands(Integer.MAX_VALUE);
126            }
127            
128            /**
129             * Main method: connects to the server and executes all
130             * commands. Blocks for the given timeout value
131             * waiting for the requests to complete. If timeout expires,
132             * the connection is shutdown, all pending requests are 
133             * aborted with error.
134             * 
135             * @param timeout how long to wait for the request to complete (in milliseconds).
136             * @throws Exception if something is not 
137             *    configured correctly, or something goes extremely
138             *    wrong at the runtime.
139             */
140            public void runCommands(long timeout) throws Exception {
141                    if(connectionFactory == null) {
142                            throw new NullPointerException("connectionFactory property must be set");
143                    }
144                    
145                    if(commandList == null) {
146                            throw new NullPointerException("commandList property must be set");
147                    }
148    
149                    long target = System.currentTimeMillis() + timeout;
150    
151                    IConnection connection = connectionFactory.connect(null, connectionStateListener);
152    
153                    try {
154                            List<IRequest> requestList = new LinkedList<IRequest>();
155                            for(ICommand command : commandList) {
156                                    IRequest r = connection.prepareRequest(command);
157                                    r.submit();
158                                    requestList.add(r);
159                            }
160    
161                            for(IRequest r : requestList) {
162                                    long delay = target - System.currentTimeMillis();
163                                    if(delay > 0) {
164                                            r.waitForCompletion(delay);
165                                    }
166                            }
167                    } finally {
168                            connection.shutdown();
169                            connection.waitForCompletion();
170                    }
171            }
172    }