1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.geronimo.gshell.wisdom.application;
21
22 import org.apache.geronimo.gshell.application.Application;
23 import org.apache.geronimo.gshell.application.ApplicationConfiguration;
24 import org.apache.geronimo.gshell.application.ApplicationManager;
25 import org.apache.geronimo.gshell.application.ClassPath;
26 import org.apache.geronimo.gshell.application.model.ApplicationModel;
27 import org.apache.geronimo.gshell.artifact.Artifact;
28 import org.apache.geronimo.gshell.artifact.ArtifactResolver;
29 import org.apache.geronimo.gshell.chronos.StopWatch;
30 import org.apache.geronimo.gshell.event.EventPublisher;
31 import org.apache.geronimo.gshell.shell.Shell;
32 import org.apache.geronimo.gshell.shell.ShellContext;
33 import org.apache.geronimo.gshell.shell.ShellContextHolder;
34 import org.apache.geronimo.gshell.spring.BeanContainer;
35 import org.apache.geronimo.gshell.spring.BeanContainerAware;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 import java.io.File;
40 import java.lang.reflect.InvocationHandler;
41 import java.lang.reflect.InvocationTargetException;
42 import java.lang.reflect.Method;
43 import java.lang.reflect.Proxy;
44 import java.net.URL;
45 import java.util.Collection;
46
47
48
49
50
51
52 public class ApplicationManagerImpl
53 implements ApplicationManager, BeanContainerAware
54 {
55 private final Logger log = LoggerFactory.getLogger(getClass());
56
57 private final EventPublisher eventPublisher;
58
59 private ArtifactResolver artifactResolver;
60
61 private BeanContainer container;
62
63 private BeanContainer applicationContainer;
64
65 private Application application;
66
67 public ApplicationManagerImpl(final EventPublisher eventPublisher, final ArtifactResolver artifactResolver) {
68 assert eventPublisher != null;
69 this.eventPublisher = eventPublisher;
70
71 assert artifactResolver != null;
72 this.artifactResolver = artifactResolver;
73 }
74
75 public void setBeanContainer(final BeanContainer container) {
76 assert container != null;
77
78 this.container = container;
79 }
80
81 public Application getApplication() {
82 if (application == null) {
83 throw new IllegalStateException("Application has not been configured");
84 }
85
86 return application;
87 }
88
89 public void configure(final ApplicationConfiguration config) throws Exception {
90 assert config != null;
91
92 log.trace("Configuring; config: {}", config);
93
94
95 config.validate();
96
97 application = loadApplication(config);
98
99 log.debug("Application configured");
100
101 eventPublisher.publish(new ApplicationConfiguredEvent(application));
102 }
103
104 private ApplicationImpl loadApplication(final ApplicationConfiguration config) throws Exception {
105 assert config != null;
106
107 StopWatch watch = new StopWatch(true);
108
109 ApplicationImpl app = new ApplicationImpl(config);
110 ApplicationModel model = app.getModel();
111
112 log.debug("Loading application: {}", app.getId());
113 log.trace("Application model: {}", model);
114
115 ClassPath classPath = loadClassPath(model);
116 app.initClassPath(classPath);
117
118 BeanContainer child = container.createChild(classPath.getUrls());
119 log.debug("Application container: {}", child);
120
121 child.loadBeans(new String[] {
122 "classpath*:META-INF/gshell/components.xml"
123 });
124
125 applicationContainer = child;
126
127 log.debug("Application loaded in: {}", watch);
128
129 return app;
130 }
131
132 private ClassPath loadClassPath(final ApplicationModel model) throws Exception {
133 assert model != null;
134
135
136 Artifact artifact = model.getArtifact();
137 ClassPathCache cache = new ClassPathCache(new File(new File(System.getProperty("gshell.home")), "var/" + artifact.getGroup() + "/" + artifact.getName() + "/classpath.ser"));
138
139 ClassPath classPath = cache.get();
140
141 if (classPath == null) {
142 Collection<Artifact> artifacts = resolveArtifacts(model);
143 classPath = new ClassPathImpl(artifacts);
144 cache.set(classPath);
145 }
146
147 if (log.isDebugEnabled()) {
148 log.debug("Application classpath:");
149
150 for (URL url : classPath.getUrls()) {
151 log.debug(" {}", url);
152 }
153 }
154
155 return classPath;
156 }
157
158 private Collection<Artifact> resolveArtifacts(final ApplicationModel model) throws Exception {
159 assert model != null;
160
161 log.debug("Resolving application artifacts");
162
163 ArtifactResolver.Request request = new ArtifactResolver.Request();
164
165 request.filter = new ApplicationArtifactFilter();
166 request.artifact = model.getArtifact();
167 request.artifacts = model.getDependencies();
168
169 ArtifactResolver.Result result = artifactResolver.resolve(request);
170
171 return result.artifacts;
172 }
173
174
175
176
177
178 public Shell create() throws Exception {
179
180 getApplication();
181
182 final Shell shell = applicationContainer.getBean(Shell.class);
183
184 final ShellContext context = shell.getContext();
185
186 log.debug("Created shell instance: {}", shell);
187
188 InvocationHandler handler = new InvocationHandler() {
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
205 assert proxy != null;
206 assert method != null;
207
208
209 if (method.getDeclaringClass() == Object.class) {
210 return method.invoke(this, args);
211 }
212
213 final ShellContext prevContext = ShellContextHolder.get(true);
214 ShellContextHolder.set(context);
215
216
217
218
219 try {
220 return method.invoke(shell, args);
221 }
222 catch (InvocationTargetException e) {
223 throw e.getTargetException();
224 }
225 finally {
226
227 ShellContextHolder.set(prevContext);
228 }
229 }
230 };
231
232 ClassLoader cl = Thread.currentThread().getContextClassLoader();
233 Shell proxy = (Shell) Proxy.newProxyInstance(cl, new Class[] { Shell.class }, handler);
234
235 log.debug("Create shell proxy: {}", proxy);
236
237 eventPublisher.publish(new ShellCreatedEvent(proxy));
238
239 return proxy;
240 }
241 }