001 /**
002 *
003 * Copyright 2003-2004 The Apache Software Foundation
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.apache.geronimo.gbean.runtime;
019
020 import org.apache.geronimo.gbean.AbstractName;
021 import org.apache.geronimo.gbean.GReferenceInfo;
022 import org.apache.geronimo.gbean.InvalidConfigurationException;
023 import org.apache.geronimo.gbean.ReferencePatterns;
024 import org.apache.geronimo.gbean.AbstractNameQuery;
025 import org.apache.geronimo.kernel.Kernel;
026 import org.apache.geronimo.kernel.lifecycle.LifecycleAdapter;
027 import org.apache.geronimo.kernel.lifecycle.LifecycleListener;
028
029 import java.util.Collections;
030 import java.util.HashSet;
031 import java.util.Iterator;
032 import java.util.Set;
033
034 /**
035 * @version $Rev:386515 $ $Date: 2006-03-18 16:52:38 -0800 (Sat, 18 Mar 2006) $
036 */
037 public class GBeanCollectionReference extends AbstractGBeanReference {
038 /**
039 * is this reference online
040 */
041 private boolean isOnline = false;
042
043 /**
044 * The target objectName patterns to watch for a connection.
045 */
046 private Set patterns = Collections.EMPTY_SET;
047
048 /**
049 * Current set of targets
050 */
051 private final Set targets = new HashSet();
052
053 /**
054 * Our listener for lifecycle events
055 */
056 private final LifecycleListener listener;
057
058 public GBeanCollectionReference(GBeanInstance gbeanInstance, GReferenceInfo referenceInfo, Kernel kernel, ReferencePatterns referencePatterns) throws InvalidConfigurationException {
059 super(gbeanInstance, referenceInfo, kernel, hasTargets(referencePatterns));
060 listener = createLifecycleListener();
061 if (referencePatterns != null) {
062 setReferencePatterns(referencePatterns);
063 }
064 }
065
066 private static boolean hasTargets(ReferencePatterns referencePatterns) {
067 if (referencePatterns == null) {
068 return false;
069 }
070 if (referencePatterns.isResolved()) {
071 return true;
072 }
073 return !referencePatterns.getPatterns().isEmpty();
074 }
075
076 public synchronized boolean start() {
077 // We only need to start if there are patterns and we don't already have a proxy
078 if (!patterns.isEmpty() && getProxy() == null) {
079 // add a dependency on our target and create the proxy
080 setProxy(new ProxyCollection(getName(), getReferenceType(), getTargets(), getKernel()));
081 }
082 return true;
083 }
084
085 public synchronized void stop() {
086 ProxyCollection proxy = (ProxyCollection) getProxy();
087 if (proxy != null) {
088 proxy.destroy();
089 setProxy(null);
090 }
091 }
092
093 protected synchronized void targetAdded(AbstractName target) {
094 ProxyCollection proxy = (ProxyCollection) getProxy();
095 if (proxy != null) {
096 proxy.addTarget(target);
097 }
098 }
099
100 protected synchronized void targetRemoved(AbstractName target) {
101 ProxyCollection proxy = (ProxyCollection) getProxy();
102 if (proxy != null) {
103 proxy.removeTarget(target);
104 }
105 }
106
107 protected LifecycleListener createLifecycleListener() {
108 return new LifecycleAdapter() {
109 public void running(AbstractName abstractName) {
110 addTarget(abstractName);
111 }
112
113 public void stopping(AbstractName abstractName) {
114 removeTarget(abstractName);
115 }
116
117 public void stopped(AbstractName abstractName) {
118 removeTarget(abstractName);
119 }
120
121 public void failed(AbstractName abstractName) {
122 removeTarget(abstractName);
123 }
124
125 public void unloaded(AbstractName abstractName) {
126 removeTarget(abstractName);
127 }
128 };
129 }
130
131 public final synchronized Set getPatterns() {
132 return patterns;
133 }
134
135 public final synchronized void setReferencePatterns(ReferencePatterns referencePatterns) {
136 if (isOnline) {
137 throw new IllegalStateException("Pattern set can not be modified while online");
138 }
139 if (referencePatterns.isResolved()) {
140 this.patterns = Collections.unmodifiableSet(Collections.singleton(new AbstractNameQuery(referencePatterns.getAbstractName())));
141 } else {
142 this.patterns = Collections.unmodifiableSet(referencePatterns.getPatterns());
143 }
144 }
145
146 public final synchronized void online() {
147 Set gbeans = getKernel().listGBeans(patterns);
148 for (Iterator objectNameIterator = gbeans.iterator(); objectNameIterator.hasNext();) {
149 AbstractName target = (AbstractName) objectNameIterator.next();
150 if (!targets.contains(target)) {
151
152 // if the bean is running add it to the runningTargets list
153 if (isRunning(getKernel(), target)) {
154 targets.add(target);
155 }
156 }
157 }
158
159 getKernel().getLifecycleMonitor().addLifecycleListener(listener, patterns);
160 isOnline = true;
161 }
162
163 public final synchronized void offline() {
164 // make sure we are stoped
165 stop();
166
167 getKernel().getLifecycleMonitor().removeLifecycleListener(listener);
168
169 targets.clear();
170 isOnline = false;
171 }
172
173 protected final Set getTargets() {
174 return targets;
175 }
176
177 protected final void addTarget(AbstractName abstractName) {
178 if (!targets.contains(abstractName)) {
179 targets.add(abstractName);
180 targetAdded(abstractName);
181 }
182 }
183
184 protected final void removeTarget(AbstractName abstractName) {
185 boolean wasTarget = targets.remove(abstractName);
186 if (wasTarget) {
187 targetRemoved(abstractName);
188 }
189 }
190
191 }