1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.uruma.rcp.core;
17
18 import java.io.FileNotFoundException;
19 import java.net.URL;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.Enumeration;
23 import java.util.List;
24 import java.util.Locale;
25 import java.util.MissingResourceException;
26 import java.util.ResourceBundle;
27
28 import org.eclipse.core.runtime.ContributorFactoryOSGi;
29 import org.eclipse.core.runtime.IContributor;
30 import org.eclipse.ui.IWorkbench;
31 import org.eclipse.ui.PlatformUI;
32 import org.osgi.framework.Bundle;
33 import org.seasar.framework.container.S2Container;
34 import org.seasar.framework.container.factory.S2ContainerFactory;
35 import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
36 import org.seasar.framework.env.Env;
37 import org.seasar.framework.exception.ResourceNotFoundRuntimeException;
38 import org.seasar.framework.util.ResourceUtil;
39 import org.seasar.framework.util.StringUtil;
40 import org.seasar.framework.util.URLUtil;
41 import org.seasar.uruma.component.Template;
42 import org.seasar.uruma.component.UIComponentContainer;
43 import org.seasar.uruma.component.jface.TemplateImpl;
44 import org.seasar.uruma.component.rcp.ViewPartComponent;
45 import org.seasar.uruma.component.rcp.WorkbenchComponent;
46 import org.seasar.uruma.context.ApplicationContext;
47 import org.seasar.uruma.context.ContextFactory;
48 import org.seasar.uruma.context.WindowContext;
49 import org.seasar.uruma.core.ComponentUtil;
50 import org.seasar.uruma.core.TemplateManager;
51 import org.seasar.uruma.core.UrumaConstants;
52 import org.seasar.uruma.core.UrumaMessageCodes;
53 import org.seasar.uruma.core.ViewTemplateLoader;
54 import org.seasar.uruma.debug.action.UrumaDebugViewAction;
55 import org.seasar.uruma.exception.NotFoundException;
56 import org.seasar.uruma.exception.UrumaAppInitException;
57 import org.seasar.uruma.log.UrumaLogger;
58 import org.seasar.uruma.rcp.UrumaService;
59 import org.seasar.uruma.rcp.binding.CommandRegistry;
60 import org.seasar.uruma.rcp.configuration.ContributionBuilder;
61 import org.seasar.uruma.rcp.configuration.Extension;
62 import org.seasar.uruma.rcp.core.UrumaBundleState.BundleState;
63 import org.seasar.uruma.rcp.util.RcpResourceUtil;
64 import org.seasar.uruma.util.AssertionUtil;
65
66
67
68
69
70
71
72 public class UrumaServiceImpl implements UrumaService, UrumaConstants,
73 UrumaMessageCodes {
74 private static final UrumaLogger logger = UrumaLogger
75 .getLogger(UrumaService.class);
76
77 protected static final String URUMA_CLASSLOADER_NAME = "UrumaClassLoader";
78
79 protected static final String APP_CLASSLOADER_PREFIX = "AppClassLoader-";
80
81 protected String appClassLoaderName;
82
83 protected Bundle targetBundle;
84
85 protected ClassLoader urumaClassLoader;
86
87 protected ClassLoader appClassLoader;
88
89 protected ClassLoader oldClassLoader;
90
91 protected IContributor contributor;
92
93 protected String pluginId;
94
95 protected S2Container container;
96
97 protected TemplateManager templateManager;
98
99 protected ViewTemplateLoader templateLoader;
100
101 protected ApplicationContext applicationContext;
102
103 protected WindowContext windowContext;
104
105 protected WorkbenchComponent workbenchComponent;
106
107 protected List<Extension> extensions = new ArrayList<Extension>();
108
109 protected String defaultContextId;
110
111 protected ResourceBundle imageBundle;
112
113
114
115
116
117
118
119 public UrumaServiceImpl(final Bundle targetBundle) {
120 AssertionUtil.assertNotNull("targetBundle", targetBundle);
121 this.targetBundle = targetBundle;
122 this.urumaClassLoader = getClass().getClassLoader();
123 this.appClassLoader = getClass().getClassLoader();
124 this.pluginId = targetBundle.getSymbolicName();
125 this.defaultContextId = pluginId + ".context";
126 this.appClassLoaderName = APP_CLASSLOADER_PREFIX + this.pluginId;
127 initialize();
128 }
129
130
131
132
133 protected void initialize() {
134 logger.log(URUMA_SERVICE_INIT_START, targetBundle.getSymbolicName());
135
136 try {
137 ClassLoader loader = activateUrumaApplication(targetBundle);
138
139 if (loader != null) {
140 this.appClassLoader = loader;
141 }
142 switchToAppClassLoader();
143
144 initS2Container();
145 prepareS2Components();
146
147 UrumaBundleState.getInstance().setAppBundleState(
148 BundleState.AVAILABLE);
149 logger.log(URUMA_SERVICE_INIT_END, targetBundle.getSymbolicName());
150 } catch (Throwable ex) {
151 logger.log(EXCEPTION_OCCURED_WITH_REASON, ex, ex.getMessage());
152 UrumaBundleState.getInstance().setUrumaAppInitializingException(ex);
153 throw new UrumaAppInitException(targetBundle, ex, ex.getMessage());
154 } finally {
155 restoreClassLoader();
156 }
157 }
158
159
160
161
162 protected void registerExtensions() {
163
164
165 if (Env.UT.equals(Env.getValue())) {
166 try {
167 String workbenchPath = DEFAULT_WORKBENCH_XML;
168 URL resourceUrl = RcpResourceUtil
169 .getLocalResourceUrl(workbenchPath);
170 if (resourceUrl != null) {
171 templateLoader.loadViewTemplates(resourceUrl);
172
173
174
175
176
177 templateManager.getTemplates(ViewPartComponent.class);
178 } else {
179 throw new ResourceNotFoundRuntimeException(workbenchPath);
180 }
181 } catch (Exception ex) {
182 logger.log(EXCEPTION_OCCURED_WITH_REASON, ex, ex.getMessage());
183 throw new UrumaAppInitException(targetBundle, ex, ex
184 .getMessage());
185 }
186 }
187
188 switchToAppClassLoader();
189 try {
190 setupContributor();
191
192 setupContexts();
193 if (!DUMMY_WORKBENCH_PATH.equals(workbenchComponent.getPath())) {
194
195 URL resourceUrl = RcpResourceUtil
196 .getLocalResourceUrl(DEFAULT_WORKBENCH_XML);
197 templateLoader.loadViewTemplates(resourceUrl);
198 }
199 ContributionBuilder.build(contributor, extensions);
200 } catch (Exception ex) {
201 logger.log(EXCEPTION_OCCURED_WITH_REASON, ex, ex.getMessage());
202 throw new UrumaAppInitException(targetBundle, ex, ex.getMessage());
203 } finally {
204 restoreClassLoader();
205 }
206 }
207
208
209
210
211
212
213
214
215
216 protected ClassLoader activateUrumaApplication(final Bundle bundle) {
217 String symbolicName = bundle.getSymbolicName();
218 logger.log(URUMA_APP_STARTING, symbolicName);
219
220 ClassLoader bundleLoader = null;
221
222 String className = findFirstClassName(bundle);
223 if (className != null) {
224 try {
225 Class<?> clazz = bundle.loadClass(className);
226 bundleLoader = clazz.getClassLoader();
227 } catch (ClassNotFoundException ex) {
228 throw new UrumaAppInitException(bundle, ex, ex.getMessage());
229 }
230 } else {
231 throw new NotFoundException(URUMA_APP_CLASS_LOADER_NOT_FOUND);
232 }
233
234 logger.log(URUMA_APP_STARTED, symbolicName);
235 return bundleLoader;
236 }
237
238
239
240
241
242
243
244
245 @SuppressWarnings("unchecked")
246 protected String findFirstClassName(final Bundle bundle) {
247 Enumeration entries = bundle.findEntries("", "*.class", true);
248 if (entries != null) {
249 while (entries.hasMoreElements()) {
250
251 String path = ((URL) entries.nextElement()).getPath();
252
253 path = path.substring(0, path.length() - ".class".length());
254
255 path = StringUtil.replace(path, SLASH, PERIOD);
256
257
258
259 while (true) {
260 int pos = path.indexOf(PERIOD);
261 if (pos >= 0) {
262 path = path.substring(pos + 1);
263 try {
264 bundle.loadClass(path);
265 return path;
266 } catch (ClassNotFoundException ex) {
267 continue;
268 } catch (NoClassDefFoundError ex) {
269 continue;
270 }
271 } else {
272 break;
273 }
274 }
275 return path;
276 }
277 }
278 return null;
279 }
280
281
282
283
284 protected void initS2Container() throws ClassNotFoundException {
285 switchToUrumaClassLoader();
286
287
288 S2ContainerFactory.destroy();
289
290
291 S2Container urumaContainer = S2ContainerFactory
292 .create(UrumaConstants.URUMA_RCP_DICON_PATH);
293
294 switchToAppClassLoader();
295
296 String configPath = SingletonS2ContainerFactory.getConfigPath();
297
298
299 URL url = RcpResourceUtil
300 .getLocalResourceUrlNoException(Env.DEFAULT_FILE_PATH);
301 if (url != null) {
302 try {
303 Env.setFile(URLUtil.toFile(url));
304 } catch (FileNotFoundException ignore) {
305 }
306 }
307
308
309 try {
310 S2ContainerFactory.configure();
311 ResourceUtil.getResource(configPath);
312 container = S2ContainerFactory.create(configPath,
313 getAppClassLoader());
314 } catch (ResourceNotFoundRuntimeException ex) {
315
316 container = S2ContainerFactory.create();
317 }
318
319 container.include(urumaContainer);
320 container.init();
321
322 SingletonS2ContainerFactory.setContainer(container);
323
324 ComponentUtil.setS2Container(container);
325 }
326
327 protected void prepareS2Components() {
328 this.templateManager = (TemplateManager) container
329 .getComponent(TemplateManager.class);
330 this.templateLoader = (ViewTemplateLoader) container
331 .getComponent(ViewTemplateLoader.class);
332 this.applicationContext = (ApplicationContext) container
333 .getComponent(ApplicationContext.class);
334
335 container.register(this, UrumaConstants.URUMA_SERVICE_S2NAME);
336
337
338 if (Env.UT.equals(Env.getValue())) {
339 UrumaDebugViewAction urumaDebugViewAction = new UrumaDebugViewAction();
340 String name = StringUtil.decapitalize(UrumaDebugViewAction.class
341 .getSimpleName());
342 container.register(urumaDebugViewAction, name);
343 }
344 }
345
346 protected void switchClassLoader(final ClassLoader loader,
347 final String loaderName) {
348 Thread currentThread = Thread.currentThread();
349 this.oldClassLoader = currentThread.getContextClassLoader();
350 if (logger.isDebugEnabled()) {
351 logger.log(SWITCH_CONTEXT_CLASS_LOADER, loaderName + "("
352 + loader.toString() + ")");
353 }
354 currentThread.setContextClassLoader(loader);
355 }
356
357 protected void setupContributor() {
358 this.contributor = ContributorFactoryOSGi
359 .createContributor(targetBundle);
360 }
361
362 protected void setupContexts() {
363 Template workbenchTemplate = getTemplate(DEFAULT_WORKBENCH_XML);
364 if (workbenchTemplate == null) {
365 logger.log(WORKBENCH_DEF_FILE_NOT_FOUND, DEFAULT_WORKBENCH_XML);
366
367 workbenchTemplate = createDummyWorkbenchTemplate();
368 }
369
370 UIComponentContainer root = workbenchTemplate.getRootComponent();
371 if (root instanceof WorkbenchComponent) {
372 this.workbenchComponent = (WorkbenchComponent) root;
373 } else {
374 throw new NotFoundException(WORKBENCH_ELEMENT_NOT_FOUND,
375 workbenchTemplate.getPath());
376 }
377
378 this.applicationContext.setValue(WORKBENCH_TEMPLATE_NAME,
379 workbenchTemplate);
380 this.windowContext = ContextFactory.createWindowContext(
381 applicationContext, WORKBENCH_WINDOW_CONTEXT_ID);
382 }
383
384 protected Template createDummyWorkbenchTemplate() {
385 Template template = new TemplateImpl();
386 WorkbenchComponent workbench = new WorkbenchComponent();
387 workbench.setPath(DUMMY_WORKBENCH_PATH);
388 workbench.title = "Uruma";
389 workbench.initWidth = "50%";
390 workbench.initHeight = "50%";
391 template.setRootComponent(workbench);
392 return template;
393 }
394
395
396
397
398 public Bundle getBundle() {
399 return this.targetBundle;
400 }
401
402
403
404
405 public String getPluginId() {
406 return this.pluginId;
407 }
408
409
410
411
412 public String createRcpId(final String id) {
413 return pluginId + PERIOD + id;
414 }
415
416
417
418
419 public String getLocalId(final String rcpId) {
420 if (rcpId != null) {
421 if (rcpId.startsWith(pluginId)) {
422 return rcpId.substring(pluginId.length() + 1, rcpId.length());
423 } else {
424 return rcpId;
425 }
426 } else {
427 return null;
428 }
429 }
430
431
432
433
434 public Template getTemplate(final String path) {
435 try {
436 Template template = templateManager.getTemplate(path);
437 return template;
438 } catch (ResourceNotFoundRuntimeException ex) {
439 return null;
440 }
441 }
442
443
444
445
446 public IWorkbench getWorkbench() {
447 return PlatformUI.getWorkbench();
448 }
449
450
451
452
453 public WorkbenchComponent getWorkbenchComponent() {
454 Template template = (Template) applicationContext
455 .getValue(UrumaConstants.WORKBENCH_TEMPLATE_NAME);
456 return (WorkbenchComponent) template.getRootComponent();
457 }
458
459
460
461
462 public List<Extension> getExtensions() {
463 return Collections.unmodifiableList(extensions);
464 }
465
466
467
468
469 public Extension getExtension(final String point) {
470 for (Extension extension : extensions) {
471 if (extension.point.equals(point)) {
472 return extension;
473 }
474 }
475 return null;
476 }
477
478
479
480
481 public WindowContext getWorkbenchWindowContext() {
482 return this.windowContext;
483 }
484
485
486
487
488 public S2Container getContainer() {
489 return this.container;
490 }
491
492
493
494
495 public ClassLoader getAppClassLoader() {
496 return this.appClassLoader;
497 }
498
499
500
501
502 public ClassLoader getUrumaClassLoader() {
503 return this.urumaClassLoader;
504 }
505
506
507
508
509 public void switchToAppClassLoader() {
510 switchClassLoader(appClassLoader, appClassLoaderName);
511 }
512
513
514
515
516 public void switchToUrumaClassLoader() {
517 switchClassLoader(urumaClassLoader, URUMA_CLASSLOADER_NAME);
518 }
519
520
521
522
523 public void restoreClassLoader() {
524 if (logger.isDebugEnabled()) {
525 String name = "";
526 if (oldClassLoader == urumaClassLoader) {
527 name = URUMA_CLASSLOADER_NAME;
528 } else if (oldClassLoader == appClassLoader) {
529 name = appClassLoaderName;
530 }
531 logger.log(SWITCH_CONTEXT_CLASS_LOADER, name + "("
532 + oldClassLoader.toString() + ")");
533 }
534 Thread.currentThread().setContextClassLoader(oldClassLoader);
535 }
536
537
538
539
540 public CommandRegistry getCommandRegistry() {
541 return (CommandRegistry) container.getComponent(CommandRegistry.class);
542 }
543
544
545
546
547 public String getDefaultContextId() {
548 return this.defaultContextId;
549 }
550
551
552
553
554 public ResourceBundle getImageBundle() {
555 if (imageBundle == null) {
556 try {
557 imageBundle = ResourceBundle.getBundle(
558 DEFAULT_IMAGE_BUNDLE_PATH, Locale.getDefault(),
559 appClassLoader);
560 } catch (MissingResourceException ex) {
561 logger.log(IMAGE_DEF_BUNDLE_NOT_FOUND,
562 DEFAULT_IMAGE_BUNDLE_PATH);
563 }
564 }
565 return imageBundle;
566 }
567
568
569
570
571 void destroy() {
572 logger.log(URUMA_SERVICE_DESTROY, targetBundle.getSymbolicName());
573 container.destroy();
574 }
575
576
577
578
579 public List<ViewPartComponent> getViewPartComponent() {
580 List<ViewPartComponent> resultList = new ArrayList<ViewPartComponent>();
581 List<Template> templates = templateManager
582 .getTemplates(ViewPartComponent.class);
583 for (Template template : templates) {
584 ViewPartComponent viewPart = (ViewPartComponent) template
585 .getRootComponent();
586 resultList.add(viewPart);
587 }
588 return resultList;
589 }
590 }