001
014
015 package com.liferay.portal.module.framework;
016
017 import aQute.libg.header.OSGiHeader;
018
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.util.ReleaseInfo;
023 import com.liferay.portal.kernel.util.ServiceLoader;
024 import com.liferay.portal.kernel.util.StringBundler;
025 import com.liferay.portal.kernel.util.StringPool;
026 import com.liferay.portal.kernel.util.StringUtil;
027 import com.liferay.portal.kernel.util.UniqueList;
028 import com.liferay.portal.kernel.util.Validator;
029 import com.liferay.portal.security.auth.PrincipalException;
030 import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
031 import com.liferay.portal.security.permission.PermissionChecker;
032 import com.liferay.portal.security.permission.PermissionThreadLocal;
033 import com.liferay.portal.util.PropsValues;
034
035 import java.io.InputStream;
036
037 import java.net.URL;
038
039 import java.util.ArrayList;
040 import java.util.Arrays;
041 import java.util.Collections;
042 import java.util.Enumeration;
043 import java.util.HashMap;
044 import java.util.HashSet;
045 import java.util.Hashtable;
046 import java.util.List;
047 import java.util.Map;
048 import java.util.Set;
049 import java.util.jar.Attributes;
050 import java.util.jar.Manifest;
051
052 import javax.servlet.ServletContext;
053
054 import org.osgi.framework.Bundle;
055 import org.osgi.framework.BundleContext;
056 import org.osgi.framework.BundleException;
057 import org.osgi.framework.Constants;
058 import org.osgi.framework.FrameworkListener;
059 import org.osgi.framework.launch.Framework;
060 import org.osgi.framework.launch.FrameworkFactory;
061 import org.osgi.framework.startlevel.BundleStartLevel;
062 import org.osgi.framework.startlevel.FrameworkStartLevel;
063
064 import org.springframework.beans.factory.BeanIsAbstractException;
065 import org.springframework.context.ApplicationContext;
066
067
070 public class ModuleFrameworkUtil implements ModuleFrameworkConstants {
071
072 public static Object addBundle(String location) throws PortalException {
073 return addBundle(location, null);
074 }
075
076 public static Object addBundle(String location, InputStream inputStream)
077 throws PortalException {
078
079 return _instance._addBundle(location, inputStream);
080 }
081
082 public static Framework getFramework() {
083 return _instance._getFramework();
084 }
085
086 public static String getState(long bundleId) throws PortalException {
087 return _instance._getState(bundleId);
088 }
089
090 public static void registerContext(Object context) {
091 _instance._registerContext(context);
092 }
093
094 public static void setBundleStartLevel(long bundleId, int startLevel)
095 throws PortalException {
096
097 _instance._setBundleStartLevel(bundleId, startLevel);
098 }
099
100 public static void startBundle(long bundleId) throws PortalException {
101 _instance._startBundle(bundleId);
102 }
103
104 public static void startBundle(long bundleId, int options)
105 throws PortalException {
106
107 _instance._startBundle(bundleId, options);
108 }
109
110 public static void startFramework() throws Exception {
111 _instance._startFramework();
112 }
113
114 public static void startRuntime() throws Exception {
115 _instance._startRuntime();
116 }
117
118 public static void stopBundle(long bundleId) throws PortalException {
119 _instance._stopBundle(bundleId);
120 }
121
122 public static void stopBundle(long bundleId, int options)
123 throws PortalException {
124
125 _instance._stopBundle(bundleId, options);
126 }
127
128 public static void stopFramework() throws Exception {
129 _instance._stopFramework();
130 }
131
132 public static void stopRuntime() throws Exception {
133 _instance._stopRuntime();
134 }
135
136 public static void uninstallBundle(long bundleId) throws PortalException {
137 _instance._uninstallBundle(bundleId);
138 }
139
140 public static void updateBundle(long bundleId) throws PortalException {
141 _instance._updateBundle(bundleId);
142 }
143
144 public static void updateBundle(long bundleId, InputStream inputStream)
145 throws PortalException {
146
147 _instance._updateBundle(bundleId, inputStream);
148 }
149
150 private ModuleFrameworkUtil() {
151 }
152
153 private Object _addBundle(String location, InputStream inputStream)
154 throws PortalException {
155
156 _checkPermission();
157
158 if (_framework == null) {
159 return null;
160 }
161
162 BundleContext bundleContext = _framework.getBundleContext();
163
164 try {
165 return bundleContext.installBundle(location, inputStream);
166 }
167 catch (BundleException be) {
168 _log.error(be, be);
169
170 throw new ModuleFrameworkException(be);
171 }
172 }
173
174 private Map<String, String> _buildProperties() {
175 Map<String, String> properties = new HashMap<String, String>();
176
177 properties.put(
178 Constants.BUNDLE_DESCRIPTION, ReleaseInfo.getReleaseInfo());
179 properties.put(Constants.BUNDLE_NAME, ReleaseInfo.getName());
180 properties.put(Constants.BUNDLE_VENDOR, ReleaseInfo.getVendor());
181 properties.put(Constants.BUNDLE_VERSION, ReleaseInfo.getVersion());
182 properties.put(
183 Constants.FRAMEWORK_BEGINNING_STARTLEVEL,
184 String.valueOf(PropsValues.MODULE_FRAMEWORK_BEGINNING_START_LEVEL));
185 properties.put(
186 Constants.FRAMEWORK_BUNDLE_PARENT,
187 Constants.FRAMEWORK_BUNDLE_PARENT_APP);
188 properties.put(
189 Constants.FRAMEWORK_STORAGE,
190 PropsValues.MODULE_FRAMEWORK_STATE_DIR);
191
192 UniqueList<String> packages = new UniqueList<String>();
193
194 try {
195 _getBundleExportPackages(
196 PropsValues.MODULE_FRAMEWORK_SYSTEM_BUNDLE_EXPORT_PACKAGES,
197 packages);
198 }
199 catch (Exception e) {
200 _log.error(e, e);
201 }
202
203 packages.addAll(
204 Arrays.asList(PropsValues.MODULE_FRAMEWORK_SYSTEM_PACKAGES_EXTRA));
205
206 Collections.sort(packages);
207
208 properties.put(
209 Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA,
210 StringUtil.merge(packages));
211
212 return properties;
213 }
214
215 private void _checkPermission() throws PrincipalException {
216 PermissionChecker permissionChecker =
217 PermissionThreadLocal.getPermissionChecker();
218
219 if ((permissionChecker == null) || !permissionChecker.isOmniadmin()) {
220 throw new PrincipalException();
221 }
222 }
223
224 private Bundle _getBundle(long bundleId) {
225 if (_framework == null) {
226 return null;
227 }
228
229 BundleContext bundleContext = _framework.getBundleContext();
230
231 return bundleContext.getBundle(bundleId);
232 }
233
234 private void _getBundleExportPackages(
235 String[] bundleSymbolicNames, List<String> packages)
236 throws Exception {
237
238 ClassLoader classLoader = PACLClassLoaderUtil.getPortalClassLoader();
239
240 Enumeration<URL> enu = classLoader.getResources("META-INF/MANIFEST.MF");
241
242 while (enu.hasMoreElements()) {
243 URL url = enu.nextElement();
244
245 Manifest manifest = new Manifest(url.openStream());
246
247 Attributes attributes = manifest.getMainAttributes();
248
249 String bundleSymbolicName = attributes.getValue(
250 Constants.BUNDLE_SYMBOLICNAME);
251
252 if (Validator.isNull(bundleSymbolicName)) {
253 continue;
254 }
255
256 for (String curBundleSymbolicName : bundleSymbolicNames) {
257 if (!bundleSymbolicName.startsWith(curBundleSymbolicName)) {
258 continue;
259 }
260
261 String exportPackage = attributes.getValue(
262 Constants.EXPORT_PACKAGE);
263
264 Map<String, Map<String, String>> exportPackageMap =
265 OSGiHeader.parseHeader(exportPackage);
266
267 for (Map.Entry<String, Map<String, String>> entry :
268 exportPackageMap.entrySet()) {
269
270 String javaPackage = entry.getKey();
271 Map<String, String> javaPackageMap = entry.getValue();
272
273 StringBundler sb = new StringBundler(4);
274
275 sb.append(javaPackage);
276 sb.append(";version=\"");
277
278 if (javaPackageMap.containsKey("version")) {
279 String version = javaPackageMap.get("version");
280
281 sb.append(version);
282 }
283 else {
284 String bundleVersionString = attributes.getValue(
285 Constants.BUNDLE_VERSION);
286
287 sb.append(bundleVersionString);
288 }
289
290 sb.append("\"");
291
292 javaPackage = sb.toString();
293
294 packages.add(javaPackage);
295 }
296
297 break;
298 }
299 }
300 }
301
302 private Framework _getFramework() {
303 return _framework;
304 }
305
306 private Set<Class<?>> _getInterfaces(Object bean) {
307 Set<Class<?>> interfaces = new HashSet<Class<?>>();
308
309 Class<?> beanClass = bean.getClass();
310
311 for (Class<?> interfaceClass : beanClass.getInterfaces()) {
312 interfaces.add(interfaceClass);
313 }
314
315 while ((beanClass = beanClass.getSuperclass()) != null) {
316 for (Class<?> interfaceClass : beanClass.getInterfaces()) {
317 if (!interfaces.contains(interfaceClass)) {
318 interfaces.add(interfaceClass);
319 }
320 }
321 }
322
323 return interfaces;
324 }
325
326 private String _getState(long bundleId) throws PortalException {
327 _checkPermission();
328
329 Bundle bundle = _getBundle(bundleId);
330
331 if (bundle == null) {
332 throw new ModuleFrameworkException("No bundle with ID " + bundleId);
333 }
334
335 int state = bundle.getState();
336
337 if (state == Bundle.ACTIVE) {
338 return "active";
339 }
340 else if (state == Bundle.INSTALLED) {
341 return "installed";
342 }
343 else if (state == Bundle.RESOLVED) {
344 return "resolved";
345 }
346 else if (state == Bundle.STARTING) {
347 return "starting";
348 }
349 else if (state == Bundle.STOPPING) {
350 return "stopping";
351 }
352 else if (state == Bundle.UNINSTALLED) {
353 return "uninstalled";
354 }
355 else {
356 return StringPool.BLANK;
357 }
358 }
359
360 private void _registerApplicationContext(
361 ApplicationContext applicationContext) {
362
363 BundleContext bundleContext = _framework.getBundleContext();
364
365 for (String beanName : applicationContext.getBeanDefinitionNames()) {
366 Object bean = null;
367
368 try {
369 bean = applicationContext.getBean(beanName);
370 }
371 catch (BeanIsAbstractException biae) {
372 }
373 catch (Exception e) {
374 _log.error(e, e);
375 }
376
377 if (bean != null) {
378 _registerService(bundleContext, beanName, bean);
379 }
380 }
381 }
382
383 private void _registerContext(Object context) {
384 if (context == null) {
385 return;
386 }
387
388 if ((context instanceof ApplicationContext) &&
389 PropsValues.MODULE_FRAMEWORK_REGISTER_LIFERAY_SERVICES) {
390
391 ApplicationContext applicationContext = (ApplicationContext)context;
392
393 _registerApplicationContext(applicationContext);
394 }
395 else if (context instanceof ServletContext) {
396 ServletContext servletContext = (ServletContext)context;
397
398 _registerServletContext(servletContext);
399 }
400 }
401
402 private void _registerService(
403 BundleContext bundleContext, String beanName, Object bean) {
404
405 Set<Class<?>> interfaces = _getInterfaces(bean);
406
407 List<String> names = new ArrayList<String>();
408
409 for (Class<?> interfaceClass : interfaces) {
410 names.add(interfaceClass.getName());
411 }
412
413 if (names.isEmpty()) {
414 return;
415 }
416
417 Hashtable<String, Object> properties = new Hashtable<String, Object>();
418
419 properties.put(BEAN_ID, beanName);
420 properties.put(ORIGINAL_BEAN, Boolean.TRUE);
421 properties.put(SERVICE_VENDOR, ReleaseInfo.getVendor());
422
423 bundleContext.registerService(
424 names.toArray(new String[names.size()]), bean, properties);
425 }
426
427 private void _registerServletContext(ServletContext servletContext) {
428 BundleContext bundleContext = _framework.getBundleContext();
429
430 Hashtable<String, Object> properties = new Hashtable<String, Object>();
431
432 properties.put(BEAN_ID, ServletContext.class.getName());
433 properties.put(ORIGINAL_BEAN, Boolean.TRUE);
434 properties.put(SERVICE_VENDOR, ReleaseInfo.getVendor());
435
436 bundleContext.registerService(
437 new String[] {ServletContext.class.getName()}, servletContext,
438 properties);
439 }
440
441 private void _setBundleStartLevel(long bundleId, int startLevel)
442 throws PortalException {
443
444 _checkPermission();
445
446 Bundle bundle = _getBundle(bundleId);
447
448 if (bundle == null) {
449 throw new ModuleFrameworkException("No bundle with ID " + bundleId);
450 }
451
452 BundleStartLevel bundleStartLevel = bundle.adapt(
453 BundleStartLevel.class);
454
455 bundleStartLevel.setStartLevel(startLevel);
456 }
457
458 private void _setupLogBridge() throws Exception {
459 BundleContext bundleContext = _framework.getBundleContext();
460
461 _logBridge = new LogBridge();
462
463 _logBridge.start(bundleContext);
464 }
465
466 private void _startBundle(long bundleId) throws PortalException {
467 _checkPermission();
468
469 Bundle bundle = _getBundle(bundleId);
470
471 if (bundle == null) {
472 throw new ModuleFrameworkException("No bundle with ID " + bundleId);
473 }
474
475 try {
476 bundle.start();
477 }
478 catch (BundleException be) {
479 _log.error(be, be);
480
481 throw new ModuleFrameworkException(be);
482 }
483 }
484
485 private void _startBundle(long bundleId, int options)
486 throws PortalException {
487
488 _checkPermission();
489
490 Bundle bundle = _getBundle(bundleId);
491
492 if (bundle == null) {
493 throw new ModuleFrameworkException("No bundle with ID " + bundleId);
494 }
495
496 try {
497 bundle.start(options);
498 }
499 catch (BundleException be) {
500 _log.error(be, be);
501
502 throw new ModuleFrameworkException(be);
503 }
504 }
505
506 private void _startFramework() throws Exception {
507 List<FrameworkFactory> frameworkFactories = ServiceLoader.load(
508 FrameworkFactory.class);
509
510 if (frameworkFactories.isEmpty()) {
511 return;
512 }
513
514 FrameworkFactory frameworkFactory = frameworkFactories.get(0);
515
516 Map<String, String> properties = _buildProperties();
517
518 _framework = frameworkFactory.newFramework(properties);
519
520 _framework.init();
521
522 _setupLogBridge();
523
524 _framework.start();
525 }
526
527 private void _startRuntime() throws Exception {
528 if (_framework == null) {
529 return;
530 }
531
532 FrameworkStartLevel frameworkStartLevel = _framework.adapt(
533 FrameworkStartLevel.class);
534
535 frameworkStartLevel.setStartLevel(
536 PropsValues.MODULE_FRAMEWORK_RUNTIME_START_LEVEL,
537 (FrameworkListener)null);
538 }
539
540 private void _stopBundle(long bundleId) throws PortalException {
541 _checkPermission();
542
543 Bundle bundle = _getBundle(bundleId);
544
545 if (bundle == null) {
546 throw new ModuleFrameworkException("No bundle with ID " + bundleId);
547 }
548
549 try {
550 bundle.stop();
551 }
552 catch (BundleException be) {
553 _log.error(be, be);
554
555 throw new ModuleFrameworkException(be);
556 }
557 }
558
559 private void _stopBundle(long bundleId, int options)
560 throws PortalException {
561
562 _checkPermission();
563
564 Bundle bundle = _getBundle(bundleId);
565
566 if (bundle == null) {
567 throw new ModuleFrameworkException("No bundle with ID " + bundleId);
568 }
569
570 try {
571 bundle.stop(options);
572 }
573 catch (BundleException be) {
574 _log.error(be, be);
575
576 throw new ModuleFrameworkException(be);
577 }
578 }
579
580 private void _stopFramework() throws Exception {
581 if (_framework == null) {
582 return;
583 }
584
585 BundleContext bundleContext = _framework.getBundleContext();
586
587 _logBridge.stop(bundleContext);
588
589 _framework.stop();
590 }
591
592 private void _stopRuntime() throws Exception {
593 if (_framework == null) {
594 return;
595 }
596
597 FrameworkStartLevel frameworkStartLevel = _framework.adapt(
598 FrameworkStartLevel.class);
599
600 frameworkStartLevel.setStartLevel(
601 PropsValues.MODULE_FRAMEWORK_BEGINNING_START_LEVEL,
602 (FrameworkListener)null);
603 }
604
605 private void _uninstallBundle(long bundleId) throws PortalException {
606 _checkPermission();
607
608 Bundle bundle = _getBundle(bundleId);
609
610 if (bundle == null) {
611 throw new ModuleFrameworkException("No bundle with ID " + bundleId);
612 }
613
614 try {
615 bundle.uninstall();
616 }
617 catch (BundleException be) {
618 _log.error(be, be);
619
620 throw new ModuleFrameworkException(be);
621 }
622 }
623
624 private void _updateBundle(long bundleId) throws PortalException {
625 _checkPermission();
626
627 Bundle bundle = _getBundle(bundleId);
628
629 if (bundle == null) {
630 throw new ModuleFrameworkException("No bundle with ID " + bundleId);
631 }
632
633 try {
634 bundle.update();
635 }
636 catch (BundleException be) {
637 _log.error(be, be);
638
639 throw new ModuleFrameworkException(be);
640 }
641 }
642
643 private void _updateBundle(long bundleId, InputStream inputStream)
644 throws PortalException {
645
646 _checkPermission();
647
648 Bundle bundle = _getBundle(bundleId);
649
650 if (bundle == null) {
651 throw new ModuleFrameworkException("No bundle with ID " + bundleId);
652 }
653
654 try {
655 bundle.update(inputStream);
656 }
657 catch (BundleException be) {
658 _log.error(be, be);
659
660 throw new ModuleFrameworkException(be);
661 }
662 }
663
664 private static Log _log = LogFactoryUtil.getLog(ModuleFrameworkUtil.class);
665
666 private static ModuleFrameworkUtil _instance = new ModuleFrameworkUtil();
667
668 private Framework _framework;
669 private LogBridge _logBridge;
670
671 }