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 public void run() 043 { 044 invocation.proceed(); 045 } 046 }; 047 } 048 049 private class SimpleAdvice implements MethodAdvice 050 { 051 private final String description; 052 053 SimpleAdvice(String description) 054 { 055 this.description = description; 056 } 057 058 public void advise(MethodInvocation invocation) 059 { 060 tracker.run(description, toRunnable(invocation)); 061 } 062 } 063 064 private class FormattedAdvice implements MethodAdvice 065 { 066 private final String format; 067 068 FormattedAdvice(String format) 069 { 070 this.format = format; 071 } 072 073 public void advise(MethodInvocation invocation) 074 { 075 Object[] parameters = extractParameters(invocation); 076 077 String description = String.format(format, parameters); 078 079 tracker.run(description, toRunnable(invocation)); 080 } 081 082 private Object[] extractParameters(MethodInvocation invocation) 083 { 084 int count = invocation.getMethod().getParameterTypes().length; 085 086 Object[] result = new Object[count]; 087 088 for (int i = 0; i < count; i++) 089 { 090 result[i] = invocation.getParameter(i); 091 } 092 093 return result; 094 } 095 } 096 097 public void addOperationAdvice(MethodAdviceReceiver receiver) 098 { 099 for (Method m : receiver.getInterface().getMethods()) 100 { 101 102 Operation annotation = receiver.getMethodAnnotation(m, Operation.class); 103 104 if (annotation != null) 105 { 106 String value = annotation.value(); 107 108 receiver.adviseMethod(m, createAdvice(value)); 109 } 110 } 111 } 112 113 public MethodAdvice createAdvice(String description) 114 { 115 assert InternalUtils.isNonBlank(description); 116 117 if (description.contains("%")) 118 { 119 return new FormattedAdvice(description); 120 } 121 122 return new SimpleAdvice(description); 123 } 124}