001// Copyright 2012 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.ioc.internal.services; 016 017import org.apache.tapestry5.ioc.MethodAdviceReceiver; 018import org.apache.tapestry5.ioc.OperationTracker; 019import org.apache.tapestry5.ioc.annotations.Operation; 020import org.apache.tapestry5.ioc.annotations.PreventServiceDecoration; 021import org.apache.tapestry5.ioc.internal.util.InternalUtils; 022import org.apache.tapestry5.ioc.services.OperationAdvisor; 023import org.apache.tapestry5.plastic.MethodAdvice; 024import org.apache.tapestry5.plastic.MethodInvocation; 025 026import java.lang.reflect.Method; 027 028@PreventServiceDecoration 029public class OperationAdvisorImpl implements OperationAdvisor 030{ 031 private final OperationTracker tracker; 032 033 public OperationAdvisorImpl(OperationTracker tracker) 034 { 035 this.tracker = tracker; 036 } 037 038 private Runnable toRunnable(final MethodInvocation invocation) 039 { 040 return new Runnable() 041 { 042 @Override 043 public void run() 044 { 045 invocation.proceed(); 046 } 047 }; 048 } 049 050 private class SimpleAdvice implements MethodAdvice 051 { 052 private final String description; 053 054 SimpleAdvice(String description) 055 { 056 this.description = description; 057 } 058 059 @Override 060 public void advise(MethodInvocation invocation) 061 { 062 tracker.run(description, toRunnable(invocation)); 063 } 064 } 065 066 private class FormattedAdvice implements MethodAdvice 067 { 068 private final String format; 069 070 FormattedAdvice(String format) 071 { 072 this.format = format; 073 } 074 075 @Override 076 public void advise(MethodInvocation invocation) 077 { 078 Object[] parameters = extractParameters(invocation); 079 080 String description = String.format(format, parameters); 081 082 tracker.run(description, toRunnable(invocation)); 083 } 084 085 private Object[] extractParameters(MethodInvocation invocation) 086 { 087 int count = invocation.getMethod().getParameterTypes().length; 088 089 Object[] result = new Object[count]; 090 091 for (int i = 0; i < count; i++) 092 { 093 result[i] = invocation.getParameter(i); 094 } 095 096 return result; 097 } 098 } 099 100 @Override 101 public void addOperationAdvice(MethodAdviceReceiver receiver) 102 { 103 for (Method m : receiver.getInterface().getMethods()) 104 { 105 106 Operation annotation = receiver.getMethodAnnotation(m, Operation.class); 107 108 if (annotation != null) 109 { 110 String value = annotation.value(); 111 112 receiver.adviseMethod(m, createAdvice(value)); 113 } 114 } 115 } 116 117 @Override 118 public MethodAdvice createAdvice(String description) 119 { 120 assert InternalUtils.isNonBlank(description); 121 122 if (description.contains("%")) 123 { 124 return new FormattedAdvice(description); 125 } 126 127 return new SimpleAdvice(description); 128 } 129}