1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */
22 package org.jboss.system.server.profileservice;
23
24 import java.util.Collection;
25 import java.util.concurrent.atomic.AtomicBoolean;
26
27 import org.jboss.bootstrap.spi.Bootstrap;
28 import org.jboss.dependency.spi.ControllerContext;
29 import org.jboss.deployers.client.spi.IncompleteDeploymentException;
30 import org.jboss.deployers.client.spi.main.MainDeployer;
31 import org.jboss.deployers.plugins.main.MainDeployerImpl;
32 import org.jboss.deployers.structure.spi.DeploymentContext;
33 import org.jboss.deployers.vfs.spi.client.VFSDeployment;
34 import org.jboss.kernel.Kernel;
35 import org.jboss.kernel.spi.dependency.KernelController;
36 import org.jboss.logging.Logger;
37 import org.jboss.managed.api.ManagedDeployment.DeploymentPhase;
38 import org.jboss.profileservice.spi.Profile;
39 import org.jboss.profileservice.spi.ProfileKey;
40 import org.jboss.profileservice.spi.ProfileService;
41 import org.jboss.system.server.Server;
42
43 /**
44 * Bootstraps the profile service
45 *
46 * @author Scott.Stark@jboss.org
47 * @author adrian@jboss.org
48 * @version $Revision: 73524 $
49 */
50 public class ProfileServiceBootstrap implements Bootstrap
51 {
52 /** The log */
53 private static final Logger log = Logger.getLogger(ProfileServiceBootstrap.class);
54
55 /** The name of the profile that is being booted */
56 protected String profileName = "default";
57
58 /** The server MainDeployer */
59 protected MainDeployer mainDeployer;
60
61 /** The server ProfileService */
62 protected ProfileService profileService;
63
64 /** The kernel */
65 protected Kernel kernel;
66
67 /** Whether we are shutdown */
68 private AtomicBoolean shutdown = new AtomicBoolean(false);
69
70 /**
71 * Create a new ProfileServiceBootstrap.
72 */
73 public ProfileServiceBootstrap()
74 {
75 }
76
77 /**
78 * Return the MainDeployer bean.
79 *
80 * @return the MainDeployer bean if bootstrap succeeded, null otherwise.
81 */
82 public MainDeployer getMainDeployer()
83 {
84 return mainDeployer;
85 }
86
87 /**
88 * Return the ProfileService bean.
89 *
90 * @return the ProfileService bean if bootstrap succeeded, null otherwise
91 */
92 public ProfileService getProfileService()
93 {
94 return profileService;
95 }
96
97 /**
98 * Get the kernel.
99 *
100 * @return the kernel.
101 */
102 public Kernel getKernel()
103 {
104 return kernel;
105 }
106
107 /**
108 * Set the kernel.
109 *
110 * @param kernel the kernel.
111 */
112 public void setKernel(Kernel kernel)
113 {
114 this.kernel = kernel;
115 }
116
117 public void start(Server server) throws Exception
118 {
119 shutdown.set(false);
120
121 KernelController controller = kernel.getController();
122
123 // Get the beans TODO injection!
124 profileService = getBean(controller, "ProfileService", ProfileService.class);
125 log.debug("Using ProfileService: " + profileService);
126 mainDeployer = getBean(controller, "MainDeployer", MainDeployer.class);
127 log.debug("Using MainDeployer: " + mainDeployer);
128
129 // Validate that everything is ok
130 mainDeployer.checkComplete();
131
132 // Load the profile beans
133 try
134 {
135 loadProfile(profileName);
136 }
137 catch (IncompleteDeploymentException e)
138 {
139 log.error("Failed to load profile: " + e.getMessage());
140 }
141 catch (Exception e)
142 {
143 log.error("Failed to load profile: ", e);
144 }
145 // Mark the profile as ready for hotdeployment if supported
146 Profile profile = profileService.getActiveProfile();
147 if( profile != null )
148 profile.enableModifiedDeploymentChecks(true);
149 }
150
151 public void prepareShutdown(Server server)
152 {
153 shutdown.set(true);
154 if (mainDeployer != null)
155 mainDeployer.prepareShutdown();
156 }
157
158 public void shutdown(Server server)
159 {
160 unloadProfile(profileName);
161 try
162 {
163 mainDeployer.shutdown();
164 }
165 catch (Throwable t)
166 {
167 log.warn("Error shutting down the main deployer", t);
168 }
169 }
170
171 /**
172 * Get a bean
173 *
174 * @param <T> the expected type
175 * @param controller the controller
176 * @param name the bean name
177 * @param expectedType the expected type
178 * @return the bean
179 * @throws IllegalStateException if the bean is not installed or has the wrong type
180 */
181 protected <T> T getBean(KernelController controller, Object name, Class<T> expectedType)
182 {
183 ControllerContext context = controller.getInstalledContext(name);
184 if (context == null)
185 throw new IllegalStateException("Context not installed: " + name);
186 Object result = context.getTarget();
187 if (result == null)
188 throw new IllegalStateException("No target for " + name);
189 if (expectedType.isInstance(result) == false)
190 throw new IllegalStateException(name + " expected " + expectedType.getName() + " was " + result.getClass().getName());
191 return expectedType.cast(result);
192 }
193
194 /**
195 * Load the deployments associated with the named profile and deploy them
196 * using the MainDeployer.
197 *
198 * @param name
199 * @throws Exception for any error
200 * @throws NullPointerException if either the MainDeployer or ProfileService
201 * have not been injected.
202 */
203 protected void loadProfile(String name) throws Exception
204 {
205 MainDeployer deployer = getMainDeployer();
206 if (deployer == null)
207 throw new NullPointerException("MainDeployer has not been set");
208 ProfileService ps = getProfileService();
209 if (ps == null)
210 throw new NullPointerException("ProfileService has not been set");
211
212 // Load the named profile
213 ProfileKey key = new ProfileKey(name);
214 Profile profile = ps.getProfile(key);
215
216 // HACK
217 VFSDeployment first = null;
218
219 // Deploy the bootstrap
220 Collection<VFSDeployment> boostraps = profile.getDeployments(DeploymentPhase.BOOTSTRAP);
221 for (VFSDeployment d : boostraps)
222 {
223 deployer.addDeployment(d);
224 if (first == null)
225 first = d;
226 }
227 deployer.process();
228 deployer.checkComplete();
229
230 Thread thread = Thread.currentThread();
231 ClassLoader old = thread.getContextClassLoader();
232 // FIXME remove this hack
233 MainDeployerImpl hack = (MainDeployerImpl) deployer;
234 ClassLoader cl = null;
235 if (first != null)
236 {
237 DeploymentContext ctx = hack.getDeploymentContext(first.getName());
238 if (ctx != null)
239 cl = ctx.getClassLoader();
240 }
241 //if (cl != null)
242 // thread.setContextClassLoader(cl);
243 try
244 {
245
246 // Deploy the profile deployers
247 Collection<VFSDeployment> profileDeployers = profile.getDeployments(DeploymentPhase.DEPLOYER);
248 for (VFSDeployment d : profileDeployers)
249 deployer.addDeployment(d);
250 deployer.process();
251 deployer.checkComplete();
252
253 // Deploy the profile applications
254 Collection<VFSDeployment> profileDeployments = profile.getDeployments(DeploymentPhase.APPLICATION);
255 for (VFSDeployment d : profileDeployments)
256 deployer.addDeployment(d);
257 deployer.process();
258 deployer.checkComplete();
259 }
260 finally
261 {
262 thread.setContextClassLoader(old);
263 }
264 }
265
266 /**
267 * Unload the deployments associated with the named profile and undeploy them
268 * using the MainDeployer in reverse phase order.
269 *
270 * @param name the profile name
271 * @throws NullPointerException if either the MainDeployer or ProfileService
272 * have not been injected.
273 */
274 protected void unloadProfile(String name)
275 {
276 MainDeployer deployer = getMainDeployer();
277 if (deployer == null)
278 {
279 log.warn("MainDeployer has not been set");
280 return;
281 }
282 ProfileService ps = getProfileService();
283 if (ps == null)
284 {
285 log.warn("ProfileService has not been set");
286 return;
287 }
288
289 try
290 {
291 // Load the named profile
292 ProfileKey key = new ProfileKey(name);
293 Profile profile = ps.getProfile(key);
294
295 // HACK
296 VFSDeployment first = null;
297
298 // Deploy the bootstrap
299 Collection<VFSDeployment> boostraps = profile.getDeployments(DeploymentPhase.BOOTSTRAP);
300 for (VFSDeployment d : boostraps)
301 {
302 if (first == null)
303 {
304 first = d;
305 break;
306 }
307 }
308
309 Thread thread = Thread.currentThread();
310 ClassLoader old = thread.getContextClassLoader();
311 // FIXME remove this hack
312 MainDeployerImpl hack = (MainDeployerImpl) deployer;
313 ClassLoader cl = null;
314 if (first != null)
315 {
316 try
317 {
318 DeploymentContext ctx = hack.getDeploymentContext(first.getName());
319 if (ctx != null)
320 cl = ctx.getClassLoader();
321 }
322 catch (Exception e)
323 {
324 log.debug("Unable to get first deployment", e);
325 }
326 }
327 //if (cl != null)
328 // thread.setContextClassLoader(cl);
329 try
330 {
331 // Undeploy the applications
332 unload(deployer, profile.getDeployments(DeploymentPhase.APPLICATION));
333 // Undeploy the deployers
334 unload(deployer, profile.getDeployments(DeploymentPhase.DEPLOYER));
335 // Undeploy the bootstrap
336 unload(deployer, profile.getDeployments(DeploymentPhase.BOOTSTRAP));
337 }
338 finally
339 {
340 thread.setContextClassLoader(old);
341 }
342 }
343 catch (Throwable t)
344 {
345 log.warn("Error unloading profile", t);
346 }
347 }
348
349 /**
350 * Unload a set of deployments
351 *
352 * @param deployer the main deployer
353 * @param deployments the deployments
354 */
355 protected void unload(MainDeployer deployer, Collection<VFSDeployment> deployments)
356 {
357 if (deployments == null || deployments.isEmpty())
358 return;
359
360 for (VFSDeployment d : deployments)
361 {
362 try
363 {
364 deployer.removeDeployment(d);
365 }
366 catch (Exception e)
367 {
368 log.warn("Unable to remove deployment: " + d);
369 }
370 }
371 deployer.process();
372 }
373 }