Skip to content
This repository was archived by the owner on Jan 15, 2020. It is now read-only.

Commit 3ab744d

Browse files
committed
CLOUDSTACK-1795: implement custom AOP to fully support legacy CloudStack AOP semantcis
Signed-off-by: Chip Childers <chip.childers@gmail.com>
1 parent 95011d6 commit 3ab744d

20 files changed

Lines changed: 383 additions & 196 deletions

client/tomcatconf/applicationContext.xml.in

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,18 @@
3535
<!--
3636
@DB support
3737
-->
38-
<aop:config>
39-
<aop:aspect id="dbContextBuilder" ref="transactionContextBuilder">
40-
<aop:pointcut id="captureAnyMethod"
41-
expression="execution(* *(..))"
42-
/>
43-
44-
<aop:around pointcut-ref="captureAnyMethod" method="AroundAnyMethod"/>
45-
</aop:aspect>
46-
47-
<aop:aspect id="actionEventInterceptorAspect" ref="actionEventInterceptor">
48-
<aop:pointcut id="captureEventMethod"
49-
expression="execution(* *(..)) and @annotation(com.cloud.event.ActionEvent)"
50-
/>
51-
52-
<aop:around pointcut-ref="captureEventMethod" method="AroundAnyMethod"/>
53-
</aop:aspect>
54-
</aop:config>
55-
5638
<bean id="transactionContextBuilder" class="com.cloud.utils.db.TransactionContextBuilder" />
5739
<bean id="actionEventInterceptor" class="com.cloud.event.ActionEventInterceptor" />
5840

41+
<bean id="instantiatePostProcessor" class="com.cloud.utils.component.ComponentInstantiationPostProcessor">
42+
<property name="Interceptors">
43+
<list>
44+
<ref bean="transactionContextBuilder" />
45+
<ref bean="actionEventInterceptor" />
46+
</list>
47+
</property>
48+
</bean>
49+
5950
<!--
6051
RPC/Async/EventBus
6152
-->

