com.liferay.portal.jsonwebservice.JSONWebServiceConfigurator.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.portal.jsonwebservice.JSONWebServiceConfigurator.java

Source

/**
 * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.jsonwebservice;

import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.jsonwebservice.JSONWebService;
import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionsManagerUtil;
import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceMode;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.SetUtil;
import com.liferay.portal.kernel.util.StreamUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portal.util.PropsValues;

import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import java.net.URL;
import java.net.URLDecoder;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import jodd.io.findfile.ClassFinder;
import jodd.io.findfile.FindFile;
import jodd.io.findfile.WildcardFindFile;

import jodd.util.ClassLoaderUtil;

import org.apache.commons.lang.time.StopWatch;

import org.objectweb.asm.ClassReader;

/**
 * @author Igor Spasic
 */
public class JSONWebServiceConfigurator extends ClassFinder {

    public JSONWebServiceConfigurator(String servletContextPath) {
        setIncludedJars("*portal-impl.jar", "*portal-service.jar", "*_wl_cls_gen.jar", "*-portlet-service*.jar");

        _servletContextPath = servletContextPath;
    }

    public void clean() {
        int count = JSONWebServiceActionsManagerUtil.unregisterJSONWebServiceActions(_servletContextPath);

        _registeredActionsCount -= count;

        if (_log.isDebugEnabled()) {
            if (count != 0) {
                _log.debug("Removed " + count + " existing JSON Web Service actions that belonged to "
                        + _servletContextPath);
            }
        }
    }

    public void configure(ClassLoader classLoader) throws PortalException, SystemException {

        File[] classPathFiles = null;

        if (classLoader != null) {
            URL servicePropertiesURL = classLoader.getResource("service.properties");

            String servicePropertiesPath = null;

            try {
                servicePropertiesPath = URLDecoder.decode(servicePropertiesURL.getPath(), StringPool.UTF8);
            } catch (UnsupportedEncodingException uee) {
                throw new SystemException(uee);
            }

            File classPathFile = null;

            File libDir = null;

            int pos = servicePropertiesPath.indexOf("_wl_cls_gen.jar!");

            if (pos != -1) {
                String wlClsGenJarPath = servicePropertiesPath.substring(0, pos + 15);

                classPathFile = new File(wlClsGenJarPath);

                libDir = new File(classPathFile.getParent());
            } else {
                File servicePropertiesFile = new File(servicePropertiesPath);

                classPathFile = servicePropertiesFile.getParentFile();

                libDir = new File(classPathFile.getParent(), "lib");
            }

            classPathFiles = new File[2];

            classPathFiles[0] = classPathFile;

            FindFile findFile = new WildcardFindFile("*-portlet-service*.jar");

            findFile.searchPath(libDir);

            classPathFiles[1] = findFile.nextFile();

            if (classPathFiles[1] == null) {
                File classesDir = new File(libDir.getParent(), "classes");

                classPathFiles[1] = classesDir;
            }
        } else {
            Thread currentThread = Thread.currentThread();

            classLoader = currentThread.getContextClassLoader();

            File portalImplJarFile = new File(PortalUtil.getPortalLibDir(), "portal-impl.jar");
            File portalServiceJarFile = new File(PortalUtil.getGlobalLibDir(), "portal-service.jar");

            if (portalImplJarFile.exists() && portalServiceJarFile.exists()) {
                classPathFiles = new File[2];

                classPathFiles[0] = portalImplJarFile;
                classPathFiles[1] = portalServiceJarFile;
            } else {
                classPathFiles = ClassLoaderUtil.getDefaultClasspath(classLoader);
            }
        }

        _classLoader = classLoader;

        _configure(classPathFiles);
    }

    @Override
    protected void onEntry(EntryData entryData) throws Exception {
        String className = entryData.getName();

        if (className.endsWith("Service") || className.endsWith("ServiceImpl")) {

            InputStream inputStream = entryData.openInputStream();

            if (!isTypeSignatureInUse(inputStream, _jsonWebServiceAnnotationBytes)) {

                return;
            }

            if (!entryData.isArchive()) {
                StreamUtil.cleanUp(inputStream);

                ClassReader classReader = new ClassReader(entryData.openInputStream());

                JSONWebServiceClassVisitor jsonWebServiceClassVisitor = new JSONWebServiceClassVisitor();

                try {
                    classReader.accept(jsonWebServiceClassVisitor, 0);
                } catch (Exception e) {
                    return;
                }

                if (!className.equals(jsonWebServiceClassVisitor.getClassName())) {

                    return;
                }
            }

            _onJSONWebServiceClass(className);
        }
    }

    private void _configure(File... classPathFiles) throws PortalException {
        StopWatch stopWatch = null;

        if (_log.isDebugEnabled()) {
            _log.debug("Configure JSON web service actions");

            stopWatch = new StopWatch();

            stopWatch.start();
        }

        try {
            scanPaths(classPathFiles);
        } catch (Exception e) {
            throw new PortalException(e.getMessage(), e);
        }

        if (_log.isDebugEnabled()) {
            _log.debug("Configured " + _registeredActionsCount + " actions in " + stopWatch.getTime() + " ms");
        }
    }

