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.system.main;
019    
020    import java.io.File;
021    import java.io.IOException;
022    import java.util.ArrayList;
023    import java.util.LinkedHashSet;
024    import java.util.List;
025    import java.util.Set;
026    
027    import org.apache.commons.logging.Log;
028    import org.apache.commons.logging.LogFactory;
029    import org.apache.geronimo.cli.daemon.DaemonCLParser;
030    import org.apache.geronimo.common.GeronimoEnvironment;
031    import org.apache.geronimo.gbean.AbstractName;
032    import org.apache.geronimo.gbean.AbstractNameQuery;
033    import org.apache.geronimo.gbean.GBeanInfo;
034    import org.apache.geronimo.gbean.GBeanInfoBuilder;
035    import org.apache.geronimo.kernel.Kernel;
036    import org.apache.geronimo.kernel.config.ConfigurationManager;
037    import org.apache.geronimo.kernel.config.ConfigurationUtil;
038    import org.apache.geronimo.kernel.config.DebugLoggingLifecycleMonitor;
039    import org.apache.geronimo.kernel.config.InvalidConfigException;
040    import org.apache.geronimo.kernel.config.LifecycleMonitor;
041    import org.apache.geronimo.kernel.config.PersistentConfigurationList;
042    import org.apache.geronimo.kernel.repository.Artifact;
043    import org.apache.geronimo.kernel.util.Main;
044    import org.apache.geronimo.system.serverinfo.DirectoryUtils;
045    
046    
047    /**
048     * @version $Rev:385659 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
049     */
050    public class EmbeddedDaemon implements Main {
051        private static final Log log = LogFactory.getLog(EmbeddedDaemon.class);
052    
053        protected final Kernel kernel;
054        private StartupMonitor monitor;
055        private LifecycleMonitor lifecycleMonitor;
056        private List<Artifact> configs = new ArrayList<Artifact>();
057    
058        public EmbeddedDaemon(Kernel kernel) {
059            this.kernel = kernel;
060        }
061    
062        public int execute(Object opaque) {
063            if (!(opaque instanceof DaemonCLParser)) {
064                throw new IllegalArgumentException("Argument type is [" + opaque.getClass() + "]; expected [" + DaemonCLParser.class + "]");
065            }
066            DaemonCLParser parser = (DaemonCLParser) opaque;
067            initializeMonitor(parser);
068            initializeOverride(parser);
069    
070            long start = System.currentTimeMillis();
071    
072            System.out.println("Booting Geronimo Kernel (in Java " + System.getProperty("java.version") + ")...");
073            System.out.flush();
074    
075            // Perform initialization tasks common with the various Geronimo environments
076            GeronimoEnvironment.init();
077    
078            monitor.systemStarting(start);
079            return doStartup();
080        }
081    
082        protected void initializeOverride(DaemonCLParser parser) {
083            String[] override = parser.getOverride();
084            if (null != override) {
085                for (String anOverride : override) {
086                    configs.add(Artifact.create(anOverride));
087                }
088            }
089        }
090    
091        protected void initializeMonitor(DaemonCLParser parser) {
092            if (parser.isVerboseInfo() || parser.isVerboseDebug() || parser.isVerboseTrace() || parser.isNoProgress()) {
093                monitor = new SilentStartupMonitor();
094            } else {
095                if (parser.isLongProgress()) {
096                    monitor = new LongStartupMonitor();
097                } else {
098                    monitor = new SimpleProgressBarStartupMonitor();
099                }
100            }
101            lifecycleMonitor = new DebugLoggingLifecycleMonitor(log);
102        }
103    
104        protected int doStartup() {
105            try {
106                // Check that the tmpdir exists - if not give friendly msg and exit
107                // since we allow it to be configured in geronimo.bat and geronimo.sh
108                // (since 1.0 release) the same way Tomcat allows it to be configured.
109                String tmpDir = System.getProperty("java.io.tmpdir");
110                if (tmpDir == null || (!(new File(tmpDir)).exists()) || (!(new File(tmpDir)).isDirectory())) {
111                    System.err.println("The java.io.tmpdir system property specifies a non-existent directory: " + tmpDir);
112                    return 1;
113                }
114    
115                // Determine the geronimo installation directory
116                File geronimoInstallDirectory = DirectoryUtils.getGeronimoInstallDirectory();
117                if (geronimoInstallDirectory == null) {
118                    System.err.println("Could not determine geronimo installation directory");
119                    return 1;
120                }
121    
122                int exitCode = initializeKernel();
123                if (0 != exitCode) {
124                    return exitCode;
125                }
126    
127                monitor.systemStarted(kernel);
128    
129                AbstractNameQuery query = new AbstractNameQuery(PersistentConfigurationList.class.getName());
130    
131                if (configs.isEmpty()) {
132                    // --override wasn't used (nothing explicit), see what was running before
133                    Set<AbstractName> configLists = kernel.listGBeans(query);
134                    for (AbstractName configListName : configLists) {
135                        try {
136                            configs.addAll((List<Artifact>) kernel.invoke(configListName, "restore"));
137                        } catch (IOException e) {
138                            System.err.println("Unable to restore last known configurations");
139                            e.printStackTrace();
140                            shutdownKernel();
141                            return 1;
142                        }
143                    }
144                }
145    
146                monitor.foundModules(configs.toArray(new Artifact[configs.size()]));
147    
148                // load the rest of the configurations
149                try {
150                    ConfigurationManager configurationManager = ConfigurationUtil.getConfigurationManager(kernel);
151                    try {
152                        List<Artifact> unloadedConfigs = new ArrayList(configs);
153                        int unloadedConfigsCount;
154                        do {
155                            unloadedConfigsCount = unloadedConfigs.size();
156                            LinkedHashSet<Artifact> sorted = configurationManager.sort(unloadedConfigs, lifecycleMonitor);
157                            for (Artifact configID : sorted) {
158                                monitor.moduleLoading(configID);
159                                configurationManager.loadConfiguration(configID, lifecycleMonitor);
160                                monitor.moduleLoaded(configID);
161                                monitor.moduleStarting(configID);
162                                configurationManager.startConfiguration(configID, lifecycleMonitor);
163                                monitor.moduleStarted(configID);
164                            }
165                        } while (unloadedConfigsCount > unloadedConfigs.size());
166                        if (!unloadedConfigs.isEmpty()) {
167                            throw new InvalidConfigException("Could not locate configs to start: " + unloadedConfigs);
168                        }
169                        // the server has finished loading the persistent configuration so inform the gbean
170                        AbstractNameQuery startedQuery = new AbstractNameQuery(ServerStatus.class.getName());
171                        Set<AbstractName> statusBeans = kernel.listGBeans(startedQuery);
172                        for (AbstractName statusName : statusBeans) {
173                            ServerStatus status = (ServerStatus) kernel.getGBean(statusName);
174                            if (status != null) {
175                                status.setServerStarted(true);
176                            }
177                        }
178                    } finally {
179                        ConfigurationUtil.releaseConfigurationManager(kernel, configurationManager);
180                    }
181                } catch (Exception e) {
182                    //Exception caught when starting configurations, starting kernel shutdown
183                    monitor.serverStartFailed(e);
184                    shutdownKernel();
185                    return 1;
186                }
187    
188                // Tell every persistent configuration list that the kernel is now fully started
189                Set<AbstractName> configLists = kernel.listGBeans(query);
190                for (AbstractName configListName : configLists) {
191                    kernel.setAttribute(configListName, "kernelFullyStarted", Boolean.TRUE);
192                }
193    
194                // Startup sequence is finished
195                monitor.startupFinished();
196                monitor = null;
197    
198                // capture this thread until the kernel is ready to exit
199                while (kernel.isRunning()) {
200                    try {
201                        synchronized (kernel) {
202                            kernel.wait();
203                        }
204                    } catch (InterruptedException e) {
205                        // continue
206                    }
207                }
208            } catch (Exception e) {
209                if (monitor != null) {
210                    monitor.serverStartFailed(e);
211                }
212                e.printStackTrace();
213                return 1;
214            }
215            return 0;
216        }
217    
218        protected void shutdownKernel() {
219            try {
220                kernel.shutdown();
221            } catch (Exception e1) {
222                System.err.println("Exception caught during kernel shutdown");
223                e1.printStackTrace();
224            }
225        }
226    
227        protected int initializeKernel() throws Exception {
228            return 0;
229        }
230    
231        public static final GBeanInfo GBEAN_INFO;
232    
233        static {
234            GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(EmbeddedDaemon.class, "EmbeddedDaemon");
235            infoFactory.addAttribute("kernel", Kernel.class, false);
236            infoFactory.setConstructor(new String[]{"kernel"});
237            GBEAN_INFO = infoFactory.getBeanInfo();
238        }
239    
240        public static GBeanInfo getGBeanInfo() {
241            return GBEAN_INFO;
242        }
243    
244    }