All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.portal.test.rule.callback.InjectTestBag Maven / Gradle / Ivy

There is a newer version: 7.4.3.112-ga112
Show newest version
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.test.rule.callback;

import com.liferay.petra.reflect.ReflectionUtil;
import com.liferay.portal.kernel.test.util.TestPropsValues;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.test.rule.Inject;
import com.liferay.registry.Registry;
import com.liferay.registry.RegistryUtil;
import com.liferay.registry.ServiceReference;
import com.liferay.registry.ServiceTracker;
import com.liferay.registry.ServiceTrackerCustomizer;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;

/**
 * @author Preston Crary
 */
public class InjectTestBag {

	public InjectTestBag(Class testClass) throws Exception {
		this(testClass, null);
	}

	public InjectTestBag(Class testClass, Object target) throws Exception {
		_target = target;

		while (testClass != Object.class) {
			for (Field field : ReflectionUtil.getDeclaredFields(testClass)) {
				boolean staticField = Modifier.isStatic(field.getModifiers());

				if (((_target == null) == staticField) &&
					field.isAnnotationPresent(Inject.class)) {

					_fields.add(field);
				}
			}

			testClass = testClass.getSuperclass();
		}
	}

	public void injectFields() throws Exception {
		Registry registry = RegistryUtil.getRegistry();

		for (Field field : _fields) {
			Inject inject = field.getAnnotation(Inject.class);

			Class clazz = inject.type();

			if (clazz == Object.class) {
				clazz = field.getType();
			}

			ServiceReference serviceReference = _getServiceReference(
				registry, clazz, field, inject.filter(), inject.blocking());

			if (serviceReference != null) {
				_serviceReferences.add(serviceReference);

				Object service = registry.getService(serviceReference);

				field.set(_target, service);
			}
		}
	}

	public void resetFields() throws Exception {
		for (Field field : _fields) {
			field.set(_target, null);
		}

		Registry registry = RegistryUtil.getRegistry();

		for (ServiceReference serviceReference : _serviceReferences) {
			registry.ungetService(serviceReference);
		}
	}

	private  String _getFilterString(Class clazz, String filterString) {
		if (filterString.isEmpty()) {
			return "(objectClass=" + clazz.getName() + ")";
		}

		if ((clazz != Object.class) && !filterString.contains("objectClass")) {
			int index = filterString.indexOf('&');

			StringBundler sb = new StringBundler(5);

			if (index < 0) {
				sb.append("(&(objectClass=");
				sb.append(clazz.getName());
				sb.append(")(");
				sb.append(filterString);
				sb.append("))");
			}
			else {
				sb.append(filterString.substring(0, index));
				sb.append("&(objectClass=");
				sb.append(clazz.getName());
				sb.append(")");
				sb.append(filterString.substring(index + 1));
			}

			filterString = sb.toString();
		}

		return filterString;
	}

	private  ServiceReference _getServiceReference(
			Registry registry, Class clazz, Field field, String filterString,
			boolean blocking)
		throws Exception {

		String filterStringString = _getFilterString(clazz, filterString);

		ServiceReference serviceReference = _getServiceReference(
			registry, clazz, filterStringString);

		if ((serviceReference != null) || !blocking) {
			return serviceReference;
		}

		CountDownLatch countDownLatch = new CountDownLatch(1);

		AtomicReference> atomicReference =
			new AtomicReference<>();

		ServiceTracker serviceTracker = registry.trackServices(
			registry.getFilter(filterStringString),
			new ServiceTrackerCustomizer() {

				@Override
				public T addingService(ServiceReference serviceReference) {
					countDownLatch.countDown();

					ServiceTracker serviceTracker = atomicReference.get();

					serviceTracker.close();

					return null;
				}

				@Override
				public void modifiedService(
					ServiceReference serviceReference, T service) {
				}

				@Override
				public void removedService(
					ServiceReference serviceReference, T service) {
				}

			});

		atomicReference.set(serviceTracker);

		serviceTracker.open();

		int waitTime = 0;

		String className = clazz.getName();

		while (serviceReference == null) {
			waitTime += _SLEEP_TIME;

			if (waitTime >= TestPropsValues.CI_TEST_TIMEOUT_TIME) {
				throw new IllegalStateException(
					StringBundler.concat(
						"Timed out while waiting for service ", className, " ",
						filterString));
			}

			Class testClass = field.getDeclaringClass();

			System.out.println(
				StringBundler.concat(
					"Waiting for service ", className, " ", filterString,
					" for field ", testClass.getName(), ".", field.getName()));

			try {
				countDownLatch.await(_SLEEP_TIME, TimeUnit.MILLISECONDS);
			}
			catch (InterruptedException ie) {
				System.out.println(
					StringBundler.concat(
						"Stopped waiting for service ", className, " ",
						filterString, " for field ", testClass.getName(), ".",
						field.getName(), " due to interruption"));

				break;
			}

			serviceReference = _getServiceReference(
				registry, clazz, filterStringString);
		}

		return serviceReference;
	}

	private  ServiceReference _getServiceReference(
			Registry registry, Class clazz, String filterString)
		throws Exception {

		Collection> serviceReferences =
			registry.getServiceReferences(clazz, filterString);

		Stream> stream = serviceReferences.stream();

		Optional> optional = stream.findFirst();

		return optional.orElse(null);
	}

	private static final int _SLEEP_TIME = 2000;

	private final List _fields = new ArrayList<>();
	private final List> _serviceReferences =
		new ArrayList<>();
	private final Object _target;

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy