-
Notifications
You must be signed in to change notification settings - Fork 283
/
DynamicServiceHandler.java
160 lines (146 loc) · 6.1 KB
/
DynamicServiceHandler.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.weld.environment.osgi.impl.extension.beans;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Set;
import javassist.util.proxy.MethodHandler;
import org.jboss.weld.environment.osgi.api.annotation.Filter;
import org.jboss.weld.environment.osgi.impl.extension.OSGiServiceBean;
import org.jboss.weld.environment.osgi.impl.extension.service.WeldOSGiExtension;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Handler for proxy used by {@link OSGiServiceBean}. Dynamicaly lookup for a
* matching OSGi service at method call. Automaticaly release the services after
* each use.
* <p/>
* @author Mathieu ANCELIN - SERLI (mathieu.ancelin@serli.com)
* @author Matthieu CLOCHARD - SERLI (matthieu.clochard@serli.com)
*/
public class DynamicServiceHandler implements InvocationHandler, MethodHandler {
private static Logger logger =
LoggerFactory.getLogger(DynamicServiceHandler.class);
private final BundleContext ctx;
private final String name;
private Filter filter;
/*private final ServiceTracker tracker;*/
private final long timeout;
private Set<Annotation> qualifiers;
boolean stored = false;
public DynamicServiceHandler(BundleContext ctx,
String name,
Filter filter,
Set<Annotation> qualifiers,
long timeout) {
logger.trace("Entering DynamicServiceHandler : "
+ "DynamicServiceHandler() with parameters {} | {} | {} | {}",
new Object[] {name, filter, qualifiers, timeout});
this.ctx = ctx;
this.name = name;
this.filter = filter;
this.timeout = timeout;
this.qualifiers = qualifiers;
/* ServiceTracker usage, currently fails
try {
if (filter != null && filter.value() != null && filter.value().length() > 0) {
this.tracker = new ServiceTracker(bundle.getBundleContext(),
bundle.getBundleContext().createFilter(
"(&(objectClass=" + name + ")" + filter.value() + ")"),
null);
} else {
this.tracker = new ServiceTracker(bundle.getBundleContext(), name, null);
}
} catch (Exception e) {
logger.error("Unable to create the DynamicServiceHandler.",e);
throw new RuntimeException(e);
}
this.tracker.open();
*/
logger.debug("New DynamicServiceHandler constructed {}", this);
}
/*public void closeHandler() {
this.tracker.close();
}*/
public void setStored(boolean stored) {
this.stored = stored;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
logger.trace("Call on the DynamicServiceHandler {} for method {}",
this,
method);
BundleContext previousContext = WeldOSGiExtension.setCurrentContext(ctx);
Bundle previousBundle = WeldOSGiExtension.setCurrentBundle(ctx.getBundle());
//intercept HashCode method when the handler is not allready registered
//map.put() need a correct hashCode() method to use
//see OSGiServiceBean
if (!stored && method.getName().equals("hashCode")) {
int result = name.hashCode();
result = 31 * result + filter.value().hashCode();
result = 31 * result + qualifiers.hashCode();
result = 31 * result + (int) timeout;
return result;
}
ServiceReference reference = null;
if (filter != null
&& filter.value() != null
&& filter.value().length() > 0) {
ServiceReference[] refs =
ctx.getServiceReferences(name, filter.value());
if (refs != null && refs.length > 0) {
reference = refs[0];
}
}
else {
reference = ctx.getServiceReference(name);
}
if (reference == null) {
throw new IllegalStateException("Can't call service "
+ name
+ ". No matching service found.");
}
Object instanceToUse = ctx.getService(reference);
try {
return method.invoke(instanceToUse, args);
}
catch(Throwable t) {
throw new RuntimeException(t);
}
finally {
ctx.ungetService(reference);
WeldOSGiExtension.setCurrentBundle(previousBundle);
WeldOSGiExtension.setCurrentContext(previousContext);
}
/*Object instanceToUse = this.tracker.waitForService(timeout);
try {
return method.invoke(instanceToUse, args);
} catch(Throwable t) {
logger.error("Unable to find a matching service for {} with filter {} due to {}", new Object[] {name, filter.value(), t});
throw new RuntimeException(t);
} finally {
WeldOSGiExtension.currentBundle.remove();
}*/
}
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
return invoke(self, thisMethod, args);
}
}