001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import java.util.ArrayList;
018    
019    /**
020     * @author Igor Spasic
021     */
022    public class MethodParameter {
023    
024            public MethodParameter(String name, String signatures, Class<?> type) {
025                    _name = name;
026                    _signatures = signatures;
027                    _type = type;
028            }
029    
030            public Class<?>[] getGenericTypes() throws ClassNotFoundException {
031                    if (_initialized) {
032                            return _genericTypes;
033                    }
034    
035                    String[] genericSignatures = _extractTopLevelGenericSignatures(
036                            _signatures);
037    
038                    if (genericSignatures == null) {
039                            _genericTypes = null;
040                    }
041                    else {
042                            _genericTypes = _loadGenericTypes(genericSignatures);
043                    }
044    
045                    _initialized = true;
046    
047                    return _genericTypes;
048            }
049    
050            public String getName() {
051                    return _name;
052            }
053    
054            public String getSignature() {
055                    return _signatures;
056            }
057    
058            public Class<?> getType() {
059                    return _type;
060            }
061    
062            private static String[] _extractTopLevelGenericSignatures(
063                    String signature) {
064    
065                    if (signature == null) {
066                            return null;
067                    }
068    
069                    int leftBracketIndex = signature.indexOf(CharPool.LESS_THAN);
070    
071                    if (leftBracketIndex == -1) {
072                            return null;
073                    }
074    
075                    int rightBracketIndex = signature.lastIndexOf(CharPool.GREATER_THAN);
076    
077                    if (rightBracketIndex == -1) {
078                            return null;
079                    }
080    
081                    String generics = signature.substring(
082                            leftBracketIndex + 1, rightBracketIndex);
083    
084                    StringBuilder sb = new StringBuilder(generics.length());
085    
086                    ArrayList<String> list = new ArrayList<String>();
087    
088                    int level = 0;
089    
090                    for (int i = 0; i < generics.length(); i++) {
091                            char c = generics.charAt(i);
092    
093                            if (c == '<') {
094                                    level++;
095                            }
096                            else if (c == '>') {
097                                    level--;
098                            }
099                            else if (level == 0) {
100                                    sb.append(c);
101    
102                                    if (c == ';') {
103                                            list.add(sb.toString());
104    
105                                            sb.setLength(0);
106                                    }
107                            }
108                    }
109    
110                    return list.toArray(new String[list.size()]);
111            }
112    
113            private static Class<?>[] _loadGenericTypes(String[] signatures)
114                    throws ClassNotFoundException {
115    
116                    Thread currentThread = Thread.currentThread();
117    
118                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
119    
120                    Class<?>[] types = new Class<?>[signatures.length];
121    
122                    for (int i = 0; i < signatures.length; i++) {
123                            String className = signatures[i];
124    
125                            char c = className.charAt(0);
126    
127                            if (c == 'B') {
128                                    types[i] = byte.class;
129                            }
130                            else if (c == 'C') {
131                                    types[i] = char.class;
132                            }
133                            else if (c == 'D') {
134                                    types[i] = double.class;
135                            }
136                            else if (c == 'F') {
137                                    types[i] = float.class;
138                            }
139                            else if (c == 'I') {
140                                    types[i] = int.class;
141                            }
142                            else if (c == 'J') {
143                                    types[i] = long.class;
144                            }
145                            else if (c == 'L') {
146                                    className = className.substring(1, className.length() - 1);
147                                    className = className.replace(CharPool.SLASH, CharPool.PERIOD);
148    
149                                    types[i] = contextClassLoader.loadClass(className);
150                            }
151                            else if (c == 'S') {
152                                    types[i] = short.class;
153                            }
154                            else if (c == 'Z') {
155                                    types[i] = boolean.class;
156                            }
157                            else if (c == 'V') {
158                                    types[i] = void.class;
159                            }
160                            else if (c == CharPool.OPEN_BRACKET) {
161                                    className = className.replace(CharPool.SLASH, CharPool.PERIOD);
162    
163                                    types[i] = contextClassLoader.loadClass(className);
164                            }
165                            else {
166                                    throw new ClassNotFoundException(className);
167                            }
168                    }
169    
170                    return types;
171            }
172    
173            private Class<?>[] _genericTypes;
174            private boolean _initialized;
175            private String _name;
176            private String _signatures;
177            private Class<?> _type;
178    
179    }