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