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 018package org.fusesource.hawtdispatch.transport; 019 020import org.fusesource.hawtdispatch.DispatchQueue; 021import org.fusesource.hawtdispatch.Task; 022import org.fusesource.hawtdispatch.TaskWrapper; 023 024import 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 */ 033public 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}