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 }