    private boolean _hasAnnotatedServiceImpl(String className) {
        StringBundler implClassName = new StringBundler(4);

        int pos = className.lastIndexOf(CharPool.PERIOD);

        implClassName.append(className.substring(0, pos));
        implClassName.append(".impl");
        implClassName.append(className.substring(pos));
        implClassName.append("Impl");

        Class<?> implClass = null;

        try {
            implClass = _classLoader.loadClass(implClassName.toString());
        } catch (ClassNotFoundException cnfe) {
            return false;
        }

        if (implClass.getAnnotation(JSONWebService.class) != null) {
            return true;
        } else {
            return false;
        }
    }

    private boolean _isJSONWebServiceClass(Class<?> clazz) {
        if (!clazz.isAnonymousClass() && !clazz.isArray() && !clazz.isEnum() && !clazz.isLocalClass()
                && !clazz.isPrimitive() && !(clazz.isMemberClass() ^ Modifier.isStatic(clazz.getModifiers()))) {

            return true;
        }

        return false;
    }

    private Class<?> _loadUtilClass(Class<?> implementationClass) throws ClassNotFoundException {

        Class<?> utilClass = _utilClasses.get(implementationClass);

        if (utilClass != null) {
            return utilClass;
        }

        String utilClassName = implementationClass.getName();

        if (utilClassName.endsWith("Impl")) {
            utilClassName = utilClassName.substring(0, utilClassName.length() - 4);

        }

        utilClassName += "Util";

        utilClassName = StringUtil.replace(utilClassName, ".impl.", ".");

        utilClass = _classLoader.loadClass(utilClassName);

        _utilClasses.put(implementationClass, utilClass);

        return utilClass;
    }

    private void _onJSONWebServiceClass(String className) throws Exception {
        Class<?> actionClass = _classLoader.loadClass(className);

        if (!_isJSONWebServiceClass(actionClass)) {
            return;
        }

        if (actionClass.isInterface() && _hasAnnotatedServiceImpl(className)) {
            return;
        }

        JSONWebService classAnnotation = actionClass.getAnnotation(JSONWebService.class);

        JSONWebServiceMode classAnnotationMode = JSONWebServiceMode.MANUAL;

        if (classAnnotation != null) {
            classAnnotationMode = classAnnotation.mode();
        }

        Method[] methods = actionClass.getMethods();

        for (Method method : methods) {
            Class<?> methodDeclaringClass = method.getDeclaringClass();

            if (!methodDeclaringClass.equals(actionClass)) {
                continue;
            }

            boolean registerMethod = false;

            JSONWebService methodAnnotation = method.getAnnotation(JSONWebService.class);

            if (classAnnotationMode.equals(JSONWebServiceMode.AUTO)) {
                registerMethod = true;

                if (methodAnnotation != null) {
                    JSONWebServiceMode methodAnnotationMode = methodAnnotation.mode();

                    if (methodAnnotationMode.equals(JSONWebServiceMode.IGNORE)) {

                        registerMethod = false;
                    }
                }
            } else {
                if (methodAnnotation != null) {
                    JSONWebServiceMode methodAnnotationMode = methodAnnotation.mode();

                    if (!methodAnnotationMode.equals(JSONWebServiceMode.IGNORE)) {

                        registerMethod = true;
                    }
                }
            }

            if (registerMethod) {
                _registerJSONWebServiceAction(actionClass, method);
            }
        }
    }

    private void _registerJSONWebServiceAction(Class<?> implementationClass, Method method) throws Exception {

        String path = _jsonWebServiceMappingResolver.resolvePath(implementationClass, method);

        String httpMethod = _jsonWebServiceMappingResolver.resolveHttpMethod(method);

        if (_invalidHttpMethods.contains(httpMethod)) {
            return;
        }

        Class<?> utilClass = _loadUtilClass(implementationClass);

        try {
            method = utilClass.getMethod(method.getName(), method.getParameterTypes());
        } catch (NoSuchMethodException nsme) {
            return;
        }

        JSONWebServiceActionsManagerUtil.registerJSONWebServiceAction(_servletContextPath,
                method.getDeclaringClass(), method, path, httpMethod);

        _registeredActionsCount++;
    }

    private static Log _log = LogFactoryUtil.getLog(JSONWebServiceConfigurator.class);

    private ClassLoader _classLoader;
    private Set<String> _invalidHttpMethods = SetUtil
            .fromArray(PropsValues.JSONWS_WEB_SERVICE_INVALID_HTTP_METHODS);
    private byte[] _jsonWebServiceAnnotationBytes = getTypeSignatureBytes(JSONWebService.class);
    private JSONWebServiceMappingResolver _jsonWebServiceMappingResolver = new JSONWebServiceMappingResolver();
    private int _registeredActionsCount;
    private String _servletContextPath;
    private Map<Class<?>, Class<?>> _utilClasses = new HashMap<Class<?>, Class<?>>();

}