refactor: Extension module

pull/1102/head
yanrongzhen 3 years ago
parent 64a7656dff
commit 9931c2834b

@ -21,8 +21,6 @@ import cn.hippo4j.common.toolkit.StringUtil;
/**
* Http media type.
*
* @author Rongzhen Yan
*/
public final class HttpMediaType {

@ -19,8 +19,6 @@ package cn.hippo4j.common.constant;
/**
* Http method constants.
*
* @author Rongzhen Yan
*/
public class HttpMethod {

@ -19,8 +19,6 @@ package cn.hippo4j.common.constant;
/**
* Http response code.
*
* @author Rongzhen Yan
*/
public class HttpResponseCode {

@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension;
/**
* Top level interface of extension-point.
*/
public interface IExtension {
}

@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension;
/**
* Top level interface of extension-point request obj.
*/
public interface IExtensionRequest {
}

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.annotation;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Component
public @interface Realization {
String code() default "DEFAULT_CODE";
String name() default "DEFAULT_NAME";
int order() default 0;
}

@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.config;
import cn.hippo4j.common.extension.IExtension;
import cn.hippo4j.common.extension.annotation.Realization;
import cn.hippo4j.common.extension.support.ExtensionRegistry;
import cn.hippo4j.common.toolkit.ClassUtil;
import org.springframework.beans.BeansException;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.util.Map;
/**
* Extension register bootstrap
*/
public class ExtensionRegisterBootstrap implements ApplicationContextAware, ApplicationRunner {
private ExtensionRegistry registry = ExtensionRegistry.getInstance();
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void run(ApplicationArguments args) throws Exception {
Map<String, Object> realizationBeanMap = applicationContext.getBeansWithAnnotation(Realization.class);
realizationBeanMap.values().forEach(
realization -> {
if (isInfrastructureClass(realization)) {
return;
}
if (realization instanceof IExtension) {
registry.register((IExtension) realization);
}
});
}
private boolean isInfrastructureClass(Object obj) {
return obj.getClass().isAssignableFrom(IExtension.class);
}
}

@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.reducer;
import cn.hippo4j.common.extension.IExtension;
import cn.hippo4j.common.extension.support.ReduceType;
import cn.hippo4j.common.toolkit.CollectionUtil;
import lombok.Getter;
import lombok.NonNull;
import java.util.Objects;
import java.util.function.Predicate;
/**
* All-match extension reduce policy.
*/
public class AllMatch<Element> extends Reducer<Element, Boolean> {
@Getter
private final Predicate<Element> predicate;
public AllMatch(@NonNull Predicate<Element> predicate) {
Objects.requireNonNull(predicate);
this.predicate = predicate;
setResult(true);
}
@Override
public Boolean reduce() {
if (CollectionUtil.isEmpty(extensionImplementations)) {
return false;
} else {
for (IExtension extensionImpl : extensionImplementations) {
if (!predicate.test(getCallback().apply(extensionImpl))) {
return false;
}
}
}
return true;
}
@Override
public ReduceType reducerType() {
return ReduceType.ALL;
}
}

@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.reducer;
import cn.hippo4j.common.extension.IExtension;
import cn.hippo4j.common.extension.support.ReduceType;
import cn.hippo4j.common.toolkit.CollectionUtil;
import lombok.Getter;
import lombok.NonNull;
import java.util.Objects;
import java.util.function.Predicate;
/**
* Any-match extension reduce policy.
*/
public class AnyMatch<Element> extends Reducer<Element, Boolean> {
@Getter
private final Predicate<Element> predicate;
public AnyMatch(@NonNull Predicate<Element> predicate) {
Objects.requireNonNull(predicate);
this.predicate = predicate;
this.setResult(false);
}
@Override
public Boolean reduce() {
if (CollectionUtil.isEmpty(extensionImplementations)) {
return false;
}
for (IExtension extension : extensionImplementations) {
if (predicate.test(getCallback().apply(extension))) {
return true;
}
}
return false;
}
@Override
public ReduceType reducerType() {
return ReduceType.FIRST;
}
}

@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.reducer;
import cn.hippo4j.common.extension.IExtension;
import cn.hippo4j.common.extension.support.ReduceType;
import lombok.NonNull;
import java.util.Objects;
import java.util.function.Predicate;
/**
* First-of extension reduce policy.
*/
public class FirstOf<Element> extends Reducer<Element, Element> {
private Predicate<Element> predicate;
public FirstOf(@NonNull Predicate<Element> predicate) {
Objects.requireNonNull(predicate);
this.predicate = predicate;
}
@Override
public ReduceType reducerType() {
return ReduceType.FIRST;
}
@Override
public Element reduce() {
for (IExtension extension : extensionImplementations) {
Element element = getCallback().apply(extension);
if (null == predicate || predicate.test(element)) {
return element;
}
}
return null;
}
}

@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.reducer;
import cn.hippo4j.common.extension.support.ReduceType;
import java.util.List;
import java.util.stream.Collectors;
public class None<Element> extends Reducer<Element, List<Element>> {
@Override
public ReduceType reducerType() {
return ReduceType.NONE;
}
@Override
public List<Element> reduce() {
return extensionImplementations.stream().map(getCallback()).collect(Collectors.toList());
}
}

@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.reducer;
import cn.hippo4j.common.extension.IExtension;
import cn.hippo4j.common.extension.IExtensionRequest;
import cn.hippo4j.common.extension.support.ExtensionCallback;
import cn.hippo4j.common.extension.support.ReduceType;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
public abstract class Reducer<Element, Result> {
@Getter
private boolean hasBreak = false;
@Getter
private Result result;
@Setter
protected IExtensionRequest request;
@Setter
protected List<IExtension> extensionImplementations;
@Setter
@Getter
private ExtensionCallback<IExtension, Element> callback;
public abstract Result reduce();
public boolean willBreak() {
return false;
}
public void setResult(Result result) {
this.result = result;
}
public abstract ReduceType reducerType();
public String reduceName() {
return this.getClass().getSimpleName();
}
}

@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.reducer;
import lombok.NonNull;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
@SuppressWarnings("all")
public class Reducers {
/**
* No reduce policy needed.
*
* @return None type reducer
*/
public static <E> Reducer<E, List<E>> none() {
return new None<>();
}
/**
* Build a FirstOf Reducer.
*
* @param predicate the condition predicate.
* @return FirstOf Policy Reducer.
*/
public static <E> Reducer<E, E> firstOf(@NonNull Predicate<E> predicate) {
return new FirstOf<>(predicate);
}
/**
* Build a FirstOf Not-null Reducer.
*
* @return FirstOf Not-null Policy Reducer.
*/
public static <E> Reducer<E, E> firstOfNotNull() {
return new FirstOf<>(Objects::nonNull);
}
/**
* Build a AnyMatch Reducer.
*
* @param predicate the condition predicate.
* @return AnyMatch Policy Reducer.
*/
public static <E> Reducer<E, Boolean> anyMatch(Predicate<E> predicate) {
return new AnyMatch<>(predicate);
}
/**
* Build a AllMatch Reducer
*
* @param predicate the condition predicate.
* @return AllMatch Policy Reducer.
*/
public static <E> Reducer<E, Boolean> allMatch(@NonNull Predicate<E> predicate) {
return new AllMatch<>(predicate);
}
}

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.support;
import cn.hippo4j.common.extension.config.ExtensionRegisterBootstrap;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ExtensionAutoConfiguration {
@Bean
public ExtensionRegisterBootstrap bootstrap() {
return new ExtensionRegisterBootstrap();
}
}

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.support;
import java.util.function.Function;
/**
* Callback function of extension invocation.
* @param <T>
* @param <R>
*/
@FunctionalInterface
public interface ExtensionCallback<T, R> extends Function<T, R> {
R apply(T extension);
}

@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.support;
import cn.hippo4j.common.extension.IExtension;
import cn.hippo4j.common.extension.reducer.Reducer;
import cn.hippo4j.common.extension.reducer.Reducers;
import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
import cn.hippo4j.common.toolkit.Assert;
import cn.hippo4j.common.toolkit.CollectionUtil;
import java.util.ArrayList;
import java.util.List;
/**
* Extension point invoker.
*
* Providing extension-point invocation ability that supports the use of reducing policy.
*/
public class ExtensionInvoker {
private static final ExtensionRegistry registry = ExtensionRegistry.getInstance();
public static <T extends IExtension, E> List<E> reduceExecute(Class<T> targetClz,
ExtensionCallback<T, E> callback) {
return reduceExecute(targetClz, callback, Reducers.none());
}
@SuppressWarnings("unchecked")
public static <T extends IExtension, E, R> R reduceExecute(Class<T> targetClz,
ExtensionCallback<T, E> callback,
Reducer<E, R> reducer) {
Assert.isTrue(IExtension.class.isAssignableFrom(targetClz),
"can not execute extension point. please implement base extension interface(" + IExtension.class.getName() + ") first.");
List<IExtension> implementations = registry.find(targetClz);
if (CollectionUtil.isEmpty(implementations)) {
implementations = new ArrayList<>(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(targetClz));
}
Assert.notEmpty(implementations, "can not find any extension realizations with interface: " + targetClz.getName());
reducer.setExtensionImplementations(implementations);
reducer.setCallback((ExtensionCallback<IExtension, E>) callback);
return reducer.reduce();
}
}

@ -0,0 +1,97 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.support;
import cn.hippo4j.common.extension.IExtension;
import cn.hippo4j.common.extension.annotation.Realization;
import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.common.toolkit.logtracing.LogMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.support.AopUtils;
import org.springframework.util.ClassUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Extension registry
*/
@Slf4j
public class ExtensionRegistry implements IExtensionRegistry {
private final Map<Class<? extends IExtension>, List<IExtension>> registry = new ConcurrentHashMap<>();
private static ExtensionRegistry INSTANCE;
private ExtensionRegistry() {
}
public static ExtensionRegistry getInstance() {
if (null == INSTANCE) {
synchronized (ExtensionRegistry.class) {
if (null == INSTANCE) {
INSTANCE = new ExtensionRegistry();
}
}
}
return INSTANCE;
}
@SuppressWarnings("unchecked")
@Override
public void register(IExtension implementation) {
Class<?> implClass = implementation.getClass();
if (AopUtils.isAopProxy(implClass)) {
implClass = ClassUtils.getUserClass(implClass);
}
Realization annotation = implClass.getAnnotation(Realization.class);
Class<?>[] interfaces = implClass.getInterfaces();
for (Class<?> intf : interfaces) {
if (IExtension.class.isAssignableFrom(intf)) {
this.register((Class<IExtension>) intf, implementation);
}
}
}
private void register(Class<? extends IExtension> extension, IExtension realization) {
if (!registry.containsKey(extension) || CollectionUtil.isEmpty(registry.get(extension))) {
List<IExtension> implementations = new ArrayList<>();
implementations.add(realization);
registry.put(extension, implementations);
} else {
if (registry.get(extension).contains(realization)) {
log.warn(LogMessage.getInstance()
.kv("realizationClassName", realization.getClass().getName())
.msg("Extension realization already registered, skip."));
}
List<IExtension> implementations = registry.get(extension);
implementations.add(realization);
registry.put(extension, implementations);
}
}
@Override
public List<IExtension> find(Class<? extends IExtension> extension) {
return registry.get(extension);
}
}

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.support;
import cn.hippo4j.common.extension.IExtension;
import java.util.List;
public interface IExtensionRegistry {
void register(IExtension realization);
List<IExtension> find(Class<? extends IExtension> extension);
}

@ -0,0 +1,26 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.support;
public enum ReduceType {
NONE,
ALL,
FIRST,
UNKNOWN
}

@ -38,6 +38,12 @@ public class Assert {
isTrue(expression, "[Assertion failed] - this expression must be true");
}
public static void isEmpty(Collection<?> collection, String message) {
if (!CollectionUtil.isEmpty(collection)) {
throw new IllegalArgumentException(message);
}
}
public static void isNull(Object object, String message) {
if (object != null) {
throw new IllegalArgumentException(message);

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.toolkit;
/**
* Class Util.
*/
public class ClassUtil {
/**
* get class loader
*
* @param clazz
* @return class loader
*/
public static ClassLoader getClassLoader(Class<?> clazz) {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back to system class loader...
}
if (cl == null) {
// No thread context class loader -> use class loader of this class.
cl = clazz.getClassLoader();
if (cl == null) {
// getClassLoader() returning null indicates the bootstrap ClassLoader
try {
cl = ClassLoader.getSystemClassLoader();
} catch (Throwable ex) {
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
}
}
}
return cl;
}
}

@ -43,8 +43,6 @@ import static cn.hippo4j.common.constant.HttpHeaderConstants.CONTENT_LENGTH;
/**
* Http request utilities.
*
* @author Rongzhen Yan
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)

@ -30,8 +30,6 @@ import java.util.Map;
/**
* Represents a client-side HTTP response with JDK implementation
*
* @author Rongzhen Yan
*/
public class JdkHttpClientResponse implements HttpClientResponse {

@ -28,8 +28,6 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* Log message.
*
* @author Rongzhen Yan
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LogMessage {

@ -0,0 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.hippo4j.common.extension.support.ExtensionAutoConfiguration

@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension;
import cn.hippo4j.common.extension.anymatch.AnyMatchExtImplA;
import cn.hippo4j.common.extension.anymatch.AnyMatchExtImplB;
import cn.hippo4j.common.extension.anymatch.IAnyMatchExtension;
import cn.hippo4j.common.extension.firstof.FirstOfExtImplA;
import cn.hippo4j.common.extension.firstof.FirstOfExtImplB;
import cn.hippo4j.common.extension.firstof.IFirstOfExtension;
import cn.hippo4j.common.extension.reducer.Reducers;
import cn.hippo4j.common.extension.spi.IOldSpi;
import cn.hippo4j.common.extension.support.ExtensionInvoker;
import cn.hippo4j.common.extension.support.ExtensionRegistry;
import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
import org.assertj.core.util.Lists;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import java.util.Objects;
import static org.junit.Assert.*;
public class ExtensionInvokerTest {
@Before
public void before() {
ExtensionRegistry.getInstance().register(new FirstOfExtImplA());
ExtensionRegistry.getInstance().register(new FirstOfExtImplB());
ExtensionRegistry.getInstance().register(new AnyMatchExtImplA());
ExtensionRegistry.getInstance().register(new AnyMatchExtImplB());
DynamicThreadPoolServiceLoader.register(IOldSpi.class);
}
@Test
public void test() {
Integer arg = 20;
// first-of
Integer res1 = ExtensionInvoker.reduceExecute(IFirstOfExtension.class, (ext) -> ext.foo(arg),
Reducers.firstOfNotNull());
assertEquals(arg, res1);
// any-match
Boolean res2 = ExtensionInvoker.reduceExecute(IAnyMatchExtension.class, (ext) -> ext.foo(arg),
Reducers.anyMatch(Objects::nonNull));
assertTrue(res2);
// none
List<Integer> res3 = ExtensionInvoker.reduceExecute(IFirstOfExtension.class, (ext) -> ext.foo(arg));
assertArrayEquals(res3.toArray(new Integer[0]), Lists.newArrayList(null, arg).toArray());
// all-match
Boolean res4 = ExtensionInvoker.reduceExecute(IAnyMatchExtension.class, (ext) -> ext.foo(arg),
Reducers.allMatch(Objects::nonNull));
assertTrue(res4);
}
@Test
public void test_spi_old() {
Boolean res1 = ExtensionInvoker.reduceExecute(IOldSpi.class, IOldSpi::foo, Reducers.firstOfNotNull());
assertTrue(res1);
}
}

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.anymatch;
import cn.hippo4j.common.extension.annotation.Realization;
@Realization
public class AnyMatchExtImplA implements IAnyMatchExtension {
@Override
public Integer foo(Integer arg) {
return arg > 0 ? arg : null;
}
}

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.anymatch;
import cn.hippo4j.common.extension.annotation.Realization;
@Realization
public class AnyMatchExtImplB implements IAnyMatchExtension {
@Override
public Integer foo(Integer arg) {
return arg > 0 ? arg : null;
}
}

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.anymatch;
import cn.hippo4j.common.extension.IExtension;
public interface IAnyMatchExtension extends IExtension {
Integer foo(Integer arg);
}

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.firstof;
import cn.hippo4j.common.extension.annotation.Realization;
@Realization
public class FirstOfExtImplA implements IFirstOfExtension {
@Override
public Integer foo(Integer arg) {
return null;
}
}

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.firstof;
import cn.hippo4j.common.extension.annotation.Realization;
@Realization
public class FirstOfExtImplB implements IFirstOfExtension {
@Override
public Integer foo(Integer arg) {
return arg;
}
}

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.firstof;
import cn.hippo4j.common.extension.IExtension;
public interface IFirstOfExtension extends IExtension {
Integer foo(Integer arg);
}

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.spi;
import cn.hippo4j.common.extension.IExtension;
public interface IOldSpi extends IExtension {
Boolean foo();
}

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.extension.spi;
public class IOldSpiImplA implements IOldSpi {
@Override
public Boolean foo() {
System.out.println(this.getClass().getName());
return true;
}
}
Loading…
Cancel
Save