001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. 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 package org.apache.xbean.kernel; 018 019 /** 020 * This condition that requires another service be in the RUNNING state to be satisfied. 021 * 022 * @author Dain Sundstrom 023 * @version $Id$ 024 * @since 2.0 025 */ 026 public class RunningServiceCondition implements ServiceCondition { 027 private final ServiceName dependency; 028 private final boolean ownedRelationship; 029 private final boolean stopOnServiceShutdown; 030 private final DependencyServiceMonitor serviceMonitor = new DependencyServiceMonitor(); 031 032 private ServiceConditionContext context; 033 private boolean satisfied = true; 034 private StoppedServiceCondition stoppedServiceCondition; 035 036 /** 037 * Creates a condition that requires the specified service be in the RUNNING state to be satisfied. 038 * 039 * @param dependency the service that must be running 040 * @param ownedRelationship if true the condition will register the relationship 041 * @param stopOnServiceShutdown if the our service should be stopped when the specified service shutsdown 042 */ 043 public RunningServiceCondition(ServiceName dependency, boolean ownedRelationship, boolean stopOnServiceShutdown) { 044 if (dependency == null) throw new NullPointerException("dependency is null"); 045 this.dependency = dependency; 046 this.ownedRelationship = ownedRelationship; 047 this.stopOnServiceShutdown = stopOnServiceShutdown; 048 } 049 050 /** 051 * {@inheritDoc} 052 */ 053 public synchronized void initialize(ServiceConditionContext context) { 054 if (context == null) throw new NullPointerException("context is null"); 055 056 // if we have no been destroyed, destroy not 057 if (this.context != null) { 058 destroy(); 059 } 060 061 this.context = context; 062 063 satisfied = false; 064 context.getKernel().addServiceMonitor(serviceMonitor, dependency); 065 if (ownedRelationship) { 066 // todo register owned relationship 067 } 068 069 if (stopOnServiceShutdown) { 070 stoppedServiceCondition = new StoppedServiceCondition(context.getServiceName()); 071 } 072 } 073 074 /** 075 * {@inheritDoc} 076 */ 077 public synchronized boolean isSatisfied() { 078 if (context == null) { 079 // we are not initialized so default to true 080 return true; 081 } 082 083 if (!satisfied) { 084 try { 085 // grab a synchronized lock on the service factory to assure that the state doesn't change while 086 // adding the dependency.... the kernel will grab the same lock when getting the stop dependencies 087 ServiceFactory serviceFactory = context.getKernel().getServiceFactory(dependency); 088 synchronized (serviceFactory) { 089 if (context.getKernel().getService(dependency) == ServiceState.RUNNING) { 090 if (stopOnServiceShutdown) { 091 serviceFactory.addStopCondition(stoppedServiceCondition); 092 } 093 satisfied = true; 094 context.getKernel().removeServiceMonitor(serviceMonitor); 095 } 096 } 097 } catch (ServiceNotFoundException ignored) { 098 // service hasn't registered yet 099 } 100 } 101 return satisfied; 102 } 103 104 /** 105 * {@inheritDoc} 106 */ 107 public synchronized void destroy() { 108 if (context == null) { 109 // we are already destroyed 110 return; 111 } 112 113 context.getKernel().removeServiceMonitor(serviceMonitor); 114 context = null; 115 satisfied = true; 116 if (ownedRelationship) { 117 // todo unregister owned relationship 118 } 119 if (stopOnServiceShutdown) { 120 stoppedServiceCondition.destroy(); 121 stoppedServiceCondition = null; 122 } 123 } 124 125 private class DependencyServiceMonitor extends NullServiceMonitor { 126 public void serviceRunning(ServiceEvent serviceEvent) { 127 synchronized (RunningServiceCondition.this) { 128 if (context != null) { 129 // we aren't running anymore 130 return; 131 } 132 133 if (!satisfied) { 134 return; 135 } 136 137 if (isSatisfied()) { 138 context.setSatisfied(); 139 } 140 } 141 } 142 } 143 }