001    /**
002     * Copyright (C) 2012 FuseSource, Inc.
003     * http://fusesource.com
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *    http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.fusesource.hawtdispatch.transport;
019    
020    import org.fusesource.hawtdispatch.DispatchQueue;
021    import org.fusesource.hawtdispatch.Task;
022    import org.fusesource.hawtdispatch.TaskWrapper;
023    
024    import java.util.LinkedList;
025    
026    /**
027     * <p>
028     * The BaseService provides helpers for dealing async service state.
029     * </p>
030     *
031     * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
032     */
033    public abstract class ServiceBase {
034    
035        public static class State {
036            public String toString() {
037                return getClass().getSimpleName();
038            }
039            public boolean isStarted() {
040                return false;
041            }
042            public boolean isStarting() {
043                return false;
044            }
045        }
046    
047        static class CallbackSupport extends State {
048            LinkedList<Task> callbacks = new LinkedList<Task>();
049    
050            void add(Task r) {
051                if (r != null) {
052                    callbacks.add(r);
053                }
054            }
055    
056            void done() {
057                for (Task callback : callbacks) {
058                    callback.run();
059                }
060            }
061        }
062    
063        public static final State CREATED = new State();
064        public static class STARTING extends CallbackSupport {
065            public boolean isStarting() {
066                return true;
067            }
068        }
069        public static final State STARTED = new State() {
070            public boolean isStarted() {
071                return true;
072            }
073        };
074        public static class STOPPING extends CallbackSupport {
075        }
076    
077        public static final State STOPPED = new State();
078    
079    
080        protected State _serviceState = CREATED;
081    
082        @Deprecated
083        final public void start(final Runnable onCompleted) {
084            start(new TaskWrapper(onCompleted));
085        }
086    
087        final public void start(final Task onCompleted) {
088            getDispatchQueue().execute(new Task() {
089                public void run() {
090                    if (_serviceState == CREATED ||
091                            _serviceState == STOPPED) {
092                        final STARTING state = new STARTING();
093                        state.add(onCompleted);
094                        _serviceState = state;
095                        _start(new Task() {
096                            public void run() {
097                                _serviceState = STARTED;
098                                state.done();
099                            }
100                        });
101                    } else if (_serviceState instanceof STARTING) {
102                        ((STARTING) _serviceState).add(onCompleted);
103                    } else if (_serviceState == STARTED) {
104                        if (onCompleted != null) {
105                            onCompleted.run();
106                        }
107                    } else {
108                        if (onCompleted != null) {
109                            onCompleted.run();
110                        }
111                        error("start should not be called from state: " + _serviceState);
112                    }
113                }
114            });
115        }
116    
117        @Deprecated
118        final public void stop(final Runnable onCompleted) {
119            stop(new TaskWrapper(onCompleted));
120        }
121    
122        final public void stop(final Task onCompleted) {
123            getDispatchQueue().execute(new Task() {
124                public void run() {
125                    if (_serviceState == STARTED) {
126                        final STOPPING state = new STOPPING();
127                        state.add(onCompleted);
128                        _serviceState = state;
129                        _stop(new Task() {
130                            public void run() {
131                                _serviceState = STOPPED;
132                                state.done();
133                            }
134                        });
135                    } else if (_serviceState instanceof STOPPING) {
136                        ((STOPPING) _serviceState).add(onCompleted);
137                    } else if (_serviceState == STOPPED) {
138                        if (onCompleted != null) {
139                            onCompleted.run();
140                        }
141                    } else {
142                        if (onCompleted != null) {
143                            onCompleted.run();
144                        }
145                        error("stop should not be called from state: " + _serviceState);
146                    }
147                }
148            });
149        }
150    
151        private void error(String msg) {
152            try {
153                throw new AssertionError(msg);
154            } catch (Exception e) {
155                e.printStackTrace();
156            }
157        }
158    
159        protected State getServiceState() {
160            return _serviceState;
161        }
162    
163        abstract protected DispatchQueue getDispatchQueue();
164    
165        abstract protected void _start(Task onCompleted);
166    
167        abstract protected void _stop(Task onCompleted);
168    
169    }