zhouping
5 years ago
52 changed files with 1236 additions and 583 deletions
@ -1,116 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2006-2018 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed 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 com.fr.third.org.objenesis; |
|
||||||
|
|
||||||
import com.fr.third.org.objenesis.instantiator.ObjectInstantiator; |
|
||||||
import com.fr.third.org.objenesis.strategy.InstantiatorStrategy; |
|
||||||
|
|
||||||
import java.util.Map; |
|
||||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||||
|
|
||||||
/** |
|
||||||
* Base class to extend if you want to have a class providing your own default strategy. Can also be |
|
||||||
* instantiated directly. |
|
||||||
* |
|
||||||
* @author Henri Tremblay |
|
||||||
*/ |
|
||||||
public class ObjenesisBase implements Objenesis { |
|
||||||
|
|
||||||
/** |
|
||||||
* Strategy used by this Objenesi implementation to create classes |
|
||||||
*/ |
|
||||||
protected final InstantiatorStrategy strategy; |
|
||||||
|
|
||||||
/** |
|
||||||
* Strategy cache. Key = Class, Value = InstantiatorStrategy |
|
||||||
*/ |
|
||||||
protected Map<Class, ObjectInstantiator<?>> cache; |
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor allowing to pick a strategy and using cache |
|
||||||
* |
|
||||||
* @param strategy Strategy to use |
|
||||||
*/ |
|
||||||
public ObjenesisBase(InstantiatorStrategy strategy) { |
|
||||||
this(strategy, true); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Flexible constructor allowing to pick the strategy and if caching should be used |
|
||||||
* |
|
||||||
* @param strategy Strategy to use |
|
||||||
* @param useCache If {@link ObjectInstantiator}s should be cached |
|
||||||
*/ |
|
||||||
public ObjenesisBase(InstantiatorStrategy strategy, boolean useCache) { |
|
||||||
if (strategy == null) { |
|
||||||
throw new IllegalArgumentException("A strategy can't be null"); |
|
||||||
} |
|
||||||
this.strategy = strategy; |
|
||||||
this.cache = useCache ? new ConcurrentHashMap<Class, ObjectInstantiator<?>>() : null; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() { |
|
||||||
return getClass().getName() + " using " + strategy.getClass().getName() |
|
||||||
+ (cache == null ? " without" : " with") + " caching"; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Will create a new object without any constructor being called |
|
||||||
* |
|
||||||
* @param clazz Class to instantiate |
|
||||||
* @return New instance of clazz |
|
||||||
*/ |
|
||||||
public <T> T newInstance(Class<T> clazz) { |
|
||||||
return getInstantiatorOf(clazz).newInstance(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Will pick the best instantiator for the provided class. If you need to create a lot of |
|
||||||
* instances from the same class, it is way more efficient to create them from the same |
|
||||||
* ObjectInstantiator than calling {@link #newInstance(Class)}. |
|
||||||
* |
|
||||||
* @param clazz Class to instantiate |
|
||||||
* @return Instantiator dedicated to the class
|
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) { |
|
||||||
if (clazz.isPrimitive()) { |
|
||||||
throw new IllegalArgumentException("Primitive types can't be instantiated in Java"); |
|
||||||
} |
|
||||||
if (cache == null) { |
|
||||||
return strategy.newInstantiatorOf(clazz); |
|
||||||
} |
|
||||||
ObjectInstantiator<?> instantiator = cache.get(clazz); |
|
||||||
if (instantiator == null) { |
|
||||||
ObjectInstantiator<?> newInstantiator = strategy.newInstantiatorOf(clazz); |
|
||||||
instantiator = putIfAbsent(clazz, newInstantiator); |
|
||||||
if (instantiator == null) { |
|
||||||
instantiator = newInstantiator; |
|
||||||
} |
|
||||||
} |
|
||||||
return (ObjectInstantiator<T>) instantiator; |
|
||||||
} |
|
||||||
|
|
||||||
private ObjectInstantiator<?> putIfAbsent(Class key, ObjectInstantiator<?> newInstantiator) { |
|
||||||
|
|
||||||
ObjectInstantiator<?> instantiator = cache.get(key); |
|
||||||
if (instantiator == null) { |
|
||||||
instantiator = cache.put(key, newInstantiator); |
|
||||||
} |
|
||||||
return instantiator; |
|
||||||
} |
|
||||||
} |
|
@ -1,78 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2006-2018 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed 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 com.fr.third.org.objenesis.instantiator.util; |
|
||||||
|
|
||||||
import com.fr.third.org.objenesis.ObjenesisException; |
|
||||||
|
|
||||||
/** |
|
||||||
* Helper class for to play with classes. It contains everything needed to play with a class
|
|
||||||
* except the dodgy (Java 8) code you will find in {@link ClassDefinitionUtils}. |
|
||||||
* |
|
||||||
* @author Henri Tremblay |
|
||||||
*/ |
|
||||||
public final class ClassUtils { |
|
||||||
|
|
||||||
private ClassUtils() { } |
|
||||||
|
|
||||||
/** |
|
||||||
* Will convert a class name to its name in the class definition format (e.g {@code com.fr.third.org.objenesis.EmptyClass} |
|
||||||
* becomes {@code org/objenesis/EmptyClass}) |
|
||||||
* |
|
||||||
* @param className full class name including the package
|
|
||||||
* @return the internal name |
|
||||||
*/ |
|
||||||
public static String classNameToInternalClassName(String className) { |
|
||||||
return className.replace('.', '/'); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Will convert a class name to its class loader resource name (e.g {@code com.fr.third.org.objenesis.EmptyClass} |
|
||||||
* becomes {@code org/objenesis/EmptyClass.class}) |
|
||||||
* |
|
||||||
* @param className full class name including the package
|
|
||||||
* @return the resource name |
|
||||||
*/ |
|
||||||
public static String classNameToResource(String className) { |
|
||||||
return classNameToInternalClassName(className) + ".class"; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Check if this class already exists in the class loader and return it if it does |
|
||||||
* |
|
||||||
* @param <T> type of the class returned |
|
||||||
* @param classLoader Class loader where to search the class
|
|
||||||
* @param className Class name with full path |
|
||||||
* @return the class if it already exists or null |
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public static <T> Class<T> getExistingClass(ClassLoader classLoader, String className) { |
|
||||||
try { |
|
||||||
return (Class<T>) Class.forName(className, true, classLoader); |
|
||||||
} |
|
||||||
catch (ClassNotFoundException e) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings("deprecation") |
|
||||||
public static <T> T newInstance(Class<T> clazz) { |
|
||||||
try { |
|
||||||
return clazz.newInstance(); |
|
||||||
} catch (Exception e) { |
|
||||||
throw new ObjenesisException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,147 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2006-2018 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed 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 com.fr.third.org.objenesis.instantiator.util; |
|
||||||
|
|
||||||
import sun.misc.Unsafe; |
|
||||||
import com.fr.third.org.objenesis.ObjenesisException; |
|
||||||
import com.fr.third.org.objenesis.strategy.PlatformDescription; |
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle; |
|
||||||
import java.lang.invoke.MethodHandles; |
|
||||||
import java.lang.invoke.MethodType; |
|
||||||
import java.security.ProtectionDomain; |
|
||||||
|
|
||||||
/** |
|
||||||
* Java 11+ removed sun.misc.Unsafe.defineClass. This class bridges the gap to work from Java 1.8 up to 11. |
|
||||||
* <p> |
|
||||||
* It was inspired from <a href="https://github.com/jboss-javassist/javassist/blob/master/src/main/javassist/util/proxy/DefineClassHelper.java">javassist</a>. |
|
||||||
* |
|
||||||
* @author Henri Tremblay |
|
||||||
*/ |
|
||||||
public final class DefineClassHelper { |
|
||||||
|
|
||||||
private static abstract class Helper { |
|
||||||
abstract Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor, |
|
||||||
ClassLoader loader, ProtectionDomain protectionDomain); |
|
||||||
} |
|
||||||
|
|
||||||
private static class Java8 extends Helper { |
|
||||||
|
|
||||||
private final MethodHandle defineClass = defineClass(); |
|
||||||
|
|
||||||
private MethodHandle defineClass() { |
|
||||||
MethodType mt = MethodType.methodType(Class.class, String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class); |
|
||||||
MethodHandle m; |
|
||||||
try { |
|
||||||
m = MethodHandles.publicLookup().findVirtual(Unsafe.class, "defineClass", mt); |
|
||||||
} catch(Exception e) { |
|
||||||
throw new ObjenesisException(e); |
|
||||||
} |
|
||||||
Unsafe unsafe = UnsafeUtils.getUnsafe(); |
|
||||||
return m.bindTo(unsafe); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
Class<?> defineClass(String className, byte[] b, int off, int len, Class<?> neighbor, ClassLoader loader, ProtectionDomain protectionDomain) { |
|
||||||
try { |
|
||||||
return (Class<?>) defineClass.invokeExact(className, b, off, len, loader, protectionDomain); |
|
||||||
} catch (Throwable e) { |
|
||||||
if(e instanceof Error) { |
|
||||||
throw (Error) e; |
|
||||||
} |
|
||||||
if(e instanceof RuntimeException) { |
|
||||||
throw (RuntimeException) e; |
|
||||||
} |
|
||||||
throw new ObjenesisException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static class Java11 extends Helper { |
|
||||||
|
|
||||||
private final Class<?> module = module(); |
|
||||||
private final MethodHandles.Lookup lookup = MethodHandles.lookup(); |
|
||||||
private final MethodHandle getModule = getModule(); |
|
||||||
private final MethodHandle addReads = addReads(); |
|
||||||
private final MethodHandle privateLookupIn = privateLookupIn(); |
|
||||||
private final MethodHandle defineClass = defineClass(); |
|
||||||
|
|
||||||
private Class<?> module() { |
|
||||||
try { |
|
||||||
return Class.forName("java.lang.Module"); |
|
||||||
} catch (ClassNotFoundException e) { |
|
||||||
throw new ObjenesisException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private MethodHandle getModule() { |
|
||||||
try { |
|
||||||
return lookup.findVirtual(Class.class, "getModule", MethodType.methodType(module)); |
|
||||||
} catch (Exception e) { |
|
||||||
throw new ObjenesisException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private MethodHandle addReads() { |
|
||||||
try { |
|
||||||
return lookup.findVirtual(module, "addReads", MethodType.methodType(module, module)); |
|
||||||
} catch (Exception e) { |
|
||||||
throw new ObjenesisException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private MethodHandle privateLookupIn() { |
|
||||||
try { |
|
||||||
return lookup.findStatic(MethodHandles.class, "privateLookupIn", MethodType.methodType(MethodHandles.Lookup.class, Class.class, MethodHandles.Lookup.class)); |
|
||||||
} catch (Exception e) { |
|
||||||
throw new ObjenesisException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private MethodHandle defineClass() { |
|
||||||
try { |
|
||||||
return lookup.findVirtual(MethodHandles.Lookup.class, "defineClass", MethodType.methodType(Class.class, byte[].class)); |
|
||||||
} catch (Exception e) { |
|
||||||
throw new ObjenesisException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
Class<?> defineClass(String className, byte[] b, int off, int len, Class<?> neighbor, ClassLoader loader, ProtectionDomain protectionDomain) { |
|
||||||
try { |
|
||||||
Object module = getModule.invokeWithArguments(DefineClassHelper.class); |
|
||||||
Object neighborModule = getModule.invokeWithArguments(neighbor); |
|
||||||
addReads.invokeWithArguments(module, neighborModule); |
|
||||||
MethodHandles.Lookup prvlookup = (MethodHandles.Lookup) privateLookupIn.invokeExact(neighbor, lookup); |
|
||||||
return (Class<?>) defineClass.invokeExact(prvlookup, b); |
|
||||||
} catch (Throwable e) { |
|
||||||
throw new ObjenesisException(neighbor.getName() + " has no permission to define the class", e); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Java 11+ removed sun.misc.Unsafe.defineClass, so we fallback to invoking defineClass on
|
|
||||||
// ClassLoader until we have an implementation that uses MethodHandles.Lookup.defineClass
|
|
||||||
private static final Helper privileged = PlatformDescription.isAfterJava11() ? |
|
||||||
new Java11() : new Java8(); |
|
||||||
|
|
||||||
public static Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor, |
|
||||||
ClassLoader loader, ProtectionDomain protectionDomain) { |
|
||||||
return privileged.defineClass(name, b, off, len, neighbor, loader, protectionDomain); |
|
||||||
} |
|
||||||
|
|
||||||
private DefineClassHelper() {} |
|
||||||
} |
|
@ -1,5 +1,5 @@ |
|||||||
/* |
/** |
||||||
* Copyright 2006-2018 the original author or authors. |
* Copyright 2006-2017 the original author or authors. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
@ -0,0 +1,102 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2006-2017 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed 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 com.fr.third.org.objenesis; |
||||||
|
|
||||||
|
import com.fr.third.org.objenesis.instantiator.ObjectInstantiator; |
||||||
|
import com.fr.third.org.objenesis.strategy.InstantiatorStrategy; |
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* Base class to extend if you want to have a class providing your own default strategy. Can also be |
||||||
|
* instantiated directly. |
||||||
|
* |
||||||
|
* @author Henri Tremblay |
||||||
|
*/ |
||||||
|
public class ObjenesisBase implements Objenesis { |
||||||
|
|
||||||
|
/** Strategy used by this Objenesi implementation to create classes */ |
||||||
|
protected final InstantiatorStrategy strategy; |
||||||
|
|
||||||
|
/** Strategy cache. Key = Class, Value = InstantiatorStrategy */ |
||||||
|
protected ConcurrentHashMap<String, ObjectInstantiator<?>> cache; |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor allowing to pick a strategy and using cache |
||||||
|
* |
||||||
|
* @param strategy Strategy to use |
||||||
|
*/ |
||||||
|
public ObjenesisBase(InstantiatorStrategy strategy) { |
||||||
|
this(strategy, true); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Flexible constructor allowing to pick the strategy and if caching should be used |
||||||
|
* |
||||||
|
* @param strategy Strategy to use |
||||||
|
* @param useCache If {@link ObjectInstantiator}s should be cached |
||||||
|
*/ |
||||||
|
public ObjenesisBase(InstantiatorStrategy strategy, boolean useCache) { |
||||||
|
if(strategy == null) { |
||||||
|
throw new IllegalArgumentException("A strategy can't be null"); |
||||||
|
} |
||||||
|
this.strategy = strategy; |
||||||
|
this.cache = useCache ? new ConcurrentHashMap<String, ObjectInstantiator<?>>() : null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() { |
||||||
|
return getClass().getName() + " using " + strategy.getClass().getName() |
||||||
|
+ (cache == null ? " without" : " with") + " caching"; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Will create a new object without any constructor being called |
||||||
|
* |
||||||
|
* @param clazz Class to instantiate |
||||||
|
* @return New instance of clazz |
||||||
|
*/ |
||||||
|
public <T> T newInstance(Class<T> clazz) { |
||||||
|
return getInstantiatorOf(clazz).newInstance(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Will pick the best instantiator for the provided class. If you need to create a lot of |
||||||
|
* instances from the same class, it is way more efficient to create them from the same |
||||||
|
* ObjectInstantiator than calling {@link #newInstance(Class)}. |
||||||
|
* |
||||||
|
* @param clazz Class to instantiate |
||||||
|
* @return Instantiator dedicated to the class
|
||||||
|
*/ |
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) { |
||||||
|
if(clazz.isPrimitive()) { |
||||||
|
throw new IllegalArgumentException("Primitive types can't be instantiated in Java"); |
||||||
|
} |
||||||
|
if(cache == null) { |
||||||
|
return strategy.newInstantiatorOf(clazz); |
||||||
|
} |
||||||
|
ObjectInstantiator<?> instantiator = cache.get(clazz.getName()); |
||||||
|
if(instantiator == null) { |
||||||
|
ObjectInstantiator<?> newInstantiator = strategy.newInstantiatorOf(clazz); |
||||||
|
instantiator = cache.putIfAbsent(clazz.getName(), newInstantiator); |
||||||
|
if(instantiator == null) { |
||||||
|
instantiator = newInstantiator; |
||||||
|
} |
||||||
|
} |
||||||
|
return (ObjectInstantiator<T>) instantiator; |
||||||
|
} |
||||||
|
} |
@ -1,5 +1,5 @@ |
|||||||
/* |
/** |
||||||
* Copyright 2006-2018 the original author or authors. |
* Copyright 2006-2017 the original author or authors. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@ |
|||||||
/* |
/** |
||||||
* Copyright 2006-2018 the original author or authors. |
* Copyright 2006-2017 the original author or authors. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@ |
|||||||
/* |
/** |
||||||
* Copyright 2006-2018 the original author or authors. |
* Copyright 2006-2017 the original author or authors. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@ |
|||||||
/* |
/** |
||||||
* Copyright 2006-2018 the original author or authors. |
* Copyright 2006-2017 the original author or authors. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@ |
|||||||
/* |
/** |
||||||
* Copyright 2006-2018 the original author or authors. |
* Copyright 2006-2017 the original author or authors. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@ |
|||||||
/* |
/** |
||||||
* Copyright 2006-2018 the original author or authors. |
* Copyright 2006-2017 the original author or authors. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
@ -0,0 +1,149 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2006-2019 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed 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 com.fr.third.org.objenesis.instantiator.util; |
||||||
|
|
||||||
|
import com.fr.third.org.objenesis.ObjenesisException; |
||||||
|
import com.fr.third.org.objenesis.strategy.PlatformDescription; |
||||||
|
import sun.misc.Unsafe; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandle; |
||||||
|
import java.lang.invoke.MethodHandles; |
||||||
|
import java.lang.invoke.MethodType; |
||||||
|
import java.security.ProtectionDomain; |
||||||
|
|
||||||
|
/** |
||||||
|
* Java 11+ removed sun.misc.Unsafe.defineClass. This class bridges the gap to work from Java 1.8 up to 11. |
||||||
|
* <p> |
||||||
|
* It was inspired from <a href="https://github.com/jboss-javassist/javassist/blob/master/src/main/javassist/util/proxy/DefineClassHelper.java">javassist</a>. |
||||||
|
* |
||||||
|
* @author Henri Tremblay |
||||||
|
*/ |
||||||
|
public final class DefineClassHelper { |
||||||
|
|
||||||
|
private static abstract class Helper { |
||||||
|
abstract Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor, |
||||||
|
ClassLoader loader, ProtectionDomain protectionDomain); |
||||||
|
} |
||||||
|
|
||||||
|
private static class Java8 extends Helper { |
||||||
|
|
||||||
|
private final MethodHandle defineClass = defineClass(); |
||||||
|
|
||||||
|
private MethodHandle defineClass() { |
||||||
|
MethodType mt = MethodType.methodType(Class.class, String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class); |
||||||
|
MethodHandle m; |
||||||
|
try { |
||||||
|
m = MethodHandles.publicLookup().findVirtual(Unsafe.class, "defineClass", mt); |
||||||
|
} catch(NoSuchMethodException | IllegalAccessException e) { |
||||||
|
throw new ObjenesisException(e); |
||||||
|
} |
||||||
|
Unsafe unsafe = UnsafeUtils.getUnsafe(); |
||||||
|
return m.bindTo(unsafe); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
Class<?> defineClass(String className, byte[] b, int off, int len, Class<?> neighbor, ClassLoader loader, ProtectionDomain protectionDomain) { |
||||||
|
try { |
||||||
|
return (Class<?>) defineClass.invokeExact(className, b, off, len, loader, protectionDomain); |
||||||
|
} catch (Throwable e) { |
||||||
|
if(e instanceof Error) { |
||||||
|
throw (Error) e; |
||||||
|
} |
||||||
|
if(e instanceof RuntimeException) { |
||||||
|
throw (RuntimeException) e; |
||||||
|
} |
||||||
|
throw new ObjenesisException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static class Java11 extends Helper { |
||||||
|
|
||||||
|
private final Class<?> module = module(); |
||||||
|
private final MethodHandles.Lookup lookup = MethodHandles.lookup(); |
||||||
|
private final MethodHandle getModule = getModule(); |
||||||
|
private final MethodHandle addReads = addReads(); |
||||||
|
private final MethodHandle privateLookupIn = privateLookupIn(); |
||||||
|
private final MethodHandle defineClass = defineClass(); |
||||||
|
|
||||||
|
private Class<?> module() { |
||||||
|
try { |
||||||
|
return Class.forName("java.lang.Module"); |
||||||
|
} catch (ClassNotFoundException e) { |
||||||
|
throw new ObjenesisException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private MethodHandle getModule() { |
||||||
|
try { |
||||||
|
return lookup.findVirtual(Class.class, "getModule", MethodType.methodType(module)); |
||||||
|
} catch (NoSuchMethodException | IllegalAccessException e) { |
||||||
|
throw new ObjenesisException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private MethodHandle addReads() { |
||||||
|
try { |
||||||
|
return lookup.findVirtual(module, "addReads", MethodType.methodType(module, module)); |
||||||
|
} catch (NoSuchMethodException | IllegalAccessException e) { |
||||||
|
throw new ObjenesisException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private MethodHandle privateLookupIn() { |
||||||
|
try { |
||||||
|
return lookup.findStatic(MethodHandles.class, "privateLookupIn", MethodType.methodType(MethodHandles.Lookup.class, Class.class, MethodHandles.Lookup.class)); |
||||||
|
} catch (NoSuchMethodException | IllegalAccessException e) { |
||||||
|
throw new ObjenesisException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private MethodHandle defineClass() { |
||||||
|
try { |
||||||
|
return lookup.findVirtual(MethodHandles.Lookup.class, "defineClass", MethodType.methodType(Class.class, byte[].class)); |
||||||
|
} catch (NoSuchMethodException | IllegalAccessException e) { |
||||||
|
throw new ObjenesisException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
Class<?> defineClass(String className, byte[] b, int off, int len, Class<?> neighbor, ClassLoader loader, ProtectionDomain protectionDomain) { |
||||||
|
try { |
||||||
|
Object module = getModule.invokeWithArguments(DefineClassHelper.class); |
||||||
|
Object neighborModule = getModule.invokeWithArguments(neighbor); |
||||||
|
addReads.invokeWithArguments(module, neighborModule); |
||||||
|
MethodHandles.Lookup prvlookup = (MethodHandles.Lookup) privateLookupIn.invokeExact(neighbor, lookup); |
||||||
|
return (Class<?>) defineClass.invokeExact(prvlookup, b); |
||||||
|
} catch (Throwable e) { |
||||||
|
throw new ObjenesisException(neighbor.getName() + " has no permission to define the class", e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Java 11+ removed sun.misc.Unsafe.defineClass, so we fallback to invoking defineClass on
|
||||||
|
// ClassLoader until we have an implementation that uses MethodHandles.Lookup.defineClass
|
||||||
|
private static final Helper privileged = PlatformDescription.isAfterJava11() ? |
||||||
|
new Java11() : new Java8(); |
||||||
|
|
||||||
|
public static Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor, |
||||||
|
ClassLoader loader, ProtectionDomain protectionDomain) { |
||||||
|
return privileged.defineClass(name, b, off, len, neighbor, loader, protectionDomain); |
||||||
|
} |
||||||
|
|
||||||
|
private DefineClassHelper() {} |
||||||
|
} |
@ -1,5 +1,5 @@ |
|||||||
/* |
/** |
||||||
* Copyright 2006-2018 the original author or authors. |
* Copyright 2006-2017 the original author or authors. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@ |
|||||||
/* |
/** |
||||||
* Copyright 2006-2018 the original author or authors. |
* Copyright 2006-2017 the original author or authors. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@ |
|||||||
/* |
/** |
||||||
* Copyright 2006-2018 the original author or authors. |
* Copyright 2006-2017 the original author or authors. |
||||||
* |
* |
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
* you may not use this file except in compliance with the License. |
* you may not use this file except in compliance with the License. |
@ -0,0 +1,96 @@ |
|||||||
|
package com.fr.third.sun.misc; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.OutputStream; |
||||||
|
import java.io.PushbackInputStream; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author zhouping |
||||||
|
* @version 10.0 |
||||||
|
* Created by zhouping on 2019/10/28 |
||||||
|
*/ |
||||||
|
public class BASE64Decoder extends CharacterDecoder { |
||||||
|
private static final char[] pem_array = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; |
||||||
|
private static final byte[] pem_convert_array = new byte[256]; |
||||||
|
byte[] decode_buffer = new byte[4]; |
||||||
|
|
||||||
|
public BASE64Decoder() { |
||||||
|
} |
||||||
|
|
||||||
|
protected int bytesPerAtom() { |
||||||
|
return 4; |
||||||
|
} |
||||||
|
|
||||||
|
protected int bytesPerLine() { |
||||||
|
return 72; |
||||||
|
} |
||||||
|
|
||||||
|
protected void decodeAtom(PushbackInputStream var1, OutputStream var2, int var3) throws IOException { |
||||||
|
byte var5 = -1; |
||||||
|
byte var6 = -1; |
||||||
|
byte var7 = -1; |
||||||
|
byte var8 = -1; |
||||||
|
if (var3 < 2) { |
||||||
|
throw new CEFormatException("BASE64Decoder: Not enough bytes for an atom."); |
||||||
|
} else { |
||||||
|
int var4; |
||||||
|
do { |
||||||
|
var4 = var1.read(); |
||||||
|
if (var4 == -1) { |
||||||
|
throw new CEStreamExhausted(); |
||||||
|
} |
||||||
|
} while(var4 == 10 || var4 == 13); |
||||||
|
|
||||||
|
this.decode_buffer[0] = (byte)var4; |
||||||
|
var4 = this.readFully(var1, this.decode_buffer, 1, var3 - 1); |
||||||
|
if (var4 == -1) { |
||||||
|
throw new CEStreamExhausted(); |
||||||
|
} else { |
||||||
|
if (var3 > 3 && this.decode_buffer[3] == 61) { |
||||||
|
var3 = 3; |
||||||
|
} |
||||||
|
|
||||||
|
if (var3 > 2 && this.decode_buffer[2] == 61) { |
||||||
|
var3 = 2; |
||||||
|
} |
||||||
|
|
||||||
|
switch(var3) { |
||||||
|
case 4: |
||||||
|
var8 = pem_convert_array[this.decode_buffer[3] & 255]; |
||||||
|
case 3: |
||||||
|
var7 = pem_convert_array[this.decode_buffer[2] & 255]; |
||||||
|
case 2: |
||||||
|
var6 = pem_convert_array[this.decode_buffer[1] & 255]; |
||||||
|
var5 = pem_convert_array[this.decode_buffer[0] & 255]; |
||||||
|
default: |
||||||
|
switch(var3) { |
||||||
|
case 2: |
||||||
|
var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3)); |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3)); |
||||||
|
var2.write((byte)(var6 << 4 & 240 | var7 >>> 2 & 15)); |
||||||
|
break; |
||||||
|
case 4: |
||||||
|
var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3)); |
||||||
|
var2.write((byte)(var6 << 4 & 240 | var7 >>> 2 & 15)); |
||||||
|
var2.write((byte)(var7 << 6 & 192 | var8 & 63)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static { |
||||||
|
int var0; |
||||||
|
for(var0 = 0; var0 < 255; ++var0) { |
||||||
|
pem_convert_array[var0] = -1; |
||||||
|
} |
||||||
|
|
||||||
|
for(var0 = 0; var0 < pem_array.length; ++var0) { |
||||||
|
pem_convert_array[pem_array[var0]] = (byte)var0; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
package com.fr.third.sun.misc; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.OutputStream; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author zhouping |
||||||
|
* @version 10.0 |
||||||
|
* Created by zhouping on 2019/10/28 |
||||||
|
*/ |
||||||
|
public class BASE64Encoder extends CharacterEncoder { |
||||||
|
|
||||||
|
private static final char[] pem_array = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; |
||||||
|
|
||||||
|
public BASE64Encoder() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
protected int bytesPerAtom() { |
||||||
|
|
||||||
|
return 3; |
||||||
|
} |
||||||
|
|
||||||
|
protected int bytesPerLine() { |
||||||
|
|
||||||
|
return 57; |
||||||
|
} |
||||||
|
|
||||||
|
protected void encodeAtom(OutputStream var1, byte[] var2, int var3, int var4) throws IOException { |
||||||
|
|
||||||
|
byte var5; |
||||||
|
if (var4 == 1) { |
||||||
|
var5 = var2[var3]; |
||||||
|
byte var6 = 0; |
||||||
|
boolean var7 = false; |
||||||
|
var1.write(pem_array[var5 >>> 2 & 63]); |
||||||
|
var1.write(pem_array[(var5 << 4 & 48) + (var6 >>> 4 & 15)]); |
||||||
|
var1.write(61); |
||||||
|
var1.write(61); |
||||||
|
} else { |
||||||
|
byte var8; |
||||||
|
if (var4 == 2) { |
||||||
|
var5 = var2[var3]; |
||||||
|
var8 = var2[var3 + 1]; |
||||||
|
byte var9 = 0; |
||||||
|
var1.write(pem_array[var5 >>> 2 & 63]); |
||||||
|
var1.write(pem_array[(var5 << 4 & 48) + (var8 >>> 4 & 15)]); |
||||||
|
var1.write(pem_array[(var8 << 2 & 60) + (var9 >>> 6 & 3)]); |
||||||
|
var1.write(61); |
||||||
|
} else { |
||||||
|
var5 = var2[var3]; |
||||||
|
var8 = var2[var3 + 1]; |
||||||
|
byte var10 = var2[var3 + 2]; |
||||||
|
var1.write(pem_array[var5 >>> 2 & 63]); |
||||||
|
var1.write(pem_array[(var5 << 4 & 48) + (var8 >>> 4 & 15)]); |
||||||
|
var1.write(pem_array[(var8 << 2 & 60) + (var10 >>> 6 & 3)]); |
||||||
|
var1.write(pem_array[var10 & 63]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package com.fr.third.sun.misc; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author zhouping |
||||||
|
* @version 10.0 |
||||||
|
* Created by zhouping on 2019/10/28 |
||||||
|
*/ |
||||||
|
public class CEFormatException extends IOException { |
||||||
|
|
||||||
|
public CEFormatException(String var1) { |
||||||
|
|
||||||
|
super(var1); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package com.fr.third.sun.misc; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author zhouping |
||||||
|
* @version 10.0 |
||||||
|
* Created by zhouping on 2019/10/28 |
||||||
|
*/ |
||||||
|
public class CEStreamExhausted extends IOException { |
||||||
|
|
||||||
|
public CEStreamExhausted() { |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,107 @@ |
|||||||
|
package com.fr.third.sun.misc; |
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.OutputStream; |
||||||
|
import java.io.PushbackInputStream; |
||||||
|
import java.nio.ByteBuffer; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author zhouping |
||||||
|
* @version 10.0 |
||||||
|
* Created by zhouping on 2019/10/28 |
||||||
|
*/ |
||||||
|
public abstract class CharacterDecoder { |
||||||
|
public CharacterDecoder() { |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract int bytesPerAtom(); |
||||||
|
|
||||||
|
protected abstract int bytesPerLine(); |
||||||
|
|
||||||
|
protected void decodeBufferPrefix(PushbackInputStream var1, OutputStream var2) throws IOException { |
||||||
|
} |
||||||
|
|
||||||
|
protected void decodeBufferSuffix(PushbackInputStream var1, OutputStream var2) throws IOException { |
||||||
|
} |
||||||
|
|
||||||
|
protected int decodeLinePrefix(PushbackInputStream var1, OutputStream var2) throws IOException { |
||||||
|
return this.bytesPerLine(); |
||||||
|
} |
||||||
|
|
||||||
|
protected void decodeLineSuffix(PushbackInputStream var1, OutputStream var2) throws IOException { |
||||||
|
} |
||||||
|
|
||||||
|
protected void decodeAtom(PushbackInputStream var1, OutputStream var2, int var3) throws IOException { |
||||||
|
throw new CEStreamExhausted(); |
||||||
|
} |
||||||
|
|
||||||
|
protected int readFully(InputStream var1, byte[] var2, int var3, int var4) throws IOException { |
||||||
|
for(int var5 = 0; var5 < var4; ++var5) { |
||||||
|
int var6 = var1.read(); |
||||||
|
if (var6 == -1) { |
||||||
|
return var5 == 0 ? -1 : var5; |
||||||
|
} |
||||||
|
|
||||||
|
var2[var5 + var3] = (byte)var6; |
||||||
|
} |
||||||
|
|
||||||
|
return var4; |
||||||
|
} |
||||||
|
|
||||||
|
public void decodeBuffer(InputStream var1, OutputStream var2) throws IOException { |
||||||
|
int var4 = 0; |
||||||
|
PushbackInputStream var5 = new PushbackInputStream(var1); |
||||||
|
this.decodeBufferPrefix(var5, var2); |
||||||
|
|
||||||
|
while(true) { |
||||||
|
try { |
||||||
|
int var6 = this.decodeLinePrefix(var5, var2); |
||||||
|
|
||||||
|
int var3; |
||||||
|
for(var3 = 0; var3 + this.bytesPerAtom() < var6; var3 += this.bytesPerAtom()) { |
||||||
|
this.decodeAtom(var5, var2, this.bytesPerAtom()); |
||||||
|
var4 += this.bytesPerAtom(); |
||||||
|
} |
||||||
|
|
||||||
|
if (var3 + this.bytesPerAtom() == var6) { |
||||||
|
this.decodeAtom(var5, var2, this.bytesPerAtom()); |
||||||
|
var4 += this.bytesPerAtom(); |
||||||
|
} else { |
||||||
|
this.decodeAtom(var5, var2, var6 - var3); |
||||||
|
var4 += var6 - var3; |
||||||
|
} |
||||||
|
|
||||||
|
this.decodeLineSuffix(var5, var2); |
||||||
|
} catch (CEStreamExhausted var8) { |
||||||
|
this.decodeBufferSuffix(var5, var2); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public byte[] decodeBuffer(String var1) throws IOException { |
||||||
|
byte[] var2 = new byte[var1.length()]; |
||||||
|
var1.getBytes(0, var1.length(), var2, 0); |
||||||
|
ByteArrayInputStream var3 = new ByteArrayInputStream(var2); |
||||||
|
ByteArrayOutputStream var4 = new ByteArrayOutputStream(); |
||||||
|
this.decodeBuffer(var3, var4); |
||||||
|
return var4.toByteArray(); |
||||||
|
} |
||||||
|
|
||||||
|
public byte[] decodeBuffer(InputStream var1) throws IOException { |
||||||
|
ByteArrayOutputStream var2 = new ByteArrayOutputStream(); |
||||||
|
this.decodeBuffer(var1, var2); |
||||||
|
return var2.toByteArray(); |
||||||
|
} |
||||||
|
|
||||||
|
public ByteBuffer decodeBufferToByteBuffer(String var1) throws IOException { |
||||||
|
return ByteBuffer.wrap(this.decodeBuffer(var1)); |
||||||
|
} |
||||||
|
|
||||||
|
public ByteBuffer decodeBufferToByteBuffer(InputStream var1) throws IOException { |
||||||
|
return ByteBuffer.wrap(this.decodeBuffer(var1)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,186 @@ |
|||||||
|
package com.fr.third.sun.misc; |
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.OutputStream; |
||||||
|
import java.io.PrintStream; |
||||||
|
import java.nio.ByteBuffer; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author zhouping |
||||||
|
* @version 10.0 |
||||||
|
* Created by zhouping on 2019/10/28 |
||||||
|
*/ |
||||||
|
public abstract class CharacterEncoder { |
||||||
|
protected PrintStream pStream; |
||||||
|
|
||||||
|
public CharacterEncoder() { |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract int bytesPerAtom(); |
||||||
|
|
||||||
|
protected abstract int bytesPerLine(); |
||||||
|
|
||||||
|
protected void encodeBufferPrefix(OutputStream var1) throws IOException { |
||||||
|
this.pStream = new PrintStream(var1); |
||||||
|
} |
||||||
|
|
||||||
|
protected void encodeBufferSuffix(OutputStream var1) throws IOException { |
||||||
|
} |
||||||
|
|
||||||
|
protected void encodeLinePrefix(OutputStream var1, int var2) throws IOException { |
||||||
|
} |
||||||
|
|
||||||
|
protected void encodeLineSuffix(OutputStream var1) throws IOException { |
||||||
|
this.pStream.println(); |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract void encodeAtom(OutputStream var1, byte[] var2, int var3, int var4) throws IOException; |
||||||
|
|
||||||
|
protected int readFully(InputStream var1, byte[] var2) throws IOException { |
||||||
|
for (int var3 = 0; var3 < var2.length; ++var3) { |
||||||
|
int var4 = var1.read(); |
||||||
|
if (var4 == -1) { |
||||||
|
return var3; |
||||||
|
} |
||||||
|
|
||||||
|
var2[var3] = (byte) var4; |
||||||
|
} |
||||||
|
|
||||||
|
return var2.length; |
||||||
|
} |
||||||
|
|
||||||
|
public void encode(InputStream var1, OutputStream var2) throws IOException { |
||||||
|
byte[] var5 = new byte[this.bytesPerLine()]; |
||||||
|
this.encodeBufferPrefix(var2); |
||||||
|
|
||||||
|
while (true) { |
||||||
|
int var4 = this.readFully(var1, var5); |
||||||
|
if (var4 == 0) { |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
this.encodeLinePrefix(var2, var4); |
||||||
|
|
||||||
|
for (int var3 = 0; var3 < var4; var3 += this.bytesPerAtom()) { |
||||||
|
if (var3 + this.bytesPerAtom() <= var4) { |
||||||
|
this.encodeAtom(var2, var5, var3, this.bytesPerAtom()); |
||||||
|
} else { |
||||||
|
this.encodeAtom(var2, var5, var3, var4 - var3); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (var4 < this.bytesPerLine()) { |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
this.encodeLineSuffix(var2); |
||||||
|
} |
||||||
|
|
||||||
|
this.encodeBufferSuffix(var2); |
||||||
|
} |
||||||
|
|
||||||
|
public void encode(byte[] var1, OutputStream var2) throws IOException { |
||||||
|
ByteArrayInputStream var3 = new ByteArrayInputStream(var1); |
||||||
|
this.encode((InputStream) var3, var2); |
||||||
|
} |
||||||
|
|
||||||
|
public String encode(byte[] var1) { |
||||||
|
ByteArrayOutputStream var2 = new ByteArrayOutputStream(); |
||||||
|
ByteArrayInputStream var3 = new ByteArrayInputStream(var1); |
||||||
|
String var4 = null; |
||||||
|
|
||||||
|
try { |
||||||
|
this.encode((InputStream) var3, var2); |
||||||
|
var4 = var2.toString("8859_1"); |
||||||
|
return var4; |
||||||
|
} catch (Exception var6) { |
||||||
|
throw new Error("CharacterEncoder.encode internal error"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private byte[] getBytes(ByteBuffer var1) { |
||||||
|
byte[] var2 = null; |
||||||
|
if (var1.hasArray()) { |
||||||
|
byte[] var3 = var1.array(); |
||||||
|
if (var3.length == var1.capacity() && var3.length == var1.remaining()) { |
||||||
|
var2 = var3; |
||||||
|
var1.position(var1.limit()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (var2 == null) { |
||||||
|
var2 = new byte[var1.remaining()]; |
||||||
|
var1.get(var2); |
||||||
|
} |
||||||
|
|
||||||
|
return var2; |
||||||
|
} |
||||||
|
|
||||||
|
public void encode(ByteBuffer var1, OutputStream var2) throws IOException { |
||||||
|
byte[] var3 = this.getBytes(var1); |
||||||
|
this.encode(var3, var2); |
||||||
|
} |
||||||
|
|
||||||
|
public String encode(ByteBuffer var1) { |
||||||
|
byte[] var2 = this.getBytes(var1); |
||||||
|
return this.encode(var2); |
||||||
|
} |
||||||
|
|
||||||
|
public void encodeBuffer(InputStream var1, OutputStream var2) throws IOException { |
||||||
|
byte[] var5 = new byte[this.bytesPerLine()]; |
||||||
|
this.encodeBufferPrefix(var2); |
||||||
|
|
||||||
|
int var4; |
||||||
|
do { |
||||||
|
var4 = this.readFully(var1, var5); |
||||||
|
if (var4 == 0) { |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
this.encodeLinePrefix(var2, var4); |
||||||
|
|
||||||
|
for (int var3 = 0; var3 < var4; var3 += this.bytesPerAtom()) { |
||||||
|
if (var3 + this.bytesPerAtom() <= var4) { |
||||||
|
this.encodeAtom(var2, var5, var3, this.bytesPerAtom()); |
||||||
|
} else { |
||||||
|
this.encodeAtom(var2, var5, var3, var4 - var3); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.encodeLineSuffix(var2); |
||||||
|
} while (var4 >= this.bytesPerLine()); |
||||||
|
|
||||||
|
this.encodeBufferSuffix(var2); |
||||||
|
} |
||||||
|
|
||||||
|
public void encodeBuffer(byte[] var1, OutputStream var2) throws IOException { |
||||||
|
ByteArrayInputStream var3 = new ByteArrayInputStream(var1); |
||||||
|
this.encodeBuffer((InputStream) var3, var2); |
||||||
|
} |
||||||
|
|
||||||
|
public String encodeBuffer(byte[] var1) { |
||||||
|
ByteArrayOutputStream var2 = new ByteArrayOutputStream(); |
||||||
|
ByteArrayInputStream var3 = new ByteArrayInputStream(var1); |
||||||
|
|
||||||
|
try { |
||||||
|
this.encodeBuffer((InputStream) var3, var2); |
||||||
|
} catch (Exception var5) { |
||||||
|
throw new Error("CharacterEncoder.encodeBuffer internal error"); |
||||||
|
} |
||||||
|
|
||||||
|
return var2.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public void encodeBuffer(ByteBuffer var1, OutputStream var2) throws IOException { |
||||||
|
byte[] var3 = this.getBytes(var1); |
||||||
|
this.encodeBuffer(var3, var2); |
||||||
|
} |
||||||
|
|
||||||
|
public String encodeBuffer(ByteBuffer var1) { |
||||||
|
byte[] var2 = this.getBytes(var1); |
||||||
|
return this.encodeBuffer(var2); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,84 @@ |
|||||||
|
package com.fr.third.sun.misc; |
||||||
|
|
||||||
|
import java.lang.ref.PhantomReference; |
||||||
|
import java.lang.ref.ReferenceQueue; |
||||||
|
import java.security.AccessController; |
||||||
|
import java.security.PrivilegedAction; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author zhouping |
||||||
|
* @version 10.0 |
||||||
|
* Created by zhouping on 2019/10/29 |
||||||
|
*/ |
||||||
|
public class Cleaner extends PhantomReference<Object> { |
||||||
|
private static final ReferenceQueue<Object> dummyQueue = new ReferenceQueue(); |
||||||
|
private static Cleaner first = null; |
||||||
|
private Cleaner next = null; |
||||||
|
private Cleaner prev = null; |
||||||
|
private final Runnable thunk; |
||||||
|
|
||||||
|
private static synchronized Cleaner add(Cleaner var0) { |
||||||
|
if (first != null) { |
||||||
|
var0.next = first; |
||||||
|
first.prev = var0; |
||||||
|
} |
||||||
|
|
||||||
|
first = var0; |
||||||
|
return var0; |
||||||
|
} |
||||||
|
|
||||||
|
private static synchronized boolean remove(Cleaner var0) { |
||||||
|
if (var0.next == var0) { |
||||||
|
return false; |
||||||
|
} else { |
||||||
|
if (first == var0) { |
||||||
|
if (var0.next != null) { |
||||||
|
first = var0.next; |
||||||
|
} else { |
||||||
|
first = var0.prev; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (var0.next != null) { |
||||||
|
var0.next.prev = var0.prev; |
||||||
|
} |
||||||
|
|
||||||
|
if (var0.prev != null) { |
||||||
|
var0.prev.next = var0.next; |
||||||
|
} |
||||||
|
|
||||||
|
var0.next = var0; |
||||||
|
var0.prev = var0; |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private Cleaner(Object var1, Runnable var2) { |
||||||
|
super(var1, dummyQueue); |
||||||
|
this.thunk = var2; |
||||||
|
} |
||||||
|
|
||||||
|
public static Cleaner create(Object var0, Runnable var1) { |
||||||
|
return var1 == null ? null : add(new Cleaner(var0, var1)); |
||||||
|
} |
||||||
|
|
||||||
|
public void clean() { |
||||||
|
if (remove(this)) { |
||||||
|
try { |
||||||
|
this.thunk.run(); |
||||||
|
} catch (final Throwable var2) { |
||||||
|
AccessController.doPrivileged(new PrivilegedAction<Void>() { |
||||||
|
public Void run() { |
||||||
|
if (System.err != null) { |
||||||
|
(new Error("Cleaner terminated abnormally", var2)).printStackTrace(); |
||||||
|
} |
||||||
|
|
||||||
|
System.exit(1); |
||||||
|
return null; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue