1 /* 2 * Copyright 2017, Google Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package com.google.api.core; 31 32 import com.google.common.collect.ImmutableMap; 33 import com.google.common.util.concurrent.AbstractService; 34 import com.google.common.util.concurrent.Service; 35 import java.util.concurrent.Executor; 36 import java.util.concurrent.TimeUnit; 37 import java.util.concurrent.TimeoutException; 38 39 /** 40 * Base class for {@link ApiService}. Similar to Guava's {@code AbstractService} but redeclared so 41 * that Guava can be shaded. 42 */ 43 public abstract class AbstractApiService implements ApiService { 44 private static final ImmutableMap<Service.State, ApiService.State> GUAVA_TO_API_SERVICE_STATE = 45 ImmutableMap.<Service.State, ApiService.State>builder() 46 .put(Service.State.FAILED, ApiService.State.FAILED) 47 .put(Service.State.NEW, ApiService.State.NEW) 48 .put(Service.State.RUNNING, ApiService.State.RUNNING) 49 .put(Service.State.STARTING, ApiService.State.STARTING) 50 .put(Service.State.STOPPING, ApiService.State.STOPPING) 51 .put(Service.State.TERMINATED, ApiService.State.TERMINATED) 52 .build(); 53 54 private final InnerService impl = new InnerService(); 55 AbstractApiService()56 protected AbstractApiService() {} 57 doStart()58 protected abstract void doStart(); 59 doStop()60 protected abstract void doStop(); 61 62 @Override addListener(final ApiService.Listener listener, Executor executor)63 public void addListener(final ApiService.Listener listener, Executor executor) { 64 impl.addListener( 65 new Service.Listener() { 66 @Override 67 public void failed(Service.State from, Throwable failure) { 68 listener.failed(GUAVA_TO_API_SERVICE_STATE.get(from), failure); 69 } 70 71 @Override 72 public void running() { 73 listener.running(); 74 } 75 76 @Override 77 public void starting() { 78 listener.starting(); 79 } 80 81 @Override 82 public void stopping(Service.State from) { 83 listener.stopping(GUAVA_TO_API_SERVICE_STATE.get(from)); 84 } 85 86 @Override 87 public void terminated(Service.State from) { 88 listener.terminated(GUAVA_TO_API_SERVICE_STATE.get(from)); 89 } 90 }, 91 executor); 92 } 93 awaitRunning()94 public void awaitRunning() { 95 impl.awaitRunning(); 96 } 97 awaitRunning(long timeout, TimeUnit unit)98 public void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException { 99 impl.awaitRunning(timeout, unit); 100 } 101 awaitTerminated()102 public void awaitTerminated() { 103 impl.awaitTerminated(); 104 } 105 awaitTerminated(long timeout, TimeUnit unit)106 public void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException { 107 impl.awaitTerminated(timeout, unit); 108 } 109 failureCause()110 public Throwable failureCause() { 111 return impl.failureCause(); 112 } 113 isRunning()114 public boolean isRunning() { 115 return impl.isRunning(); 116 } 117 startAsync()118 public ApiService startAsync() { 119 impl.startAsync(); 120 return this; 121 } 122 state()123 public State state() { 124 return GUAVA_TO_API_SERVICE_STATE.get(impl.state()); 125 } 126 stopAsync()127 public ApiService stopAsync() { 128 impl.stopAsync(); 129 return this; 130 } 131 notifyStarted()132 protected void notifyStarted() { 133 impl.innerNotifyStarted(); 134 } 135 notifyStopped()136 protected void notifyStopped() { 137 impl.innerNotifyStopped(); 138 } 139 notifyFailed(Throwable cause)140 protected void notifyFailed(Throwable cause) { 141 impl.innerNotifyFailed(cause); 142 } 143 144 private class InnerService extends AbstractService { 145 @Override doStart()146 protected void doStart() { 147 AbstractApiService.this.doStart(); 148 } 149 150 @Override doStop()151 protected void doStop() { 152 AbstractApiService.this.doStop(); 153 } 154 innerNotifyStarted()155 private void innerNotifyStarted() { 156 notifyStarted(); 157 } 158 innerNotifyStopped()159 private void innerNotifyStopped() { 160 notifyStopped(); 161 } 162 innerNotifyFailed(Throwable cause)163 private void innerNotifyFailed(Throwable cause) { 164 notifyFailed(cause); 165 } 166 } 167 } 168