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    
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: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
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    }