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