com.alibaba.schedulerx.worker.util.JobProcessorUtil Maven / Gradle / Ivy
package com.alibaba.schedulerx.worker.util;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import com.alibaba.schedulerx.common.MyClassLoader;
import com.alibaba.schedulerx.common.domain.JobType;
import com.alibaba.schedulerx.common.domain.K8sJobXAttrs;
import com.alibaba.schedulerx.common.util.JsonUtil;
import com.alibaba.schedulerx.common.util.ReflectionUtil;
import com.alibaba.schedulerx.worker.SchedulerxWorker;
import com.alibaba.schedulerx.worker.domain.JavaProcessorProfile;
import com.alibaba.schedulerx.worker.domain.JobContext;
import com.alibaba.schedulerx.worker.log.LogFactory;
import com.alibaba.schedulerx.worker.log.Logger;
import com.alibaba.schedulerx.worker.processor.JavaProcessor;
import com.alibaba.schedulerx.worker.processor.JobProcessor;
import com.alibaba.schedulerx.worker.processor.JobProcessorRepository;
import com.alibaba.schedulerx.worker.processor.ProcessorFactory;
import org.apache.commons.lang.StringUtils;
/**
*
* @author xiaomeng.hxm
*/
public class JobProcessorUtil {
private static final Logger LOGGER = LogFactory.getLogger(JobProcessorUtil.class);
public static JobProcessor getJobProcessor(JobContext context) throws Exception {
if (JobType.JAVA.getKey().equalsIgnoreCase(context.getJobType())) {
return JobProcessorUtil.getJavaProcessor(context.getContent());
} else if (JobType.XXLJOB.getKey().equalsIgnoreCase(context.getJobType())) {
return JobProcessorUtil.getXxlJobProcessor(context.getContent());
} else if (JobType.K8S.getKey().equalsIgnoreCase(context.getJobType())) {
K8sJobXAttrs xAttrs = JsonUtil.fromJson(context.getXAttrs(), K8sJobXAttrs.class);
return ProcessorFactory.create(context.getJobType() + "_" + xAttrs.getResource());
} else {
return ProcessorFactory.create(context);
}
}
/**
* 判断是否未指定类型
* @param className
* @param clazz
* @return
* @throws Exception
*/
public static Boolean checkJavaProcessor(String className, Class clazz) throws Exception {
int beanIdIndex = className.indexOf(":");
if (beanIdIndex > 0) {
className = className.substring(0, beanIdIndex);
}
Class> javaProcessorClass = null;
if (SchedulerxWorker.CUSTOMER_CLASS_LOADER == null) {
javaProcessorClass = clazz.getClassLoader().loadClass(className);
} else {
javaProcessorClass = SchedulerxWorker.CUSTOMER_CLASS_LOADER.loadClass(className);
}
return clazz.isAssignableFrom(javaProcessorClass);
}
public static JobProcessor getJavaProcessor(String content) throws Exception {
JobProcessor jobProcessor;
JavaProcessorProfile profile = JsonUtil.fromJson(content, JavaProcessorProfile.class);
//如果没有配置jarUrl,表示用户和用户应用在同一个进程中,直接从当前进程中获取
if (profile.getJarUrl() == null || profile.getJarUrl().isEmpty()) {
if (SpringContext.context != null) {
try {
jobProcessor = SpringContext.getBean(profile.getClassName(), SchedulerxWorker.CUSTOMER_CLASS_LOADER);
} catch (Exception e) {
LOGGER.warn("Spring bean not found.", e);
throw new RuntimeException("Spring bean not found. Can not found bean by Class="+profile.getClassName());
// jobProcessor = initSpringJobProcessor(profile.getClassName());
}
} else {
jobProcessor = ReflectionUtil.getInstanceByClassName(profile.getClassName(), SchedulerxWorker.CUSTOMER_CLASS_LOADER);
}
} else {
String jarUrl = profile.getJarUrl();
String jarFilePath = jarUrl;
@SuppressWarnings("resource")
MyClassLoader classLoader = new MyClassLoader(new URL[] {}, Thread.currentThread()
.getContextClassLoader());
if (jarUrl.startsWith("file:")) {
// jar包存在本地
jarFilePath = jarUrl.substring("file:".length());
} else if (jarUrl.startsWith("http:")) {
// 这里目前主要是支持oss上传
jarFilePath = FileDownloader.httpDownload(jarUrl);
} else if (jarUrl.startsWith("hdfs:")) {
//TODO 比如可以把jar包上传到hdfs上
}
File jarFile = new File(jarFilePath);
if (!jarFile.exists()) {
throw new IOException(jarFilePath + "is not existed!");
}
classLoader.addJar(jarFile.toURI().toURL());
if (SpringContext.context != null) {
jobProcessor = SpringContext.getBean(profile.getClassName(), classLoader);
} else {
Class> clazz = classLoader.loadClass(profile.getClassName());
jobProcessor = (JavaProcessor)ReflectionUtil.newInstanceWithoutCache(clazz);
}
}
return jobProcessor;
}
/**
* 兼容1.0用法,如果jobProcessor不是bean,反射filed去springcontext里获取同名的bean
* @param className
* @return
* @throws ClassNotFoundException
*/
private static JobProcessor initSpringJobProcessor(String className) throws Exception {
JobProcessor jobProcessor = ReflectionUtil.getInstanceByClassName(className, SchedulerxWorker.CUSTOMER_CLASS_LOADER);
/** 填充字段 */
Field[] fields = jobProcessor.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
String fieldName = fields[i].getName();
Object object = null;
try {
object = SpringContext.getBeanByName(fieldName);
} catch (Throwable e) {
LOGGER.warn("initSpringJobProcessor field not found"
+ ", jobProcessor:" + className
+ ", fieldName:" + fieldName, e);
}
if (object != null) {
try {
fields[i].set(jobProcessor, object);
} catch (Throwable e) {
LOGGER.error("initSpringJobProcessor field set error"
+ ", jobProcessor:" + className
+ ", fieldName:" + fieldName
+ ", object:" + object, e);
continue;
}
LOGGER.info("initSpringJobProcessor set field successfully"
+ ", jobProcessor:" + className
+ ", fieldName:" + fieldName);
}
}
return jobProcessor;
}
public static JobProcessor getXxlJobProcessor(String content) throws Exception {
JavaProcessorProfile profile = JsonUtil.fromJson(content, JavaProcessorProfile.class);
return JobProcessorRepository.loadJobProcessor(profile.getJobHandler());
}
/**
* 获取配置的类名
* @param content
* @return
* @throws Exception
*/
public static String getSimpleClassName(String content) {
JavaProcessorProfile profile = JsonUtil.fromJson(content, JavaProcessorProfile.class);
if (profile.getJarUrl() == null || profile.getJarUrl().isEmpty()) {
String className = profile.getClassName();
if (StringUtils.isNotBlank(className)) {
int beanIdIndex = className.indexOf(":");
if (beanIdIndex > 0) {
className = className.substring(0, beanIdIndex);
}
if (className.contains(".")) {
className = StringUtils.substringAfterLast(className, ".");
}
}
return className;
}
return null;
}
}