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.geronimo.kernel.config;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.Collections;
022    import java.util.Iterator;
023    import java.util.List;
024    
025    import org.apache.geronimo.gbean.AbstractName;
026    import org.apache.geronimo.gbean.AbstractNameQuery;
027    import org.apache.geronimo.gbean.GBeanData;
028    import org.apache.geronimo.gbean.GBeanInfo;
029    import org.apache.geronimo.gbean.GBeanInfoBuilder;
030    import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
031    import org.apache.geronimo.kernel.GBeanNotFoundException;
032    import org.apache.geronimo.kernel.Kernel;
033    import org.apache.geronimo.kernel.management.State;
034    import org.apache.geronimo.kernel.repository.Artifact;
035    import org.apache.geronimo.kernel.repository.ArtifactManager;
036    import org.apache.geronimo.kernel.repository.ArtifactResolver;
037    
038    /**
039     * Standard implementation of an editable ConfigurationManager.
040     *
041     * @version $Rev:386276 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
042     */
043    public class EditableKernelConfigurationManager extends KernelConfigurationManager implements EditableConfigurationManager {
044        private final AbstractNameQuery defaultStoreNameQuery;
045    
046        public EditableKernelConfigurationManager(Kernel kernel,
047                AbstractNameQuery defaultStoreNameQuery,
048                Collection stores,
049                ManageableAttributeStore attributeStore,
050                PersistentConfigurationList configurationList,
051                ArtifactManager artifactManager,
052                ArtifactResolver artifactResolver,
053                Collection repositories,
054                Collection watchers,
055                ClassLoader classLoader) {
056            super(kernel,
057                stores,
058                attributeStore,
059                configurationList,
060                artifactManager,
061                artifactResolver,
062                repositories,
063                watchers,
064                classLoader);
065            this.defaultStoreNameQuery = defaultStoreNameQuery;
066        }
067    
068        @Override
069        protected List getStoreList() {
070            if (null == defaultStoreNameQuery) {
071                return super.getStoreList();
072            }
073            
074            List<ConfigurationStore> storeList = new ArrayList<ConfigurationStore>();
075            for (Iterator iterator = stores.iterator(); iterator.hasNext();) {
076                ConfigurationStore configurationStore = (ConfigurationStore) iterator.next();
077                if (defaultStoreNameQuery.matches(configurationStore.getAbstractName(), Collections.EMPTY_SET)) {
078                    storeList.add(0, configurationStore);
079                } else {
080                    storeList.add(configurationStore);
081                }
082            }
083            return storeList;
084        }
085        
086        public void addGBeanToConfiguration(Artifact configurationId, GBeanData gbean, boolean start) throws InvalidConfigException {
087            Configuration configuration = getConfiguration(configurationId);
088    
089            try {
090                // add the gbean to the configuration
091                configuration.addGBean(gbean);
092            } catch (GBeanAlreadyExistsException e) {
093                throw new InvalidConfigException("Cound not add GBean " + gbean.getAbstractName() + " to configuration " + configurationId, e);
094            }
095    
096            addGBeanToConfiguration(configuration, gbean, start);
097        }
098    
099        public void addGBeanToConfiguration(Artifact configurationId, String name, GBeanData gbean, boolean start) throws InvalidConfigException {
100            Configuration configuration = getConfiguration(configurationId);
101    
102            try {
103                // add the gbean to the configuration
104                configuration.addGBean(name, gbean);
105            } catch (GBeanAlreadyExistsException e) {
106                throw new InvalidConfigException("Cound not add GBean " + gbean.getAbstractName() + " to configuration " + configurationId, e);
107            }
108    
109            addGBeanToConfiguration(configuration, gbean, start);
110        }
111    
112        private void addGBeanToConfiguration(Configuration configuration, GBeanData gbean, boolean start) throws InvalidConfigException {
113            ClassLoader configurationClassLoader = configuration.getConfigurationClassLoader();
114            ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
115            try {
116                Thread.currentThread().setContextClassLoader(configurationClassLoader);
117    
118                log.trace("Registering GBean " + gbean.getAbstractName());
119    
120    
121                // preprocess the gbean data before loading it into the kernel
122                ConfigurationUtil.preprocessGBeanData(configuration.getAbstractName(), configuration, gbean);
123    
124                // register the bean with the kernel
125                kernel.loadGBean(gbean, configurationClassLoader);
126    
127                // start the configuration
128                if (start) {
129                    try {
130                        kernel.startRecursiveGBean(gbean.getAbstractName());
131                    } catch (GBeanNotFoundException e) {
132                        throw new InvalidConfigException("How could we not find a GBean that we just loaded ('" + gbean.getAbstractName() + "')?", e);
133                    }
134                }
135    
136            } catch(Exception e) {
137                // clean up failed gbean
138                try {
139                    configuration.removeGBean(gbean.getAbstractName());
140                } catch (GBeanNotFoundException e1) {
141                    // this is good
142                }
143                try {
144                    kernel.stopGBean(gbean.getAbstractName());
145                } catch (GBeanNotFoundException e1) {
146                    // this is good
147                }
148                try {
149                    kernel.unloadGBean(gbean.getAbstractName());
150                } catch (GBeanNotFoundException e1) {
151                    // this is good
152                }
153    
154                if (e instanceof InvalidConfigException) {
155                    throw (InvalidConfigException) e;
156                }
157                throw new InvalidConfigException("Cound not add GBean " + gbean.getAbstractName() + " to configuration " + configuration.getId(), e);
158            } finally {
159                Thread.currentThread().setContextClassLoader(oldCl);
160            }
161    
162            if (attributeStore != null) {
163                attributeStore.addGBean(configuration.getId(), gbean, configurationClassLoader);
164            }
165        }
166    
167        public void removeGBeanFromConfiguration(Artifact configurationId, AbstractName gbeanName) throws GBeanNotFoundException, InvalidConfigException {
168            Configuration configuration = getConfiguration(configurationId);
169            if (!configuration.containsGBean(gbeanName)) {
170                throw new GBeanNotFoundException(gbeanName);
171            }
172            configuration.removeGBean(gbeanName);
173    
174            try {
175                if (kernel.getGBeanState(gbeanName) == State.RUNNING_INDEX) {
176                    kernel.stopGBean(gbeanName);
177                }
178                kernel.unloadGBean(gbeanName);
179            } catch (GBeanNotFoundException e) {
180                // Bean is no longer loaded
181            }
182    
183            // Make sure it's not loaded next time the configuration is loaded
184            if (attributeStore != null) {
185                attributeStore.setShouldLoad(configurationId, gbeanName, false);
186            }
187        }
188    
189        public static final GBeanInfo GBEAN_INFO;
190    
191        public static final String GBEAN_ATTR_DEFAULT_STORE_NAME_QUERY = "defaultStoreNameQuery";
192    
193        static {
194            GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(EditableKernelConfigurationManager.class, KernelConfigurationManager.GBEAN_INFO, "ConfigurationManager");
195            
196            infoFactory.addAttribute(GBEAN_ATTR_DEFAULT_STORE_NAME_QUERY, AbstractNameQuery.class, true);
197            
198            infoFactory.addInterface(EditableConfigurationManager.class);
199            
200            infoFactory.setConstructor(new String[] { "kernel",
201                GBEAN_ATTR_DEFAULT_STORE_NAME_QUERY,
202                "Stores",
203                "AttributeStore",
204                "PersistentConfigurationList",
205                "ArtifactManager",
206                "ArtifactResolver",
207                "Repositories",
208                "Watchers",
209                "classLoader" });
210    
211            GBEAN_INFO = infoFactory.getBeanInfo();
212        }
213    
214        public static GBeanInfo getGBeanInfo() {
215            return GBEAN_INFO;
216        }
217    }