001    /**
002     * Copyright (c) 2000-2012 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.jsonwebservice.action;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceAction;
019    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionMapping;
020    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionsManagerUtil;
021    import com.liferay.portal.kernel.util.MethodParameter;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    
026    import java.io.Serializable;
027    
028    import java.lang.reflect.Method;
029    
030    import java.util.ArrayList;
031    import java.util.Arrays;
032    import java.util.Date;
033    import java.util.LinkedHashMap;
034    import java.util.List;
035    import java.util.Locale;
036    import java.util.Map;
037    
038    import javax.servlet.http.HttpServletRequest;
039    
040    import jodd.util.Wildcard;
041    
042    /**
043     * @author Igor Spasic
044     */
045    public class JSONWebServiceDiscoverAction implements JSONWebServiceAction {
046    
047            public JSONWebServiceDiscoverAction(HttpServletRequest request) {
048                    _basePath = request.getServletPath();
049                    _baseURL = request.getRequestURL().toString();
050                    _contextPath = request.getContextPath();
051    
052                    String discover = request.getParameter("discover");
053    
054                    _discover = StringUtil.split(discover);
055            }
056    
057            public JSONWebServiceActionMapping getJSONWebServiceActionMapping() {
058                    return null;
059            }
060    
061            public Object invoke() throws Exception {
062                    Map<String, Object> resultsMap = new LinkedHashMap<String, Object>();
063    
064                    Map<String, Object> jsonWebServiceActionMappingMaps =
065                            _buildJsonWebServiceActionMappingMaps();
066    
067                    resultsMap.put("actions", jsonWebServiceActionMappingMaps);
068    
069                    resultsMap.put("context", _contextPath);
070                    resultsMap.put("basePath", _basePath);
071                    resultsMap.put("baseURL", _baseURL);
072    
073                    if (_discover.length > 0) {
074                            resultsMap.put("discover", Arrays.toString(_discover));
075                    }
076    
077                    return resultsMap;
078            }
079    
080            private Map<String, Object> _buildJsonWebServiceActionMappingMaps()
081                    throws PortalException {
082    
083                    List<JSONWebServiceActionMapping> jsonWebServiceActionMappingMaps =
084                            JSONWebServiceActionsManagerUtil.getJSONWebServiceActionMappings(
085                                    _contextPath);
086    
087                    Map<String, Object> jsonWebServiceActionMappingsMap =
088                            new LinkedHashMap<String, Object>(
089                                    jsonWebServiceActionMappingMaps.size());
090    
091                    for (JSONWebServiceActionMapping jsonWebServiceActionMapping :
092                                    jsonWebServiceActionMappingMaps) {
093    
094                            String path = jsonWebServiceActionMapping.getPath();
095    
096                            if (!_isAcceptPath(path)) {
097                                    continue;
098                            }
099    
100                            Map<String, Object> jsonWebServiceActionMappingMap =
101                                    new LinkedHashMap<String, Object>();
102    
103                            jsonWebServiceActionMappingMap.put(
104                                    "method", jsonWebServiceActionMapping.getMethod());
105    
106                            MethodParameter[] methodParameters =
107                                    jsonWebServiceActionMapping.getMethodParameters();
108    
109                            Map<String, Object> parameterMap =
110                                    new LinkedHashMap<String, Object>(methodParameters.length);
111    
112                            for (MethodParameter methodParameter : methodParameters) {
113                                    Class<?>[] genericTypes = null;
114    
115                                    try {
116                                            genericTypes = methodParameter.getGenericTypes();
117                                    }
118                                    catch (ClassNotFoundException e) {
119                                            throw new PortalException(e);
120                                    }
121    
122                                    parameterMap.put(
123                                            methodParameter.getName(),
124                                            _formatType(methodParameter.getType(), genericTypes));
125                            }
126    
127                            jsonWebServiceActionMappingMap.put("parameters", parameterMap);
128    
129                            jsonWebServiceActionMappingMap.put("path", path);
130    
131                            Method actionMethod = jsonWebServiceActionMapping.getActionMethod();
132    
133                            jsonWebServiceActionMappingMap.put(
134                                    "response", _formatType(actionMethod.getReturnType(), null));
135    
136                            jsonWebServiceActionMappingsMap.put(
137                                    path, jsonWebServiceActionMappingMap);
138                    }
139    
140                    return jsonWebServiceActionMappingsMap;
141            }
142    
143            private String _formatType(Class<?> type, Class<?>[] genericTypes) {
144                    if (type.isArray()) {
145                            Class<?> componentType = type.getComponentType();
146    
147                            return _formatType(componentType, genericTypes) + "[]";
148                    }
149    
150                    if (type.isPrimitive()) {
151                            return type.getSimpleName();
152                    }
153                    else if (type.equals(Date.class)) {
154                            return "long";
155                    }
156                    else if (type.equals(Locale.class) || type.equals(String.class)) {
157                            return "string";
158                    }
159                    else if (type.equals(Object.class) || type.equals(Serializable.class)) {
160                            return "object";
161                    }
162    
163                    String typeName = type.getName();
164    
165                    if (type.equals(List.class)) {
166                            typeName = "list";
167                    }
168                    else if (type.equals(Map.class)) {
169                            typeName = "map";
170                    }
171                    else {
172                            _types.add(type);
173                    }
174    
175                    if (genericTypes == null) {
176                            return "object<" + typeName + ">";
177                    }
178    
179                    StringBundler sb = new StringBundler(genericTypes.length * 2 + 1);
180    
181                    sb.append(StringPool.LESS_THAN);
182    
183                    for (int i = 0; i < genericTypes.length; i++) {
184                            Class<?> genericType = genericTypes[i];
185    
186                            if (i != 0) {
187                                    sb.append(StringPool.COMMA);
188                            }
189    
190                            sb.append(_formatType(genericType, null));
191                    }
192    
193                    sb.append(StringPool.GREATER_THAN);
194    
195                    return typeName + sb.toString();
196            }
197    
198            private boolean _isAcceptPath(String path) {
199                    if (_discover.length == 0) {
200                            return true;
201                    }
202    
203                    if (Wildcard.matchOne(path, _discover) != -1) {
204                            return true;
205                    }
206                    else {
207                            return false;
208                    }
209            }
210    
211            private String _basePath;
212            private String _baseURL;
213            private String _contextPath;
214            private String[] _discover;
215            private List<Class<?>> _types = new ArrayList<Class<?>>();
216    
217    }