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 final public void start(final Runnable onCompleted) {
083 start(new TaskWrapper(onCompleted));
084 }
085
086 final public void start(final Task onCompleted) {
087 getDispatchQueue().execute(new Task() {
088 public void run() {
089 if (_serviceState == CREATED ||
090 _serviceState == STOPPED) {
091 final STARTING state = new STARTING();
092 state.add(onCompleted);
093 _serviceState = state;
094 _start(new Task() {
095 public void run() {
096 _serviceState = STARTED;
097 state.done();
098 }
099 });
100 } else if (_serviceState instanceof STARTING) {
101 ((STARTING) _serviceState).add(onCompleted);
102 } else if (_serviceState == STARTED) {
103 if (onCompleted != null) {
104 onCompleted.run();
105 }
106 } else {
107 if (onCompleted != null) {
108 onCompleted.run();
109 }
110 error("start should not be called from state: " + _serviceState);
111 }
112 }
113 });
114 }
115
116 final public void stop(final Runnable onCompleted) {
117 stop(new TaskWrapper(onCompleted));
118 }
119
120 final public void stop(final Task onCompleted) {
121 getDispatchQueue().execute(new Task() {
122 public void run() {
123 if (_serviceState == STARTED) {
124 final STOPPING state = new STOPPING();
125 state.add(onCompleted);
126 _serviceState = state;
127 _stop(new Task() {
128 public void run() {
129 _serviceState = STOPPED;
130 state.done();
131 }
132 });
133 } else if (_serviceState instanceof STOPPING) {
134 ((STOPPING) _serviceState).add(onCompleted);
135 } else if (_serviceState == STOPPED) {
136 if (onCompleted != null) {
137 onCompleted.run();
138 }
139 } else {
140 if (onCompleted != null) {
141 onCompleted.run();
142 }
143 error("stop should not be called from state: " + _serviceState);
144 }
145 }
146 });
147 }
148
149 private void error(String msg) {
150 try {
151 throw new AssertionError(msg);
152 } catch (Exception e) {
153 e.printStackTrace();
154 }
155 }
156
157 protected State getServiceState() {
158 return _serviceState;
159 }
160
161 abstract protected DispatchQueue getDispatchQueue();
162
163 abstract protected void _start(Task onCompleted);
164
165 abstract protected void _stop(Task onCompleted);
166
167 }