Package org.jberet.creation

Source Code of org.jberet.creation.SimpleArtifactFactory$SetFieldPrivilegedExceptionAction

/*
* Copyright (c) 2012-2013 Red Hat, Inc. and/or its affiliates.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Cheng Fang - Initial API and implementation
*/

package org.jberet.creation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.batch.api.BatchProperty;
import javax.batch.runtime.context.JobContext;
import javax.batch.runtime.context.StepContext;
import javax.inject.Inject;

import org.jberet.job.Properties;
import org.jberet.metadata.ApplicationMetaData;
import org.jberet.util.BatchUtil;

import static org.jberet.util.BatchLogger.LOGGER;

public final class SimpleArtifactFactory implements ArtifactFactory {
    public void initialize() throws Exception {
    }

    @Override
    public Class<?> getArtifactClass(String ref, ClassLoader classLoader, Map<?, ?> data) {
        ApplicationMetaData appData = (ApplicationMetaData) data.get(DataKey.APPLICATION_META_DATA);
        String className = appData.getClassNameForRef(ref);
        Class<?> cls;
        try {
            cls = classLoader.loadClass(className);
        } catch (ClassNotFoundException e) {
            throw LOGGER.failToCreateArtifact(e, ref);
        }
        return cls;
    }

    @Override
    public Object create(String ref, Class<?> cls, ClassLoader classLoader, Map<?, ?> data) throws Exception {
        if (cls == null) {
            cls = getArtifactClass(ref, classLoader, data);
        }
        Object obj = cls.newInstance();
        doInjection(obj, cls, classLoader, data);
        invokeAnnotatedLifecycleMethod(obj, cls, PostConstruct.class);
        return obj;
    }

    @Override
    public void destroy(Object instance) {
        if (instance != null) {
            try {
                invokeAnnotatedLifecycleMethod(instance, instance.getClass(), PreDestroy.class);
            } catch (Exception e) {
                LOGGER.failToDestroyArtifact(e, instance);
            }
        }
    }

    private void doInjection(final Object obj, Class<?> cls, final ClassLoader classLoader, final Map<?, ?> data) throws Exception {
        Properties batchProps = (Properties) data.get(DataKey.BATCH_PROPERTY);
        boolean hasBatchProps = batchProps != null && batchProps.getProperty().size() > 0;
        while (cls != null && cls != Object.class && !cls.getPackage().getName().startsWith("javax.batch")) {
            for (Field f : cls.getDeclaredFields()) {
                if (!f.isSynthetic()) {
                    Object fieldVal = null;
                    if (f.getAnnotation(Inject.class) != null) {
                        Class<?> fType = f.getType();
                        if (fType == JobContext.class) {
                            fieldVal = data.get(DataKey.JOB_CONTEXT);
                        } else if (fType == StepContext.class) {
                            //fieldVal may be null when StepContext was not stored in data map, as in job listeners
                            fieldVal = data.get(DataKey.STEP_CONTEXT);
                        } else if (hasBatchProps) {
                            BatchProperty batchPropertyAnn = f.getAnnotation(BatchProperty.class);
                            if (batchPropertyAnn != null) {
                                String propName = batchPropertyAnn.name();
                                if (propName.equals("")) {
                                    propName = f.getName();
                                }
                                String sVal = BatchUtil.getBatchProperty(batchProps, propName);
                                if (sVal != null) {
                                    if (sVal.length() == 0) {
                                        fieldVal = null;
                                    } else if (!fType.isAssignableFrom(String.class)) {
                                        fieldVal = ValueConverter.convertFieldValue(sVal, fType, f, classLoader);
                                    } else {
                                        fieldVal = sVal;
                                    }
                                }
                            }
                        }
                        if (fieldVal != null) {
                            doInjection(obj, f, fieldVal);
                        }
                    }
                }
            }
            cls = cls.getSuperclass();
        }
    }

    private void invokeAnnotatedLifecycleMethod(final Object obj, Class<?> cls, final Class<? extends Annotation> annCls) throws Exception{
        List<Method> lifecycleMethods = new ArrayList<Method>();
        while (cls != null && cls != Object.class && !cls.getPackage().getName().startsWith("javax.batch")) {
            Method[] methods = cls.getDeclaredMethods();
            for (Method m : methods) {
                if (m.getAnnotation(annCls) != null) {  //the lifecyle annotation is present
                    int modifiers = m.getModifiers();
                    String mName = m.getName();
                    if (Modifier.isPrivate(modifiers)) {
                        lifecycleMethods.add(m);
                    } else {
                        boolean alreadyAdded = false;
                        for (Method lm : lifecycleMethods) {
                            if (lm.getName().equals(mName)) {
                                if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) {
                                    alreadyAdded = true;
                                    break;
                                } else { // package default access
                                    if (m.getDeclaringClass().getPackage().getName().equals(lm.getDeclaringClass().getPackage().getName())) {
                                        alreadyAdded = true;
                                        break;
                                    }
                                    //there can be multiple methods of the same name in lifecycleMethods, some are its
                                    //super method and some are not.  So need to continue.
                                }
                            }
                        }
                        if (!alreadyAdded) {
                            lifecycleMethods.add(m);
                        }
                    }
                }
            }
            cls = cls.getSuperclass();
        }
        if (annCls == PostConstruct.class) {
            Collections.reverse(lifecycleMethods);
        }
        for(Method m : lifecycleMethods) {
            if (System.getSecurityManager() == null) {
                if (!m.isAccessible()) {
                    m.setAccessible(true);
                }
                m.invoke(obj);
            } else {
                AccessController.doPrivileged(new InvokeMethodPrivilegedExceptionAction(m, obj));
            }
        }
    }

    private void doInjection(final Object obj, final Field field, final Object val) throws Exception {
        if (System.getSecurityManager() == null) {
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            field.set(obj, val);
        } else {
            AccessController.doPrivileged(new SetFieldPrivilegedExceptionAction(field, obj, val));
        }
    }

    private static class SetFieldPrivilegedExceptionAction implements java.security.PrivilegedExceptionAction<Void> {
        private final Field field;
        private final Object obj;
        private final Object val;

        public SetFieldPrivilegedExceptionAction(Field field, Object obj, Object val) {
            this.field = field;
            this.obj = obj;
            this.val = val;
        }

        @Override
        public Void run() throws Exception {
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            field.set(obj, val);
            return null;
        }
    }

    private static class InvokeMethodPrivilegedExceptionAction implements PrivilegedExceptionAction<Object> {
        private final Method method;
        private final Object obj;

        public InvokeMethodPrivilegedExceptionAction(Method method, Object obj) {
            this.method = method;
            this.obj = obj;
        }

        @Override
        public Object run() throws Exception {
            if (!method.isAccessible()) {
                method.setAccessible(true);
            }
            return method.invoke(obj);
        }
    }
}
TOP

Related Classes of org.jberet.creation.SimpleArtifactFactory$SetFieldPrivilegedExceptionAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
ew');