001    /*
002     * $Id: SignatureHelper.java,v 1.6 2013/08/31 20:00:26 oboehm Exp $
003     *
004     * Copyright (c) 2009 by Oliver Boehm
005     *
006     * Licensed under the Apache License, Version 2.0 (the "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *   http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     *
018     * (c)reated 03.04.2009 by oliver (ob@aosd.de)
019     */
020    package patterntesting.runtime.util;
021    
022    import java.lang.reflect.*;
023    
024    import org.apache.commons.lang.StringUtils;
025    import org.aspectj.lang.*;
026    import org.aspectj.lang.reflect.*;
027    import org.slf4j.*;
028    
029    import patterntesting.runtime.util.reflect.*;
030    
031    /**
032     * The Class SignatureHelper.
033     *
034     * @author <a href="boehm@javatux.de">oliver</a>
035     * @since 03.04.2009
036     * @version $Revision: 1.6 $
037     */
038    public class SignatureHelper {
039    
040        private static final Logger log = LoggerFactory.getLogger(SignatureHelper.class);
041    
042        /** Utility class - no need to instantiate it */
043        private SignatureHelper() {}
044    
045        /**
046         * The difference to Signature.toString() is that in case of a methode
047         * or constructor the return type is not part of result.
048         *
049         * @param sig the sig
050         *
051         * @return the given signature as string
052         */
053        public static String getAsString(final Signature sig) {
054            try {
055                CodeSignature codeSig = (CodeSignature) sig;
056                String name = getAsString(sig.getDeclaringTypeName(), sig);
057                Class<?>[] params = codeSig.getParameterTypes();
058                return name + "(" + Converter.toShortString(params) + ")";
059            } catch (Exception e) {
060                log.debug("can't get '" + sig + "' as String", e);
061                return sig.toString();
062            }
063        }
064    
065        /**
066         * Gets the as string.
067         *
068         * @param type the type
069         * @param sig the sig
070         *
071         * @return the as string
072         */
073        public static String getAsString(final String type, final Signature sig) {
074            String name = sig.getName();
075            if (name.equals("<init>")) {
076                return "new " + type;
077            } else {
078                return type + "." + name;
079            }
080        }
081    
082        /**
083         * Gets the as signature.
084         *
085         * @param method the method
086         *
087         * @return the as signature
088         */
089        public static MethodSignature getAsSignature(final Method method) {
090            return new MethodSignatureImpl(method);
091        }
092    
093        /**
094         * Gets the as signature.
095         *
096         * @param ctor the ctor
097         *
098         * @return the as signature
099         */
100        public static ConstructorSignature getAsSignature(final Constructor<?> ctor) {
101            return new ConstructorSignatureImpl(ctor);
102        }
103    
104        /**
105         * Gets the as signature.
106         *
107         * @param label e.g. "java.lang.String.substring(int)" or
108         * "new java.lang.String()
109         *
110         * @return the given label as Signature
111         *
112         * @throws ClassNotFoundException the class not found exception
113         * @throws NoSuchMethodException the no such method exception
114         * @throws SecurityException the security exception
115         */
116        public static Signature getAsSignature(final String label)
117                throws ClassNotFoundException, SecurityException,
118                NoSuchMethodException {
119            if (label.startsWith("new ")) {
120                return getAsConstructorSignature(label);
121            }
122            String classDotMethod = StringUtils.substringBefore(label, "(");
123            String className = StringUtils.substringBeforeLast(classDotMethod, ".");
124            String methodName = StringUtils.substringAfterLast(classDotMethod, ".");
125            Class<?>[] params = getParameterTypes(label);
126            return getAsSignature(Class.forName(className), methodName, params);
127        }
128    
129        private static Signature getAsSignature(final Class<?> clazz, final String methodName,
130                final Class<?>[] parameterTypes) throws ClassNotFoundException, SecurityException,
131                NoSuchMethodException {
132            Method method = clazz.getMethod(methodName, parameterTypes);
133            return getAsSignature(method);
134        }
135    
136        private static ConstructorSignature getAsConstructorSignature(final String label)
137                throws ClassNotFoundException, SecurityException,
138                NoSuchMethodException {
139            String ctor = StringUtils.substringAfterLast(label, " ").trim();
140            String className = StringUtils.substringBefore(ctor, "(");
141            Class<?>[] params = getParameterTypes(label);
142            return getAsConstructorSignature(Class.forName(className), params);
143        }
144    
145        private static ConstructorSignature getAsConstructorSignature(final Class<?> clazz,
146                final Class<?>[] parameterTypes) throws ClassNotFoundException, SecurityException,
147                NoSuchMethodException {
148            Constructor<?> ctor = clazz.getConstructor(parameterTypes);
149            return getAsSignature(ctor);
150        }
151    
152        private static Class<?>[] getParameterTypes(final String label)
153                throws ClassNotFoundException {
154            String parameters = StringUtils.substringAfter(label, "(");
155            parameters = StringUtils.substringBefore(parameters, ")");
156            String[] params = StringUtils.split(parameters, ',');
157            Class<?>[] parameterTypes = new Class<?>[params.length];
158            for (int i = 0; i < params.length; i++) {
159                parameterTypes[i] = Class.forName(params[i].trim());
160            }
161            return parameterTypes;
162        }
163    
164        /**
165         * Returns true if the given signature is a {@link MethodSignature} and
166         * the return value is not of type 'void'.
167         *
168         * @param signature the signature
169         * @return true, if successful
170         * @since 1.3.1
171         */
172        public static boolean hasReturnType(final Signature signature) {
173            if (signature instanceof MethodSignature) {
174                MethodSignature methodSignature = (MethodSignature) signature;
175                if (methodSignature.getReturnType() != void.class) {
176                    return true;
177                }
178            }
179            return false;
180        }
181    
182    }