server/src/com/cloud/api/ApiDispatcher.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,7 @@ public void dispatch(BaseCmd cmd, Map<String, String> params) throws Exception {
138138
UserContext ctx = UserContext.current();
139139
ctx.setAccountId(cmd.getEntityOwnerId());
140140

141-
BaseCmd realCmdObj = ComponentContext.getTargetObject(cmd);
142-
if (realCmdObj instanceof BaseAsyncCmd) {
141+
if (cmd instanceof BaseAsyncCmd) {
143142

144143
BaseAsyncCmd asyncCmd = (BaseAsyncCmd) cmd;
145144
String startEventId = params.get("ctxStartEventId");
@@ -171,8 +170,6 @@ public static void processParameters(BaseCmd cmd, Map<String, String> params) {
171170
Map<Object, AccessType> entitiesToAccess = new HashMap<Object, AccessType>();
172171
Map<String, Object> unpackedParams = cmd.unpackParams(params);
173172

174-
cmd = ComponentContext.getTargetObject(cmd);
175-
176173
if (cmd instanceof BaseListCmd) {
177174
Object pageSizeObj = unpackedParams.get(ApiConstants.PAGE_SIZE);
178175
Long pageSize = null;

server/src/com/cloud/api/ApiServer.java

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -388,16 +388,15 @@ private String queueCommand(BaseCmd cmdObj, Map<String, String> params) throws E
388388
Long callerUserId = ctx.getCallerUserId();
389389
Account caller = ctx.getCaller();
390390

391-
BaseCmd realCmdObj = ComponentContext.getTargetObject(cmdObj);
392391

393392
// Queue command based on Cmd super class:
394393
// BaseCmd: cmd is dispatched to ApiDispatcher, executed, serialized and returned.
395394
// BaseAsyncCreateCmd: cmd params are processed and create() is called, then same workflow as BaseAsyncCmd.
396395
// BaseAsyncCmd: cmd is processed and submitted as an AsyncJob, job related info is serialized and returned.
397-
if (realCmdObj instanceof BaseAsyncCmd) {
396+
if (cmdObj instanceof BaseAsyncCmd) {
398397
Long objectId = null;
399398
String objectUuid = null;
400-
if (realCmdObj instanceof BaseAsyncCreateCmd) {
399+
if (cmdObj instanceof BaseAsyncCreateCmd) {
401400
BaseAsyncCreateCmd createCmd = (BaseAsyncCreateCmd) cmdObj;
402401
_dispatcher.dispatchCreateCmd(createCmd, params);
403402
objectId = createCmd.getEntityId();
@@ -433,7 +432,7 @@ private String queueCommand(BaseCmd cmdObj, Map<String, String> params) throws E
433432
ctx.setAccountId(asyncCmd.getEntityOwnerId());
434433

435434
Long instanceId = (objectId == null) ? asyncCmd.getInstanceId() : objectId;
436-
AsyncJobVO job = new AsyncJobVO(callerUserId, caller.getId(), realCmdObj.getClass().getName(),
435+
AsyncJobVO job = new AsyncJobVO(callerUserId, caller.getId(), cmdObj.getClass().getName(),
437436
ApiGsonHelper.getBuilder().create().toJson(params), instanceId, asyncCmd.getInstanceType());
438437

439438
long jobId = _asyncMgr.submitAsyncJob(job);
@@ -457,22 +456,22 @@ private String queueCommand(BaseCmd cmdObj, Map<String, String> params) throws E
457456
// if the command is of the listXXXCommand, we will need to also return the
458457
// the job id and status if possible
459458
// For those listXXXCommand which we have already created DB views, this step is not needed since async job is joined in their db views.
460-
if (realCmdObj instanceof BaseListCmd && !(realCmdObj instanceof ListVMsCmd) && !(realCmdObj instanceof ListRoutersCmd)
461-
&& !(realCmdObj instanceof ListSecurityGroupsCmd)
462-
&& !(realCmdObj instanceof ListTagsCmd)
463-
&& !(realCmdObj instanceof ListEventsCmd)
464-
&& !(realCmdObj instanceof ListVMGroupsCmd)
465-
&& !(realCmdObj instanceof ListProjectsCmd)
466-
&& !(realCmdObj instanceof ListProjectAccountsCmd)
467-
&& !(realCmdObj instanceof ListProjectInvitationsCmd)
468-
&& !(realCmdObj instanceof ListHostsCmd)
469-
&& !(realCmdObj instanceof ListVolumesCmd)
470-
&& !(realCmdObj instanceof ListUsersCmd)
471-
&& !(realCmdObj instanceof ListAccountsCmd)
472-
&& !(realCmdObj instanceof ListStoragePoolsCmd)
473-
&& !(realCmdObj instanceof ListDiskOfferingsCmd)
474-
&& !(realCmdObj instanceof ListServiceOfferingsCmd)
475-
&& !(realCmdObj instanceof ListZonesByCmd)
459+
if (cmdObj instanceof BaseListCmd && !(cmdObj instanceof ListVMsCmd) && !(cmdObj instanceof ListRoutersCmd)
460+
&& !(cmdObj instanceof ListSecurityGroupsCmd)
461+
&& !(cmdObj instanceof ListTagsCmd)
462+
&& !(cmdObj instanceof ListEventsCmd)
463+
&& !(cmdObj instanceof ListVMGroupsCmd)
464+
&& !(cmdObj instanceof ListProjectsCmd)
465+
&& !(cmdObj instanceof ListProjectAccountsCmd)
466+
&& !(cmdObj instanceof ListProjectInvitationsCmd)
467+
&& !(cmdObj instanceof ListHostsCmd)
468+
&& !(cmdObj instanceof ListVolumesCmd)
469+
&& !(cmdObj instanceof ListUsersCmd)
470+
&& !(cmdObj instanceof ListAccountsCmd)
471+
&& !(cmdObj instanceof ListStoragePoolsCmd)
472+
&& !(cmdObj instanceof ListDiskOfferingsCmd)
473+
&& !(cmdObj instanceof ListServiceOfferingsCmd)
474+
&& !(cmdObj instanceof ListZonesByCmd)
476475
) {
477476
buildAsyncListResponse((BaseListCmd) cmdObj, caller);
478477
}

server/src/com/cloud/cluster/ClusterManagerImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,11 @@ private String handleScheduleHostScanTaskCommand(ScheduleHostScanTaskCommand cmd
365365

366366
try {
367367
// schedule a scan task immediately
368-
if (ComponentContext.getTargetObject(_agentMgr) instanceof ClusteredAgentManagerImpl) {
368+
if (_agentMgr instanceof ClusteredAgentManagerImpl) {
369369
if (s_logger.isDebugEnabled()) {
370370
s_logger.debug("Received notification as part of addHost command to start a host scan task");
371371
}
372-
ClusteredAgentManagerImpl clusteredAgentMgr = (ClusteredAgentManagerImpl)ComponentContext.getTargetObject(_agentMgr);
372+
ClusteredAgentManagerImpl clusteredAgentMgr = (ClusteredAgentManagerImpl)_agentMgr;
373373
clusteredAgentMgr.scheduleHostScanTask();
374374
}
375375
} catch (Exception e) {

server/src/com/cloud/event/ActionEventInterceptor.java

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,55 +16,22 @@
1616
// under the License.
1717
package com.cloud.event;
1818

19-
import java.lang.reflect.AnnotatedElement;
2019
import java.lang.reflect.Method;
2120

2221
import org.apache.log4j.Logger;
23-
import org.aspectj.lang.ProceedingJoinPoint;
24-
import org.aspectj.lang.reflect.MethodSignature;
2522

2623
import com.cloud.user.UserContext;
27-
import com.cloud.utils.component.ComponentMethodProxyCache;
24+
import com.cloud.utils.component.ComponentMethodInterceptor;
2825

29-
public class ActionEventInterceptor {
26+
public class ActionEventInterceptor implements ComponentMethodInterceptor {
3027
private static final Logger s_logger = Logger.getLogger(ActionEventInterceptor.class);
3128

3229
public ActionEventInterceptor() {
3330
}
3431

35-
public Object AroundAnyMethod(ProceedingJoinPoint call) throws Throwable {
36-
MethodSignature methodSignature = (MethodSignature)call.getSignature();
37-
38-
// Note: AOP for ActionEvent is triggered annotation, no need to check the annotation on method again
39-
Method targetMethod = ComponentMethodProxyCache.getTargetMethod(
40-
methodSignature.getMethod(), call.getTarget());
41-
42-
if(targetMethod != null) {
43-
EventVO event = interceptStart(targetMethod);
44-
45-
boolean success = true;
46-
Object ret = null;
47-
try {
48-
ret = call.proceed();
49-
} catch (Throwable e) {
50-
success = false;
51-
interceptException(targetMethod, event);
52-
throw e;
53-
} finally {
54-
if(success){
55-
interceptComplete(targetMethod, event);
56-
}
57-
}
58-
return ret;
59-
} else {
60-
s_logger.error("Unable to find the proxied method behind. Method: " + methodSignature.getMethod().getName());
61-
}
62-
return call.proceed();
63-
}
64-
65-
public EventVO interceptStart(AnnotatedElement element) {
32+
@Override
33+
public Object interceptStart(Method method, Object target) {
6634
EventVO event = null;
67-
Method method = (Method)element;
6835
ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
6936
if (actionEvent != null) {
7037
boolean async = actionEvent.async();
@@ -83,8 +50,8 @@ public EventVO interceptStart(AnnotatedElement element) {
8350
return event;
8451
}
8552

86-
public void interceptComplete(AnnotatedElement element, EventVO event) {
87-
Method method = (Method)element;
53+
@Override
54+
public void interceptComplete(Method method, Object target, Object event) {
8855
ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
8956
if (actionEvent != null) {
9057
UserContext ctx = UserContext.current();
@@ -105,8 +72,8 @@ public void interceptComplete(AnnotatedElement element, EventVO event) {
10572
}
10673
}
10774

108-
public void interceptException(AnnotatedElement element, EventVO event) {
109-
Method method = (Method)element;
75+
@Override
76+
public void interceptException(Method method, Object target, Object event) {
11077
ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
11178
if (actionEvent != null) {
11279
UserContext ctx = UserContext.current();
@@ -126,7 +93,8 @@ public void interceptException(AnnotatedElement element, EventVO event) {
12693
}
12794
}
12895

129-
private boolean needToIntercept(Method method) {
96+
@Override
97+
public boolean needToIntercept(Method method) {
13098
ActionEvent actionEvent = method.getAnnotation(ActionEvent.class);
13199
if (actionEvent != null) {
132100
return true;

server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,7 @@ protected IpDeployer getIpDeployerForInlineMode(Network network) {
11131113
}
11141114

11151115
NetworkElement element = _networkModel.getElementImplementingProvider(providers.get(0).getName());
1116-
if (!(ComponentContext.getTargetObject(element) instanceof IpDeployer)) {
1116+
if (!(element instanceof IpDeployer)) {
11171117
s_logger.error("The firewall provider for network " + network.getName() + " don't have ability to deploy IP address!");
11181118
return null;
11191119
}

server/src/com/cloud/network/NetworkManagerImpl.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -611,10 +611,10 @@ public boolean applyIpAssociations(Network network, boolean rulesRevoked, boolea
611611
}
612612
IpDeployer deployer = null;
613613
NetworkElement element = _networkModel.getElementImplementingProvider(provider.getName());
614-
if (!(ComponentContext.getTargetObject(element) instanceof IpDeployingRequester)) {
614+
if (!(element instanceof IpDeployingRequester)) {
615615
throw new CloudRuntimeException("Element " + element + " is not a IpDeployingRequester!");
616616
}
617-
deployer = ((IpDeployingRequester)ComponentContext.getTargetObject(element)).getIpDeployer(network);
617+
deployer = ((IpDeployingRequester)element).getIpDeployer(network);
618618
if (deployer == null) {
619619
throw new CloudRuntimeException("Fail to get ip deployer for element: " + element);
620620
}
@@ -1594,13 +1594,13 @@ protected void prepareElement(NetworkElement element, NetworkVO network,
15941594
if (vmProfile.getType() == Type.User && element.getProvider() != null) {
15951595
if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Dhcp) &&
15961596
_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dhcp, element.getProvider()) &&
1597-
(ComponentContext.getTargetObject(element) instanceof DhcpServiceProvider)) {
1597+
element instanceof DhcpServiceProvider) {
15981598
DhcpServiceProvider sp = (DhcpServiceProvider) element;
15991599
sp.addDhcpEntry(network, profile, vmProfile, dest, context);
16001600
}
16011601
if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.UserData) &&
16021602
_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.UserData, element.getProvider()) &&
1603-
(ComponentContext.getTargetObject(element) instanceof UserDataServiceProvider)) {
1603+
element instanceof UserDataServiceProvider) {
16041604
UserDataServiceProvider sp = (UserDataServiceProvider) element;
16051605
sp.addPasswordAndUserdata(network, profile, vmProfile, dest, context);
16061606
}
@@ -3678,15 +3678,15 @@ protected NetworkElement getElementForServiceInNetwork(Network network, Service
36783678
@Override
36793679
public StaticNatServiceProvider getStaticNatProviderForNetwork(Network network) {
36803680
NetworkElement element = getElementForServiceInNetwork(network, Service.StaticNat);
3681-
assert ComponentContext.getTargetObject(element) instanceof StaticNatServiceProvider;
3682-
return (StaticNatServiceProvider)ComponentContext.getTargetObject(element);
3681+
assert element instanceof StaticNatServiceProvider;
3682+
return (StaticNatServiceProvider)element;
36833683
}
36843684

36853685
@Override
36863686
public LoadBalancingServiceProvider getLoadBalancingProviderForNetwork(Network network) {
36873687
NetworkElement element = getElementForServiceInNetwork(network, Service.Lb);
3688-
assert ComponentContext.getTargetObject(element) instanceof LoadBalancingServiceProvider;
3689-
return ( LoadBalancingServiceProvider)ComponentContext.getTargetObject(element);
3688+
assert element instanceof LoadBalancingServiceProvider;
3689+
return (LoadBalancingServiceProvider)element;
36903690
}
36913691
@Override
36923692
public boolean isNetworkInlineMode(Network network) {

server/src/com/cloud/network/NetworkModelImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,9 @@ public boolean canIpUsedForService(PublicIp publicIp, Service service, Long netw
404404
Network network = _networksDao.findById(networkId);
405405
NetworkElement oldElement = getElementImplementingProvider(oldProvider.getName());
406406
NetworkElement newElement = getElementImplementingProvider(newProvider.getName());
407-
if (ComponentContext.getTargetObject(oldElement) instanceof IpDeployingRequester && ComponentContext.getTargetObject(newElement) instanceof IpDeployingRequester) {
408-
IpDeployer oldIpDeployer = ((IpDeployingRequester)ComponentContext.getTargetObject(oldElement)).getIpDeployer(network);
409-
IpDeployer newIpDeployer = ((IpDeployingRequester)ComponentContext.getTargetObject(newElement)).getIpDeployer(network);
407+
if (oldElement instanceof IpDeployingRequester && newElement instanceof IpDeployingRequester) {
408+
IpDeployer oldIpDeployer = ((IpDeployingRequester)oldElement).getIpDeployer(network);
409+
IpDeployer newIpDeployer = ((IpDeployingRequester)newElement).getIpDeployer(network);
410410
if (!oldIpDeployer.getProvider().getName().equals(newIpDeployer.getProvider().getName())) {
411411
throw new InvalidParameterException("There would be multiple providers for IP " + publicIp.getAddress() + "!");
412412
}

server/src/com/cloud/server/StatsCollector.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import com.cloud.storage.dao.VolumeDao;
6666
import com.cloud.storage.secondary.SecondaryStorageVmManager;
6767
import com.cloud.utils.NumbersUtil;
68+
import com.cloud.utils.component.ComponentMethodInterceptable;
6869
import com.cloud.utils.concurrency.NamedThreadFactory;
6970
import com.cloud.utils.db.SearchCriteria;
7071
import com.cloud.vm.UserVmManager;
@@ -77,7 +78,7 @@
7778
*
7879
*/
7980
@Component
80-
public class StatsCollector {
81+
public class StatsCollector implements ComponentMethodInterceptable {
8182
public static final Logger s_logger = Logger.getLogger(StatsCollector.class.getName());
8283

8384
private static StatsCollector s_instance = null;

utils/src/com/cloud/utils/component/AdapterBase.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import java.util.List;
2020

2121
// Typical Adapter implementation.
22-
public class AdapterBase extends ComponentLifecycleBase implements Adapter {
22+
public class AdapterBase extends ComponentLifecycleBase implements Adapter, ComponentMethodInterceptable {
2323

2424
public AdapterBase() {
2525
// set default run level for adapter components
@@ -29,7 +29,7 @@ public AdapterBase() {
2929
public static <T extends Adapter> T getAdapterByName(List<T> adapters, String name) {
3030
for(T adapter : adapters) {
3131
if(adapter.getName() != null && adapter.getName().equalsIgnoreCase(name))
32-
return ComponentContext.getTargetObject(adapter);
32+
return adapter;
3333
}
3434
return null;
3535
}

0 commit comments

Comments
 (0)