1 /*******************************************************************************
2  * Copyright (c) Feb. 2, 2019 Liferay, Inc.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *    Liferay, Inc. - initial API and implementation and/or initial
13  *                    documentation
14  ******************************************************************************/
15 
16 package org.eclipse.equinox.http.servlet.internal.context;
17 
18 import org.eclipse.equinox.http.servlet.internal.util.Const;
19 import org.osgi.framework.*;
20 
21 public final class ServiceHolder<S> implements Comparable<ServiceHolder<?>> {
22 
23 	final ServiceObjects<S> serviceObjects;
24 	final S service;
25 	final Bundle bundle;
26 	final long serviceId;
27 	final int serviceRanking;
28 	final ClassLoader legacyTCCL;
29 	private volatile boolean released = false;
30 
ServiceHolder(ServiceObjects<S> serviceObjects)31 	public ServiceHolder(ServiceObjects<S> serviceObjects) {
32 		this.serviceObjects = serviceObjects;
33 		this.bundle = serviceObjects.getServiceReference().getBundle();
34 		this.service = serviceObjects.getService();
35 		this.legacyTCCL = (ClassLoader)serviceObjects.getServiceReference().getProperty(Const.EQUINOX_LEGACY_TCCL_PROP);
36 		Long serviceIdProp = (Long)serviceObjects.getServiceReference().getProperty(Constants.SERVICE_ID);
37 		if (legacyTCCL != null) {
38 			// this is a legacy registration; use a negative id for the DTO
39 			serviceIdProp = -serviceIdProp;
40 		}
41 		this.serviceId = serviceIdProp;
42 		Object rankProp = serviceObjects.getServiceReference().getProperty(Constants.SERVICE_RANKING);
43 		this.serviceRanking = !Integer.class.isInstance(rankProp) ? 0 : ((Integer)rankProp).intValue();
44 	}
45 
ServiceHolder(S service, Bundle bundle, long serviceId, int serviceRanking, ClassLoader legacyTCCL)46 	public ServiceHolder(S service, Bundle bundle, long serviceId, int serviceRanking, ClassLoader legacyTCCL) {
47 		this.service = service;
48 		this.bundle = bundle;
49 		this.serviceObjects = null;
50 		this.serviceId = serviceId;
51 		this.serviceRanking = serviceRanking;
52 		this.legacyTCCL = legacyTCCL;
53 	}
54 
get()55 	public S get() {
56 		return service;
57 	}
58 
getBundle()59 	public Bundle getBundle() {
60 		return bundle;
61 	}
62 
getLegacyTCCL()63 	public ClassLoader getLegacyTCCL() {
64 		return legacyTCCL;
65 	}
66 
getServiceId()67 	public long getServiceId() {
68 		return serviceId;
69 	}
70 
release()71 	public void release() {
72 		if (!released && (serviceObjects != null) && (service != null)) {
73 			try {
74 				serviceObjects.ungetService(service);
75 			} catch (IllegalStateException e) {
76 				// this can happen if the whiteboard bundle is in the process of stopping
77 				// and the framework is in the middle of auto-unregistering any services
78 				// the bundle forgot to unregister on stop
79 			}
80 			finally {
81 				released = true;
82 			}
83 		}
84 	}
85 
getServiceReference()86 	public ServiceReference<S> getServiceReference() {
87 		return serviceObjects == null ? null : serviceObjects.getServiceReference();
88 	}
89 
90 	@Override
compareTo(ServiceHolder<?> o)91 	public int compareTo(ServiceHolder<?> o) {
92 		final int thisRanking = serviceRanking;
93 		final int otherRanking = o.serviceRanking;
94 		if (thisRanking != otherRanking) {
95 			if (thisRanking < otherRanking) {
96 				return 1;
97 			}
98 			return -1;
99 		}
100 		final long thisId = this.getServiceId();
101 		final long otherId = o.getServiceId();
102 		if (thisId == otherId) {
103 			return 0;
104 		}
105 		if (thisId < otherId) {
106 			return -1;
107 		}
108 		return 1;
109 	}
110 }