This commit is contained in:
Binary file not shown.
@@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package java.beans;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
<p>An annotation on a constructor that shows how the parameters of
|
|
||||||
that constructor correspond to the constructed object's getter
|
|
||||||
methods. For example:
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
public class Point {
|
|
||||||
@ConstructorProperties({"x", "y"})
|
|
||||||
public Point(int x, int y) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int x, y;
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
The annotation shows that the first parameter of the constructor
|
|
||||||
can be retrieved with the {@code getX()} method and the second with
|
|
||||||
the {@code getY()} method. Since parameter names are not in
|
|
||||||
general available at runtime, without the annotation there would be
|
|
||||||
no way to know whether the parameters correspond to {@code getX()}
|
|
||||||
and {@code getY()} or the other way around.
|
|
||||||
|
|
||||||
@since 1.6
|
|
||||||
*/
|
|
||||||
@Documented @Target(CONSTRUCTOR) @Retention(RUNTIME)
|
|
||||||
public @interface ConstructorProperties {
|
|
||||||
/**
|
|
||||||
<p>The getter names.</p>
|
|
||||||
@return the getter names corresponding to the parameters in the
|
|
||||||
annotated constructor.
|
|
||||||
*/
|
|
||||||
String[] value();
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package java.lang;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An informative annotation type used to indicate that an interface
|
|
||||||
* type declaration is intended to be a <i>functional interface</i> as
|
|
||||||
* defined by the Java Language Specification.
|
|
||||||
*
|
|
||||||
* Conceptually, a functional interface has exactly one abstract
|
|
||||||
* method. Since {@linkplain java.lang.reflect.Method#isDefault()
|
|
||||||
* default methods} have an implementation, they are not abstract. If
|
|
||||||
* an interface declares an abstract method overriding one of the
|
|
||||||
* public methods of {@code java.lang.Object}, that also does
|
|
||||||
* <em>not</em> count toward the interface's abstract method count
|
|
||||||
* since any implementation of the interface will have an
|
|
||||||
* implementation from {@code java.lang.Object} or elsewhere.
|
|
||||||
*
|
|
||||||
* <p>Note that instances of functional interfaces can be created with
|
|
||||||
* lambda expressions, method references, or constructor references.
|
|
||||||
*
|
|
||||||
* <p>If a type is annotated with this annotation type, compilers are
|
|
||||||
* required to generate an error message unless:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li> The type is an interface type and not an annotation type, enum, or class.
|
|
||||||
* <li> The annotated type satisfies the requirements of a functional interface.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* <p>However, the compiler will treat any interface meeting the
|
|
||||||
* definition of a functional interface as a functional interface
|
|
||||||
* regardless of whether or not a {@code FunctionalInterface}
|
|
||||||
* annotation is present on the interface declaration.
|
|
||||||
*
|
|
||||||
* @jls 4.3.2. The Class Object
|
|
||||||
* @jls 9.8 Functional Interfaces
|
|
||||||
* @jls 9.4.3 Interface Method Body
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
public @interface FunctionalInterface {}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package java.lang.annotation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The annotation type {@code java.lang.annotation.Repeatable} is
|
|
||||||
* used to indicate that the annotation type whose declaration it
|
|
||||||
* (meta-)annotates is <em>repeatable</em>. The value of
|
|
||||||
* {@code @Repeatable} indicates the <em>containing annotation
|
|
||||||
* type</em> for the repeatable annotation type.
|
|
||||||
*
|
|
||||||
* @since 1.8
|
|
||||||
* @jls 9.6 Annotation Types
|
|
||||||
* @jls 9.7 Annotations
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.ANNOTATION_TYPE)
|
|
||||||
public @interface Repeatable {
|
|
||||||
/**
|
|
||||||
* Indicates the <em>containing annotation type</em> for the
|
|
||||||
* repeatable annotation type.
|
|
||||||
* @return the containing annotation type
|
|
||||||
*/
|
|
||||||
Class<? extends Annotation> value();
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package java.nio.channels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A handler for consuming the result of an asynchronous I/O operation.
|
|
||||||
*
|
|
||||||
* <p> The asynchronous channels defined in this package allow a completion
|
|
||||||
* handler to be specified to consume the result of an asynchronous operation.
|
|
||||||
* The {@link #completed completed} method is invoked when the I/O operation
|
|
||||||
* completes successfully. The {@link #failed failed} method is invoked if the
|
|
||||||
* I/O operations fails. The implementations of these methods should complete
|
|
||||||
* in a timely manner so as to avoid keeping the invoking thread from dispatching
|
|
||||||
* to other completion handlers.
|
|
||||||
*
|
|
||||||
* @param <V> The result type of the I/O operation
|
|
||||||
* @param <A> The type of the object attached to the I/O operation
|
|
||||||
*
|
|
||||||
* @since 1.7
|
|
||||||
*/
|
|
||||||
|
|
||||||
public interface CompletionHandler<V,A> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked when an operation has completed.
|
|
||||||
*
|
|
||||||
* @param result
|
|
||||||
* The result of the I/O operation.
|
|
||||||
* @param attachment
|
|
||||||
* The object attached to the I/O operation when it was initiated.
|
|
||||||
*/
|
|
||||||
void completed(V result, A attachment);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked when an operation fails.
|
|
||||||
*
|
|
||||||
* @param exc
|
|
||||||
* The exception to indicate why the I/O operation failed
|
|
||||||
* @param attachment
|
|
||||||
* The object attached to the I/O operation when it was initiated.
|
|
||||||
*/
|
|
||||||
void failed(Throwable exc, A attachment);
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package java.util.function;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a predicate (boolean-valued function) of two arguments. This is
|
|
||||||
* the two-arity specialization of {@link Predicate}.
|
|
||||||
*
|
|
||||||
* <p>This is a <a href="package-summary.html">functional interface</a>
|
|
||||||
* whose functional method is {@link #test(Object, Object)}.
|
|
||||||
*
|
|
||||||
* @param <T> the type of the first argument to the predicate
|
|
||||||
* @param <U> the type of the second argument the predicate
|
|
||||||
*
|
|
||||||
* @see Predicate
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface BiPredicate<T, U> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates this predicate on the given arguments.
|
|
||||||
*
|
|
||||||
* @param t the first input argument
|
|
||||||
* @param u the second input argument
|
|
||||||
* @return {@code true} if the input arguments match the predicate,
|
|
||||||
* otherwise {@code false}
|
|
||||||
*/
|
|
||||||
boolean test(T t, U u);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package java.util.function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an operation that accepts a single input argument and returns no
|
|
||||||
* result. Unlike most other functional interfaces, {@code Consumer} is expected
|
|
||||||
* to operate via side-effects.
|
|
||||||
*
|
|
||||||
* <p>This is a <a href="package-summary.html">functional interface</a>
|
|
||||||
* whose functional method is {@link #accept(Object)}.
|
|
||||||
*
|
|
||||||
* @param <T> the type of the input to the operation
|
|
||||||
*
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface Consumer<T> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs this operation on the given argument.
|
|
||||||
*
|
|
||||||
* @param t the input argument
|
|
||||||
*/
|
|
||||||
void accept(T t);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package java.util.function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a predicate (boolean-valued function) of one argument.
|
|
||||||
*
|
|
||||||
* <p>This is a <a href="package-summary.html">functional interface</a>
|
|
||||||
* whose functional method is {@link #test(Object)}.
|
|
||||||
*
|
|
||||||
* @param <T> the type of the input to the predicate
|
|
||||||
*
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface Predicate<T> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates this predicate on the given argument.
|
|
||||||
*
|
|
||||||
* @param t the input argument
|
|
||||||
* @return {@code true} if the input argument matches the predicate,
|
|
||||||
* otherwise {@code false}
|
|
||||||
*/
|
|
||||||
boolean test(T t);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package java.util.function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a supplier of results.
|
|
||||||
*
|
|
||||||
* <p>There is no requirement that a new or distinct result be returned each
|
|
||||||
* time the supplier is invoked.
|
|
||||||
*
|
|
||||||
* <p>This is a <a href="package-summary.html">functional interface</a>
|
|
||||||
* whose functional method is {@link #get()}.
|
|
||||||
*
|
|
||||||
* @param <T> the type of results supplied by this supplier
|
|
||||||
*
|
|
||||||
* @since 1.8
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface Supplier<T> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a result.
|
|
||||||
*
|
|
||||||
* @return a result
|
|
||||||
*/
|
|
||||||
T get();
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package javax.annotation;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Resource annotation marks a resource that is needed
|
|
||||||
* by the application. This annotation may be applied to an
|
|
||||||
* application component class, or to fields or methods of the
|
|
||||||
* component class. When the annotation is applied to a
|
|
||||||
* field or method, the container will inject an instance
|
|
||||||
* of the requested resource into the application component
|
|
||||||
* when the component is initialized. If the annotation is
|
|
||||||
* applied to the component class, the annotation declares a
|
|
||||||
* resource that the application will look up at runtime. <p>
|
|
||||||
*
|
|
||||||
* Even though this annotation is not marked Inherited, deployment
|
|
||||||
* tools are required to examine all superclasses of any component
|
|
||||||
* class to discover all uses of this annotation in all superclasses.
|
|
||||||
* All such annotation instances specify resources that are needed
|
|
||||||
* by the application component. Note that this annotation may
|
|
||||||
* appear on private fields and methods of superclasses; the container
|
|
||||||
* is required to perform injection in these cases as well.
|
|
||||||
*
|
|
||||||
* @since Common Annotations 1.0
|
|
||||||
*/
|
|
||||||
@Target({TYPE, FIELD, METHOD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
public @interface Resource {
|
|
||||||
/**
|
|
||||||
* The JNDI name of the resource. For field annotations,
|
|
||||||
* the default is the field name. For method annotations,
|
|
||||||
* the default is the JavaBeans property name corresponding
|
|
||||||
* to the method. For class annotations, there is no default
|
|
||||||
* and this must be specified.
|
|
||||||
*/
|
|
||||||
String name() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the resource that the reference points to. It can
|
|
||||||
* link to any compatible resource using the global JNDI names.
|
|
||||||
*
|
|
||||||
* @since Common Annotations 1.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
String lookup() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Java type of the resource. For field annotations,
|
|
||||||
* the default is the type of the field. For method annotations,
|
|
||||||
* the default is the type of the JavaBeans property.
|
|
||||||
* For class annotations, there is no default and this must be
|
|
||||||
* specified.
|
|
||||||
*/
|
|
||||||
Class<?> type() default java.lang.Object.class;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The two possible authentication types for a resource.
|
|
||||||
*/
|
|
||||||
enum AuthenticationType {
|
|
||||||
CONTAINER,
|
|
||||||
APPLICATION
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The authentication type to use for this resource.
|
|
||||||
* This may be specified for resources representing a
|
|
||||||
* connection factory of any supported type, and must
|
|
||||||
* not be specified for resources of other types.
|
|
||||||
*/
|
|
||||||
AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether this resource can be shared between
|
|
||||||
* this component and other components.
|
|
||||||
* This may be specified for resources representing a
|
|
||||||
* connection factory of any supported type, and must
|
|
||||||
* not be specified for resources of other types.
|
|
||||||
*/
|
|
||||||
boolean shareable() default true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A product specific name that this resource should be mapped to.
|
|
||||||
* The name of this resource, as defined by the <code>name</code>
|
|
||||||
* element or defaulted, is a name that is local to the application
|
|
||||||
* component using the resource. (It's a name in the JNDI
|
|
||||||
* <code>java:comp/env</code> namespace.) Many application servers
|
|
||||||
* provide a way to map these local names to names of resources
|
|
||||||
* known to the application server. This mapped name is often a
|
|
||||||
* <i>global</i> JNDI name, but may be a name of any form. <p>
|
|
||||||
*
|
|
||||||
* Application servers are not required to support any particular
|
|
||||||
* form or type of mapped name, nor the ability to use mapped names.
|
|
||||||
* The mapped name is product-dependent and often installation-dependent.
|
|
||||||
* No use of a mapped name is portable.
|
|
||||||
*/
|
|
||||||
String mappedName() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of this resource. The description is expected
|
|
||||||
* to be in the default language of the system on which the
|
|
||||||
* application is deployed. The description can be presented
|
|
||||||
* to the Deployer to help in choosing the correct resource.
|
|
||||||
*/
|
|
||||||
String description() default "";
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入Writer,JSON则不写入。
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public final class AnyEncoder<T> implements Encodeable<Writer, T> {
|
|
||||||
|
|
||||||
final Factory factory;
|
|
||||||
|
|
||||||
AnyEncoder(Factory factory) {
|
|
||||||
this.factory = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void convertTo(final Writer out, final T value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
out.wirteClassName(factory.getEntity(value.getClass()));
|
|
||||||
factory.loadEncoder(value.getClass()).convertTo(out, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return Object.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对象数组的序列化,不包含int[]、long[]这样的primitive class数组.
|
|
||||||
* 数组长度不能超过 32767。 在BSON中数组长度设定的是short,对于大于32767长度的数组传输会影响性能,所以没有采用int存储。
|
|
||||||
* 支持一定程度的泛型。
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
|
||||||
|
|
||||||
private final Type type;
|
|
||||||
|
|
||||||
private final Type componentType;
|
|
||||||
|
|
||||||
private final Class componentClass;
|
|
||||||
|
|
||||||
private final Decodeable<Reader, T> decoder;
|
|
||||||
|
|
||||||
public ArrayDecoder(final Factory factory, final Type type) {
|
|
||||||
this.type = type;
|
|
||||||
if (type instanceof GenericArrayType) {
|
|
||||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
|
||||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
|
||||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
|
||||||
this.componentType = ((Class) type).getComponentType();
|
|
||||||
} else {
|
|
||||||
throw new ConvertException("(" + type + ") is not a array type");
|
|
||||||
}
|
|
||||||
if (this.componentType instanceof ParameterizedType) {
|
|
||||||
this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType();
|
|
||||||
} else {
|
|
||||||
this.componentClass = (Class) this.componentType;
|
|
||||||
}
|
|
||||||
factory.register(type, this);
|
|
||||||
this.decoder = factory.loadDecoder(this.componentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T[] convertFrom(Reader in) {
|
|
||||||
final int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
final Decodeable<Reader, T> localdecoder = this.decoder;
|
|
||||||
final List<T> result = new ArrayList();
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
while (in.hasNext()) {
|
|
||||||
result.add(localdecoder.convertFrom(in));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
result.add(localdecoder.convertFrom(in));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
T[] rs = (T[]) Array.newInstance((Class) this.componentClass, result.size());
|
|
||||||
return result.toArray(rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.decoder + "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组.
|
|
||||||
* 数组长度不能超过 32767。 在BSON中数组长度设定的是short,对于大于32767长度的数组传输会影响性能,所以没有必要采用int存储。
|
|
||||||
* 支持一定程度的泛型。
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
|
||||||
|
|
||||||
private final Type type;
|
|
||||||
|
|
||||||
private final Type componentType;
|
|
||||||
|
|
||||||
private final Encodeable anyEncoder;
|
|
||||||
|
|
||||||
private final Encodeable<Writer, Object> encoder;
|
|
||||||
|
|
||||||
public ArrayEncoder(final Factory factory, final Type type) {
|
|
||||||
this.type = type;
|
|
||||||
if (type instanceof GenericArrayType) {
|
|
||||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
|
||||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
|
||||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
|
||||||
this.componentType = ((Class) type).getComponentType();
|
|
||||||
} else {
|
|
||||||
throw new ConvertException("(" + type + ") is not a array type");
|
|
||||||
}
|
|
||||||
factory.register(type, this);
|
|
||||||
this.encoder = factory.loadEncoder(this.componentType);
|
|
||||||
this.anyEncoder = factory.getAnyEncoder();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(Writer out, T[] value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.wirteClassName(null);
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (value.length == 0) {
|
|
||||||
out.writeArrayB(0);
|
|
||||||
out.writeArrayE();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(value.length);
|
|
||||||
final Type comp = this.componentType;
|
|
||||||
boolean first = true;
|
|
||||||
for (Object v : value) {
|
|
||||||
if (!first) out.writeArrayMark();
|
|
||||||
((v != null && v.getClass() == comp) ? encoder : anyEncoder).convertTo(out, v);
|
|
||||||
if (first) first = false;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.encoder + "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import org.redkale.util.Creator;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对象集合的反序列化.
|
|
||||||
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short,对于大于32767长度的集合传输会影响性能,所以没有采用int存储。
|
|
||||||
* 支持一定程度的泛型。
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> {
|
|
||||||
|
|
||||||
private final Type type;
|
|
||||||
|
|
||||||
private final Type componentType;
|
|
||||||
|
|
||||||
protected Creator<Collection<T>> creator;
|
|
||||||
|
|
||||||
private final Decodeable<Reader, T> decoder;
|
|
||||||
|
|
||||||
public CollectionDecoder(final Factory factory, final Type type) {
|
|
||||||
this.type = type;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
|
||||||
this.componentType = pt.getActualTypeArguments()[0];
|
|
||||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
|
||||||
factory.register(type, this);
|
|
||||||
this.decoder = factory.loadDecoder(this.componentType);
|
|
||||||
} else {
|
|
||||||
throw new ConvertException("collectiondecoder not support the type (" + type + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<T> convertFrom(Reader in) {
|
|
||||||
final int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
final Decodeable<Reader, T> localdecoder = this.decoder;
|
|
||||||
final Collection<T> result = this.creator.create();
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
while (in.hasNext()) {
|
|
||||||
result.add(localdecoder.convertFrom(in));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
result.add(localdecoder.convertFrom(in));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对象集合的序列化.
|
|
||||||
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short,对于大于32767长度的集合传输会影响性能,所以没有采用int存储。
|
|
||||||
* 支持一定程度的泛型。
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> {
|
|
||||||
|
|
||||||
private final Type type;
|
|
||||||
|
|
||||||
private final Encodeable<Writer, Object> encoder;
|
|
||||||
|
|
||||||
public CollectionEncoder(final Factory factory, final Type type) {
|
|
||||||
this.type = type;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
|
||||||
if (t instanceof TypeVariable) {
|
|
||||||
this.encoder = factory.getAnyEncoder();
|
|
||||||
} else {
|
|
||||||
this.encoder = factory.loadEncoder(t);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.encoder = factory.getAnyEncoder();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(Writer out, Collection<T> value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (value.isEmpty()) {
|
|
||||||
out.writeArrayB(0);
|
|
||||||
out.writeArrayE();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(value.size());
|
|
||||||
boolean first = true;
|
|
||||||
for (Object v : value) {
|
|
||||||
if (!first) out.writeArrayMark();
|
|
||||||
encoder.convertTo(out, v);
|
|
||||||
if (first) first = false;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 序列化操作类
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public abstract class Convert<R extends Reader, W extends Writer> {
|
|
||||||
|
|
||||||
protected final Factory<R, W> factory;
|
|
||||||
|
|
||||||
protected Convert(Factory<R, W> factory) {
|
|
||||||
this.factory = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Factory<R, W> getFactory() {
|
|
||||||
return this.factory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 依附在setter、getter方法、字段进行简单的配置
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Documented
|
|
||||||
@Target({METHOD, FIELD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Repeatable(ConvertColumns.class)
|
|
||||||
public @interface ConvertColumn {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 给字段取个别名, 只对JSON有效
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
String name() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析/序列化时是否屏蔽该字段
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
boolean ignore() default false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析/序列化定制化的TYPE
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
ConvertType type() default ConvertType.ALL;
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ConvertColumn 对应的实体类
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class ConvertColumnEntry {
|
|
||||||
|
|
||||||
private String name = "";
|
|
||||||
|
|
||||||
private boolean ignore;
|
|
||||||
|
|
||||||
private ConvertType convertType;
|
|
||||||
|
|
||||||
public ConvertColumnEntry() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConvertColumnEntry(ConvertColumn column) {
|
|
||||||
if (column == null) return;
|
|
||||||
this.name = column.name();
|
|
||||||
this.ignore = column.ignore();
|
|
||||||
this.convertType = column.type();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConvertColumnEntry(String name, boolean ignore) {
|
|
||||||
this.name = name;
|
|
||||||
this.ignore = ignore;
|
|
||||||
this.convertType = ConvertType.ALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConvertColumnEntry(String name, boolean ignore, ConvertType convertType) {
|
|
||||||
this.name = name;
|
|
||||||
this.ignore = ignore;
|
|
||||||
this.convertType = convertType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String name() {
|
|
||||||
return name == null ? "" : name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean ignore() {
|
|
||||||
return ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIgnore(boolean ignore) {
|
|
||||||
this.ignore = ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConvertType type() {
|
|
||||||
return convertType == null ? ConvertType.ALL : convertType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setConvertType(ConvertType convertType) {
|
|
||||||
this.convertType = convertType;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ConvertColumn 的多用类
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Documented
|
|
||||||
@Target({METHOD, FIELD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
public @interface ConvertColumns {
|
|
||||||
|
|
||||||
ConvertColumn[] value();
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用于类名的别名, 类似javax.persistence.Table
|
|
||||||
* 该值必须是全局唯一
|
|
||||||
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.wirteClassName(String value) 。
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Documented
|
|
||||||
@Target({TYPE})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
public @interface ConvertEntity {
|
|
||||||
|
|
||||||
String value();
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this template, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public class ConvertException extends RuntimeException {
|
|
||||||
|
|
||||||
public ConvertException() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConvertException(String s) {
|
|
||||||
super(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConvertException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConvertException(Throwable cause) {
|
|
||||||
super(cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public enum ConvertType {
|
|
||||||
|
|
||||||
JSON(1),
|
|
||||||
BSON(2),
|
|
||||||
ALL(127);
|
|
||||||
|
|
||||||
private final int value;
|
|
||||||
|
|
||||||
private ConvertType(int v) {
|
|
||||||
this.value = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(ConvertType type) {
|
|
||||||
if (type == null) return false;
|
|
||||||
return this.value >= type.value && (this.value & type.value) > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import org.redkale.util.Attribute;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <T>
|
|
||||||
* @param <F>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class DeMember<R extends Reader, T, F> implements Comparable<DeMember<R, T, F>> {
|
|
||||||
|
|
||||||
protected final Attribute<T, F> attribute;
|
|
||||||
|
|
||||||
protected Decodeable<R, F> decoder;
|
|
||||||
|
|
||||||
public DeMember(final Attribute<T, F> attribute) {
|
|
||||||
this.attribute = attribute;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeMember(Attribute<T, F> attribute, Decodeable<R, F> decoder) {
|
|
||||||
this(attribute);
|
|
||||||
this.decoder = decoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void read(R in, T obj) {
|
|
||||||
this.attribute.set(obj, decoder.convertFrom(in));
|
|
||||||
}
|
|
||||||
|
|
||||||
public final F read(R in) {
|
|
||||||
return decoder.convertFrom(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Attribute<T, F> getAttribute() {
|
|
||||||
return this.attribute;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int compareTo(DeMember<R, T, F> o) {
|
|
||||||
if (o == null) return 1;
|
|
||||||
return this.attribute.field().compareTo(o.attribute.field());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) return true;
|
|
||||||
if (!(obj instanceof DeMember)) return false;
|
|
||||||
DeMember other = (DeMember) obj;
|
|
||||||
return compareTo(other) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.attribute.field().hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "DeMember{" + "attribute=" + attribute.field() + ", decoder=" + decoder + '}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public interface Decodeable<R extends Reader, T> {
|
|
||||||
|
|
||||||
public T convertFrom(final R in);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 泛型映射接口
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Type getType();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import org.redkale.util.Attribute;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <W>
|
|
||||||
* @param <T>
|
|
||||||
* @param <F>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class EnMember<W extends Writer, T, F> implements Comparable<EnMember<W, T, F>> {
|
|
||||||
|
|
||||||
private final Attribute<T, F> attribute;
|
|
||||||
|
|
||||||
final Encodeable<W, F> encoder;
|
|
||||||
|
|
||||||
private final boolean istring;
|
|
||||||
|
|
||||||
//private final boolean isnumber;
|
|
||||||
private final boolean isbool;
|
|
||||||
|
|
||||||
public EnMember(Attribute<T, F> attribute, Encodeable<W, F> encoder) {
|
|
||||||
this.attribute = attribute;
|
|
||||||
this.encoder = encoder;
|
|
||||||
Class t = attribute.type();
|
|
||||||
this.istring = CharSequence.class.isAssignableFrom(t);
|
|
||||||
this.isbool = t == Boolean.class || t == boolean.class;
|
|
||||||
//this.isnumber = Number.class.isAssignableFrom(t) || (!this.isbool && t.isPrimitive());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean write(final W out, final boolean comma, final T obj) {
|
|
||||||
F value = attribute.get(obj);
|
|
||||||
if (value == null) return comma;
|
|
||||||
if (out.isTiny()) {
|
|
||||||
if (istring) {
|
|
||||||
if (((CharSequence) value).length() == 0) return comma;
|
|
||||||
} else if (isbool) {
|
|
||||||
if (!((Boolean) value)) return comma;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out.writeField(comma, attribute);
|
|
||||||
encoder.convertTo(out, value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int compareTo(EnMember<W, T, F> o) {
|
|
||||||
if (o == null) return 1;
|
|
||||||
return this.attribute.field().compareTo(o.attribute.field());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) return true;
|
|
||||||
if (!(obj instanceof EnMember)) return false;
|
|
||||||
EnMember other = (EnMember) obj;
|
|
||||||
return compareTo(other) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.attribute.field().hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "EnMember{" + "attribute=" + attribute.field() + ", encoder=" + encoder + '}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <W>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public interface Encodeable<W extends Writer, T> {
|
|
||||||
|
|
||||||
public void convertTo(final W out, T value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 泛型映射接口
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Type getType();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,448 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.net.*;
|
|
||||||
import java.nio.channels.*;
|
|
||||||
import static org.redkale.convert.ext.InetAddressSimpledCoder.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import java.util.regex.*;
|
|
||||||
import org.redkale.convert.ext.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
import org.redkale.util.Creator.Creators;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public abstract class Factory<R extends Reader, W extends Writer> {
|
|
||||||
|
|
||||||
private final Factory parent;
|
|
||||||
|
|
||||||
protected Convert<R, W> convert;
|
|
||||||
|
|
||||||
protected boolean tiny;
|
|
||||||
|
|
||||||
private final Encodeable<W, ?> anyEncoder = new AnyEncoder(this);
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
|
||||||
private final ConcurrentHashMap<Class, Creator> creators = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
private final Map<String, Class> entitys = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
private final ConcurrentHashMap<Type, Decodeable<R, ?>> decoders = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
private final ConcurrentHashMap<Type, Encodeable<W, ?>> encoders = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
private final HashMap<AccessibleObject, ConvertColumnEntry> columnEntrys = new HashMap();
|
|
||||||
|
|
||||||
private final Set<Class> skipIgnores = new HashSet();
|
|
||||||
|
|
||||||
private boolean skipAllIgnore = false;
|
|
||||||
|
|
||||||
protected Factory(Factory<R, W> parent, boolean tiny) {
|
|
||||||
this.tiny = tiny;
|
|
||||||
this.parent = parent;
|
|
||||||
if (parent == null) {
|
|
||||||
//---------------------------------------------------------
|
|
||||||
this.register(boolean.class, BoolSimpledCoder.instance);
|
|
||||||
this.register(Boolean.class, BoolSimpledCoder.instance);
|
|
||||||
|
|
||||||
this.register(byte.class, ByteSimpledCoder.instance);
|
|
||||||
this.register(Byte.class, ByteSimpledCoder.instance);
|
|
||||||
|
|
||||||
this.register(short.class, ShortSimpledCoder.instance);
|
|
||||||
this.register(Short.class, ShortSimpledCoder.instance);
|
|
||||||
|
|
||||||
this.register(char.class, CharSimpledCoder.instance);
|
|
||||||
this.register(Character.class, CharSimpledCoder.instance);
|
|
||||||
|
|
||||||
this.register(int.class, IntSimpledCoder.instance);
|
|
||||||
this.register(Integer.class, IntSimpledCoder.instance);
|
|
||||||
|
|
||||||
this.register(long.class, LongSimpledCoder.instance);
|
|
||||||
this.register(Long.class, LongSimpledCoder.instance);
|
|
||||||
|
|
||||||
this.register(float.class, FloatSimpledCoder.instance);
|
|
||||||
this.register(Float.class, FloatSimpledCoder.instance);
|
|
||||||
|
|
||||||
this.register(double.class, DoubleSimpledCoder.instance);
|
|
||||||
this.register(Double.class, DoubleSimpledCoder.instance);
|
|
||||||
|
|
||||||
this.register(Number.class, NumberSimpledCoder.instance);
|
|
||||||
this.register(String.class, StringSimpledCoder.instance);
|
|
||||||
this.register(CharSequence.class, CharSequenceSimpledCoder.instance);
|
|
||||||
this.register(java.util.Date.class, DateSimpledCoder.instance);
|
|
||||||
this.register(BigInteger.class, BigIntegerSimpledCoder.instance);
|
|
||||||
this.register(InetAddress.class, InetAddressSimpledCoder.instance);
|
|
||||||
this.register(DLong.class, DLongSimpledCoder.instance);
|
|
||||||
this.register(Class.class, TypeSimpledCoder.instance);
|
|
||||||
this.register(InetSocketAddress.class, InetSocketAddressSimpledCoder.instance);
|
|
||||||
this.register(Pattern.class, PatternSimpledCoder.instance);
|
|
||||||
this.register(CompletionHandler.class, CompletionHandlerSimpledCoder.instance);
|
|
||||||
//---------------------------------------------------------
|
|
||||||
this.register(boolean[].class, BoolArraySimpledCoder.instance);
|
|
||||||
this.register(byte[].class, ByteArraySimpledCoder.instance);
|
|
||||||
this.register(short[].class, ShortArraySimpledCoder.instance);
|
|
||||||
this.register(char[].class, CharArraySimpledCoder.instance);
|
|
||||||
this.register(int[].class, IntArraySimpledCoder.instance);
|
|
||||||
this.register(long[].class, LongArraySimpledCoder.instance);
|
|
||||||
this.register(float[].class, FloatArraySimpledCoder.instance);
|
|
||||||
this.register(double[].class, DoubleArraySimpledCoder.instance);
|
|
||||||
this.register(String[].class, StringArraySimpledCoder.instance);
|
|
||||||
//---------------------------------------------------------
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Factory parent() {
|
|
||||||
return this.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract ConvertType getConvertType();
|
|
||||||
|
|
||||||
public abstract boolean isReversible();
|
|
||||||
|
|
||||||
public abstract Factory createChild();
|
|
||||||
|
|
||||||
public abstract Factory createChild(boolean tiny);
|
|
||||||
|
|
||||||
public Convert getConvert() {
|
|
||||||
return convert;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTiny(boolean tiny) {
|
|
||||||
this.tiny = tiny;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConvertColumnEntry findRef(AccessibleObject field) {
|
|
||||||
if (field == null) return null;
|
|
||||||
ConvertColumnEntry en = this.columnEntrys.get(field);
|
|
||||||
if (en != null) return en;
|
|
||||||
final ConvertType ct = this.getConvertType();
|
|
||||||
final ConvertColumns ccs = field.getAnnotation(ConvertColumns.class);
|
|
||||||
final ConvertColumn cc = field.getAnnotation(ConvertColumn.class);
|
|
||||||
if (ccs == null && cc == null) return null;
|
|
||||||
final ConvertColumn[] cca = (ccs == null) ? new ConvertColumn[]{cc} : ccs.value();
|
|
||||||
for (ConvertColumn ref : cca) {
|
|
||||||
if (ref.type().contains(ct)) {
|
|
||||||
ConvertColumnEntry entry = new ConvertColumnEntry(ref);
|
|
||||||
if (skipAllIgnore) {
|
|
||||||
entry.setIgnore(false);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
if (skipIgnores.isEmpty()) return entry;
|
|
||||||
if (skipIgnores.contains(((Member) field).getDeclaringClass())) entry.setIgnore(false);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String getEntity(Class clazz) {
|
|
||||||
ConvertEntity ce = (ConvertEntity) clazz.getAnnotation(ConvertEntity.class);
|
|
||||||
if (ce != null && findEntity(ce.value()) == null) entitys.put(ce.value(), clazz);
|
|
||||||
return ce == null ? clazz.getName() : ce.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class findEntity(String name) {
|
|
||||||
Class clazz = entitys.get(name);
|
|
||||||
return parent == null ? clazz : parent.findEntity(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Class getEntity(String name) {
|
|
||||||
Class clazz = findEntity(name);
|
|
||||||
try {
|
|
||||||
return clazz == null ? Class.forName(name) : clazz;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new ConvertException("convert entity is " + name, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
|
|
||||||
* <p>
|
|
||||||
* @param skipIgnore
|
|
||||||
*/
|
|
||||||
public final void registerSkipAllIgnore(final boolean skipIgnore) {
|
|
||||||
this.skipAllIgnore = skipIgnore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使该类所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
|
|
||||||
* <p>
|
|
||||||
* @param type
|
|
||||||
*/
|
|
||||||
public final void registerSkipIgnore(final Class type) {
|
|
||||||
skipIgnores.add(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void register(final Class type, boolean ignore, String... columns) {
|
|
||||||
for (String column : columns) {
|
|
||||||
register(type, column, new ConvertColumnEntry(column, ignore));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean register(final Class type, String column, ConvertColumnEntry entry) {
|
|
||||||
if (type == null || column == null || entry == null) return false;
|
|
||||||
try {
|
|
||||||
final Field field = type.getDeclaredField(column);
|
|
||||||
String get = "get";
|
|
||||||
if (field.getType() == boolean.class || field.getType() == Boolean.class) get = "is";
|
|
||||||
char[] cols = column.toCharArray();
|
|
||||||
cols[0] = Character.toUpperCase(cols[0]);
|
|
||||||
String col2 = new String(cols);
|
|
||||||
try {
|
|
||||||
register(type.getMethod(get + col2), entry);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
register(type.getMethod("set" + col2, field.getType()), entry);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
return register(field, entry);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> boolean register(final AccessibleObject field, final ConvertColumnEntry entry) {
|
|
||||||
if (field == null || entry == null) return false;
|
|
||||||
this.columnEntrys.put(field, entry);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> void register(final Class<E> clazz, final Creator<? extends E> creator) {
|
|
||||||
creators.put(clazz, creator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <T> Creator<T> findCreator(Class<T> type) {
|
|
||||||
Creator<T> creator = creators.get(type);
|
|
||||||
if (creator != null) return creator;
|
|
||||||
return this.parent == null ? null : this.parent.findCreator(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <T> Creator<T> loadCreator(Class<T> type) {
|
|
||||||
Creator result = findCreator(type);
|
|
||||||
if (result == null) {
|
|
||||||
result = Creators.create(type);
|
|
||||||
creators.put(type, result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
public final <E> Encodeable<W, E> getAnyEncoder() {
|
|
||||||
return (Encodeable<W, E>) anyEncoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> void register(final Type clazz, final SimpledCoder<R, W, E> coder) {
|
|
||||||
decoders.put(clazz, coder);
|
|
||||||
encoders.put(clazz, coder);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> void register(final Type clazz, final Decodeable<R, E> decoder) {
|
|
||||||
decoders.put(clazz, decoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> void register(final Type clazz, final Encodeable<W, E> printer) {
|
|
||||||
encoders.put(clazz, printer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> Decodeable<R, E> findDecoder(final Type type) {
|
|
||||||
Decodeable<R, E> rs = (Decodeable<R, E>) decoders.get(type);
|
|
||||||
if (rs != null) return rs;
|
|
||||||
return this.parent == null ? null : this.parent.findDecoder(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> Encodeable<W, E> findEncoder(final Type type) {
|
|
||||||
Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
|
|
||||||
if (rs != null) return rs;
|
|
||||||
return this.parent == null ? null : this.parent.findEncoder(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> Decodeable<R, E> loadDecoder(final Type type) {
|
|
||||||
Decodeable<R, E> decoder = findDecoder(type);
|
|
||||||
if (decoder != null) return decoder;
|
|
||||||
if (type instanceof GenericArrayType) return new ArrayDecoder(this, type);
|
|
||||||
Class clazz;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
final ParameterizedType pts = (ParameterizedType) type;
|
|
||||||
clazz = (Class) (pts).getRawType();
|
|
||||||
} else if (type instanceof TypeVariable) { // e.g. <? extends E>
|
|
||||||
final TypeVariable tv = (TypeVariable) type;
|
|
||||||
Class cz = tv.getBounds().length == 0 ? Object.class : null;
|
|
||||||
for (Type f : tv.getBounds()) {
|
|
||||||
if (f instanceof Class) {
|
|
||||||
cz = (Class) f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clazz = cz;
|
|
||||||
if (cz == null) throw new ConvertException("not support the type (" + type + ")");
|
|
||||||
} else if (type instanceof WildcardType) { // e.g. <? extends Serializable>
|
|
||||||
final WildcardType wt = (WildcardType) type;
|
|
||||||
Class cz = null;
|
|
||||||
for (Type f : wt.getUpperBounds()) {
|
|
||||||
if (f instanceof Class) {
|
|
||||||
cz = (Class) f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clazz = cz;
|
|
||||||
if (cz == null) throw new ConvertException("not support the type (" + type + ")");
|
|
||||||
} else if (type instanceof Class) {
|
|
||||||
clazz = (Class) type;
|
|
||||||
} else {
|
|
||||||
throw new ConvertException("not support the type (" + type + ")");
|
|
||||||
}
|
|
||||||
decoder = findDecoder(clazz);
|
|
||||||
if (decoder != null) return decoder;
|
|
||||||
return createDecoder(type, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> Decodeable<R, E> createDecoder(final Type type) {
|
|
||||||
Class clazz;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
final ParameterizedType pts = (ParameterizedType) type;
|
|
||||||
clazz = (Class) (pts).getRawType();
|
|
||||||
} else if (type instanceof Class) {
|
|
||||||
clazz = (Class) type;
|
|
||||||
} else {
|
|
||||||
throw new ConvertException("not support the type (" + type + ")");
|
|
||||||
}
|
|
||||||
return createDecoder(type, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
private <E> Decodeable<R, E> createDecoder(final Type type, final Class clazz) {
|
|
||||||
Decodeable<R, E> decoder = null;
|
|
||||||
ObjectDecoder od = null;
|
|
||||||
if (clazz.isEnum()) {
|
|
||||||
decoder = new EnumSimpledCoder(clazz);
|
|
||||||
} else if (clazz.isArray()) {
|
|
||||||
decoder = new ArrayDecoder(this, type);
|
|
||||||
} else if (Collection.class.isAssignableFrom(clazz)) {
|
|
||||||
decoder = new CollectionDecoder(this, type);
|
|
||||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
|
||||||
decoder = new MapDecoder(this, type);
|
|
||||||
} else if (clazz == Object.class) {
|
|
||||||
od = new ObjectDecoder(type);
|
|
||||||
decoder = od;
|
|
||||||
} else if (!clazz.getName().startsWith("java.")) {
|
|
||||||
SimpledCoder simpleCoder = null;
|
|
||||||
for (final Method method : clazz.getDeclaredMethods()) {
|
|
||||||
if (!Modifier.isStatic(method.getModifiers())) continue;
|
|
||||||
if (method.getParameterTypes().length != 0) continue;
|
|
||||||
if (method.getReturnType() != SimpledCoder.class) continue;
|
|
||||||
try {
|
|
||||||
method.setAccessible(true);
|
|
||||||
simpleCoder = (SimpledCoder) method.invoke(null);
|
|
||||||
break;
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (simpleCoder == null) {
|
|
||||||
od = new ObjectDecoder(type);
|
|
||||||
decoder = od;
|
|
||||||
} else {
|
|
||||||
decoder = simpleCoder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (decoder == null) throw new ConvertException("not support the type (" + type + ")");
|
|
||||||
register(type, decoder);
|
|
||||||
if (od != null) od.init(this);
|
|
||||||
return decoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> Encodeable<W, E> loadEncoder(final Type type) {
|
|
||||||
Encodeable<W, E> encoder = findEncoder(type);
|
|
||||||
if (encoder != null) return encoder;
|
|
||||||
if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
|
|
||||||
Class clazz;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
final ParameterizedType pts = (ParameterizedType) type;
|
|
||||||
clazz = (Class) (pts).getRawType();
|
|
||||||
} else if (type instanceof TypeVariable) {
|
|
||||||
TypeVariable tv = (TypeVariable) type;
|
|
||||||
Type t = Object.class;
|
|
||||||
if (tv.getBounds().length == 1) {
|
|
||||||
t = tv.getBounds()[0];
|
|
||||||
}
|
|
||||||
if (!(t instanceof Class)) t = Object.class;
|
|
||||||
clazz = (Class) t;
|
|
||||||
} else if (type instanceof Class) {
|
|
||||||
clazz = (Class) type;
|
|
||||||
} else {
|
|
||||||
throw new ConvertException("not support the type (" + type + ")");
|
|
||||||
}
|
|
||||||
encoder = findEncoder(clazz);
|
|
||||||
if (encoder != null) return encoder;
|
|
||||||
return createEncoder(type, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <E> Encodeable<W, E> createEncoder(final Type type) {
|
|
||||||
Class clazz;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
final ParameterizedType pts = (ParameterizedType) type;
|
|
||||||
clazz = (Class) (pts).getRawType();
|
|
||||||
} else if (type instanceof Class) {
|
|
||||||
clazz = (Class) type;
|
|
||||||
} else {
|
|
||||||
throw new ConvertException("not support the type (" + type + ")");
|
|
||||||
}
|
|
||||||
return createEncoder(type, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
private <E> Encodeable<W, E> createEncoder(final Type type, final Class clazz) {
|
|
||||||
Encodeable<W, E> encoder = null;
|
|
||||||
ObjectEncoder oe = null;
|
|
||||||
if (clazz.isEnum()) {
|
|
||||||
encoder = new EnumSimpledCoder(clazz);
|
|
||||||
} else if (clazz.isArray()) {
|
|
||||||
encoder = new ArrayEncoder(this, type);
|
|
||||||
} else if (Collection.class.isAssignableFrom(clazz)) {
|
|
||||||
encoder = new CollectionEncoder(this, type);
|
|
||||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
|
||||||
encoder = new MapEncoder(this, type);
|
|
||||||
} else if (clazz == Object.class) {
|
|
||||||
return (Encodeable<W, E>) this.anyEncoder;
|
|
||||||
} else if (!clazz.getName().startsWith("java.")) {
|
|
||||||
SimpledCoder simpleCoder = null;
|
|
||||||
for (final Method method : clazz.getDeclaredMethods()) {
|
|
||||||
if (!Modifier.isStatic(method.getModifiers())) continue;
|
|
||||||
if (method.getParameterTypes().length != 0) continue;
|
|
||||||
if (method.getReturnType() != SimpledCoder.class) continue;
|
|
||||||
try {
|
|
||||||
method.setAccessible(true);
|
|
||||||
simpleCoder = (SimpledCoder) method.invoke(null);
|
|
||||||
break;
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (simpleCoder == null) {
|
|
||||||
oe = new ObjectEncoder(type);
|
|
||||||
encoder = oe;
|
|
||||||
} else {
|
|
||||||
encoder = simpleCoder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (encoder == null) throw new ConvertException("not support the type (" + type + ")");
|
|
||||||
register(type, encoder);
|
|
||||||
if (oe != null) oe.init(this);
|
|
||||||
return encoder;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import org.redkale.util.Creator;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <K>
|
|
||||||
* @param <V>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
|
|
||||||
|
|
||||||
private final Type type;
|
|
||||||
|
|
||||||
private final Type keyType;
|
|
||||||
|
|
||||||
private final Type valueType;
|
|
||||||
|
|
||||||
protected Creator<Map<K, V>> creator;
|
|
||||||
|
|
||||||
private final Decodeable<Reader, K> keyDecoder;
|
|
||||||
|
|
||||||
private final Decodeable<Reader, V> valueDecoder;
|
|
||||||
|
|
||||||
public MapDecoder(final Factory factory, final Type type) {
|
|
||||||
this.type = type;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
|
||||||
this.keyType = pt.getActualTypeArguments()[0];
|
|
||||||
this.valueType = pt.getActualTypeArguments()[1];
|
|
||||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
|
||||||
factory.register(type, this);
|
|
||||||
this.keyDecoder = factory.loadDecoder(this.keyType);
|
|
||||||
this.valueDecoder = factory.loadDecoder(this.valueType);
|
|
||||||
} else {
|
|
||||||
throw new ConvertException("mapdecoder not support the type (" + type + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<K, V> convertFrom(Reader in) {
|
|
||||||
final int len = in.readMapB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
final Map<K, V> result = this.creator.create();
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
while (in.hasNext()) {
|
|
||||||
K key = keyDecoder.convertFrom(in);
|
|
||||||
in.skipBlank();
|
|
||||||
V value = valueDecoder.convertFrom(in);
|
|
||||||
result.put(key, value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
K key = keyDecoder.convertFrom(in);
|
|
||||||
in.skipBlank();
|
|
||||||
V value = valueDecoder.convertFrom(in);
|
|
||||||
result.put(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in.readMapE();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return this.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <K>
|
|
||||||
* @param <V>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
|
|
||||||
|
|
||||||
private final Type type;
|
|
||||||
|
|
||||||
private final Encodeable<Writer, K> keyencoder;
|
|
||||||
|
|
||||||
private final Encodeable<Writer, V> valencoder;
|
|
||||||
|
|
||||||
public MapEncoder(final Factory factory, final Type type) {
|
|
||||||
this.type = type;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
|
|
||||||
this.keyencoder = factory.loadEncoder(pt[0]);
|
|
||||||
this.valencoder = factory.loadEncoder(pt[1]);
|
|
||||||
} else {
|
|
||||||
this.keyencoder = factory.getAnyEncoder();
|
|
||||||
this.valencoder = factory.getAnyEncoder();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(Writer out, Map<K, V> value) {
|
|
||||||
final Map<K, V> values = value;
|
|
||||||
if (values == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeMapB(values.size());
|
|
||||||
boolean first = true;
|
|
||||||
for (Map.Entry<K, V> en : values.entrySet()) {
|
|
||||||
if (!first) out.writeArrayMark();
|
|
||||||
this.keyencoder.convertTo(out, en.getKey());
|
|
||||||
out.writeMapMark();
|
|
||||||
this.valencoder.convertTo(out, en.getValue());
|
|
||||||
if (first) first = false;
|
|
||||||
}
|
|
||||||
out.writeMapE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,237 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import org.redkale.util.Creator;
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T> {
|
|
||||||
|
|
||||||
protected final Type type;
|
|
||||||
|
|
||||||
protected final Class typeClass;
|
|
||||||
|
|
||||||
protected Creator<T> creator;
|
|
||||||
|
|
||||||
protected DeMember<R, T, ?>[] creatorConstructorMembers;
|
|
||||||
|
|
||||||
protected DeMember<R, T, ?>[] members;
|
|
||||||
|
|
||||||
protected Factory factory;
|
|
||||||
|
|
||||||
private boolean inited = false;
|
|
||||||
|
|
||||||
private final Object lock = new Object();
|
|
||||||
|
|
||||||
protected ObjectDecoder(Type type) {
|
|
||||||
this.type = ((type instanceof Class) && ((Class) type).isInterface()) ? Object.class : type;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
|
||||||
this.typeClass = (Class) pt.getRawType();
|
|
||||||
} else {
|
|
||||||
this.typeClass = (Class) type;
|
|
||||||
}
|
|
||||||
this.members = new DeMember[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init(final Factory factory) {
|
|
||||||
this.factory = factory;
|
|
||||||
try {
|
|
||||||
if (type == Object.class) return;
|
|
||||||
|
|
||||||
Class clazz = null;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
final ParameterizedType pts = (ParameterizedType) type;
|
|
||||||
clazz = (Class) (pts).getRawType();
|
|
||||||
} else if (!(type instanceof Class)) {
|
|
||||||
throw new ConvertException("[" + type + "] is no a class");
|
|
||||||
} else {
|
|
||||||
clazz = (Class) type;
|
|
||||||
}
|
|
||||||
this.creator = factory.loadCreator(clazz);
|
|
||||||
|
|
||||||
final Set<DeMember> list = new HashSet();
|
|
||||||
final String[] cps = ObjectEncoder.findConstructorProperties(this.creator);
|
|
||||||
try {
|
|
||||||
ConvertColumnEntry ref;
|
|
||||||
for (final Field field : clazz.getFields()) {
|
|
||||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
|
||||||
ref = factory.findRef(field);
|
|
||||||
if (ref != null && ref.ignore()) continue;
|
|
||||||
Type t = ObjectEncoder.createClassType(field.getGenericType(), this.type);
|
|
||||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t)));
|
|
||||||
}
|
|
||||||
final boolean reversible = factory.isReversible();
|
|
||||||
for (final Method method : clazz.getMethods()) {
|
|
||||||
if (Modifier.isStatic(method.getModifiers())) continue;
|
|
||||||
if (Modifier.isAbstract(method.getModifiers())) continue;
|
|
||||||
if (method.isSynthetic()) continue;
|
|
||||||
if (method.getName().length() < 4) continue;
|
|
||||||
if (!method.getName().startsWith("set")) continue;
|
|
||||||
if (method.getParameterTypes().length != 1) continue;
|
|
||||||
if (method.getReturnType() != void.class) continue;
|
|
||||||
if (reversible && (cps == null || !ObjectEncoder.contains(cps, ObjectEncoder.readGetSetFieldName(method)))) {
|
|
||||||
boolean is = method.getParameterTypes()[0] == boolean.class || method.getParameterTypes()[0] == Boolean.class;
|
|
||||||
try {
|
|
||||||
clazz.getMethod(method.getName().replaceFirst("set", is ? "is" : "get"));
|
|
||||||
} catch (Exception e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ref = factory.findRef(method);
|
|
||||||
if (ref != null && ref.ignore()) continue;
|
|
||||||
Type t = ObjectEncoder.createClassType(method.getGenericParameterTypes()[0], this.type);
|
|
||||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t)));
|
|
||||||
}
|
|
||||||
if (cps != null) { //可能存在某些构造函数中的字段名不存在setter方法
|
|
||||||
for (final String constructorField : cps) {
|
|
||||||
boolean flag = false;
|
|
||||||
for (DeMember m : list) {
|
|
||||||
if (m.attribute.field().equals(constructorField)) {
|
|
||||||
flag = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (flag) continue;
|
|
||||||
//不存在setter方法
|
|
||||||
try {
|
|
||||||
Field f = clazz.getDeclaredField(constructorField);
|
|
||||||
Type t = ObjectEncoder.createClassType(f.getGenericType(), this.type);
|
|
||||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, f, null, null), factory.loadDecoder(t)));
|
|
||||||
} catch (NoSuchFieldException nsfe) { //不存在field, 可能存在getter方法
|
|
||||||
char[] fs = constructorField.toCharArray();
|
|
||||||
fs[0] = Character.toUpperCase(fs[0]);
|
|
||||||
String mn = new String(fs);
|
|
||||||
Method getter;
|
|
||||||
try {
|
|
||||||
getter = clazz.getMethod("get" + mn);
|
|
||||||
} catch (NoSuchMethodException ex) {
|
|
||||||
getter = clazz.getMethod("is" + mn);
|
|
||||||
}
|
|
||||||
Type t = ObjectEncoder.createClassType(getter.getGenericParameterTypes()[0], this.type);
|
|
||||||
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, getter, null), factory.loadDecoder(t)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.members = list.toArray(new DeMember[list.size()]);
|
|
||||||
Arrays.sort(this.members);
|
|
||||||
|
|
||||||
if (cps != null) {
|
|
||||||
final String[] fields = cps;
|
|
||||||
final DeMember<R, T, ?>[] ms = new DeMember[fields.length];
|
|
||||||
for (int i = 0; i < fields.length; i++) {
|
|
||||||
for (DeMember m : this.members) {
|
|
||||||
if (m.attribute.field().equals(fields[i])) {
|
|
||||||
ms[i] = m;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.creatorConstructorMembers = ms;
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new ConvertException(ex);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
inited = true;
|
|
||||||
synchronized (lock) {
|
|
||||||
lock.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对象格式: [0x1][short字段个数][字段名][字段值]...[0x2]
|
|
||||||
*
|
|
||||||
* @param in
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final T convertFrom(final R in) {
|
|
||||||
final String clazz = in.readClassName();
|
|
||||||
if (clazz != null && !clazz.isEmpty()) return (T) factory.loadDecoder(factory.getEntity(clazz)).convertFrom(in);
|
|
||||||
if (in.readObjectB() == Reader.SIGN_NULL) return null;
|
|
||||||
if (!this.inited) {
|
|
||||||
synchronized (lock) {
|
|
||||||
try {
|
|
||||||
lock.wait();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.creatorConstructorMembers == null) { //空构造函数
|
|
||||||
final T result = this.creator.create();
|
|
||||||
final AtomicInteger index = new AtomicInteger();
|
|
||||||
while (in.hasNext()) {
|
|
||||||
DeMember member = in.readField(index, members);
|
|
||||||
in.skipBlank();
|
|
||||||
if (member == null) {
|
|
||||||
in.skipValue(); //跳过该属性的值
|
|
||||||
} else {
|
|
||||||
member.read(in, result);
|
|
||||||
}
|
|
||||||
index.incrementAndGet();
|
|
||||||
}
|
|
||||||
in.readObjectE();
|
|
||||||
return result;
|
|
||||||
} else { //带参数的构造函数
|
|
||||||
final DeMember<R, T, ?>[] fields = this.creatorConstructorMembers;
|
|
||||||
final Object[] constructorParams = new Object[fields.length];
|
|
||||||
final Object[][] otherParams = new Object[this.members.length][2];
|
|
||||||
final AtomicInteger index = new AtomicInteger();
|
|
||||||
int oc = 0;
|
|
||||||
while (in.hasNext()) {
|
|
||||||
DeMember member = in.readField(index, members);
|
|
||||||
in.skipBlank();
|
|
||||||
if (member == null) {
|
|
||||||
in.skipValue(); //跳过该属性的值
|
|
||||||
} else {
|
|
||||||
Object val = member.read(in);
|
|
||||||
boolean flag = true;
|
|
||||||
for (int i = 0; i < fields.length; i++) {
|
|
||||||
if (member == fields[i]) {
|
|
||||||
constructorParams[i] = val;
|
|
||||||
flag = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (flag) otherParams[oc++] = new Object[]{member.attribute, val};
|
|
||||||
}
|
|
||||||
index.incrementAndGet();
|
|
||||||
}
|
|
||||||
in.readObjectE();
|
|
||||||
final T result = this.creator.create(constructorParams);
|
|
||||||
for (int i = 0; i < oc; i++) {
|
|
||||||
((Attribute) otherParams[i][0]).set(result, otherParams[i][1]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Type getType() {
|
|
||||||
return this.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ObjectDecoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,280 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import org.redkale.util.Attribute;
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.util.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
import org.redkale.util.Attribute.Attributes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <W>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
|
|
||||||
|
|
||||||
static final Type[] TYPEZERO = new Type[0];
|
|
||||||
|
|
||||||
protected final Type type;
|
|
||||||
|
|
||||||
protected final Class typeClass;
|
|
||||||
|
|
||||||
protected EnMember[] members;
|
|
||||||
|
|
||||||
protected Factory factory;
|
|
||||||
|
|
||||||
private boolean inited = false;
|
|
||||||
|
|
||||||
private final Object lock = new Object();
|
|
||||||
|
|
||||||
protected ObjectEncoder(Type type) {
|
|
||||||
this.type = type;
|
|
||||||
if (type instanceof ParameterizedType) {
|
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
|
||||||
this.typeClass = (Class) pt.getRawType();
|
|
||||||
} else {
|
|
||||||
this.typeClass = (Class) type;
|
|
||||||
}
|
|
||||||
this.members = new EnMember[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init(final Factory factory) {
|
|
||||||
this.factory = factory;
|
|
||||||
try {
|
|
||||||
if (type == Object.class) return;
|
|
||||||
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
|
|
||||||
final Class clazz = this.typeClass;
|
|
||||||
final Set<EnMember> list = new HashSet();
|
|
||||||
final String[] cps = ObjectEncoder.findConstructorProperties(factory.loadCreator(this.typeClass));
|
|
||||||
try {
|
|
||||||
ConvertColumnEntry ref;
|
|
||||||
for (final Field field : clazz.getFields()) {
|
|
||||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
|
||||||
ref = factory.findRef(field);
|
|
||||||
if (ref != null && ref.ignore()) continue;
|
|
||||||
Type t = createClassType(field.getGenericType(), this.type);
|
|
||||||
list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)));
|
|
||||||
}
|
|
||||||
final boolean reversible = factory.isReversible();
|
|
||||||
for (final Method method : clazz.getMethods()) {
|
|
||||||
if (Modifier.isStatic(method.getModifiers())) continue;
|
|
||||||
if (Modifier.isAbstract(method.getModifiers())) continue;
|
|
||||||
if (method.isSynthetic()) continue;
|
|
||||||
if (method.getName().length() < 3) continue;
|
|
||||||
if (method.getName().equals("getClass")) continue;
|
|
||||||
if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) continue;
|
|
||||||
if (method.getParameterTypes().length != 0) continue;
|
|
||||||
if (method.getReturnType() == void.class) continue;
|
|
||||||
if (reversible && (cps == null || !contains(cps, readGetSetFieldName(method)))) {
|
|
||||||
boolean is = method.getName().startsWith("is");
|
|
||||||
try {
|
|
||||||
clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType());
|
|
||||||
} catch (Exception e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ref = factory.findRef(method);
|
|
||||||
if (ref != null && ref.ignore()) continue;
|
|
||||||
Type t = createClassType(method.getGenericReturnType(), this.type);
|
|
||||||
list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)));
|
|
||||||
}
|
|
||||||
this.members = list.toArray(new EnMember[list.size()]);
|
|
||||||
Arrays.sort(this.members);
|
|
||||||
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new ConvertException(ex);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
inited = true;
|
|
||||||
synchronized (lock) {
|
|
||||||
lock.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void convertTo(W out, T value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.wirteClassName(null);
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.inited) {
|
|
||||||
synchronized (lock) {
|
|
||||||
try {
|
|
||||||
lock.wait();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (value != null && value.getClass() != this.typeClass) {
|
|
||||||
final Class clz = value.getClass();
|
|
||||||
out.wirteClassName(factory.getEntity(clz));
|
|
||||||
factory.loadEncoder(clz).convertTo(out, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeObjectB(members.length, value);
|
|
||||||
boolean comma = false;
|
|
||||||
for (EnMember member : members) {
|
|
||||||
comma = member.write(out, comma, value);
|
|
||||||
}
|
|
||||||
out.writeObjectE(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Type getType() {
|
|
||||||
return this.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
static Type createClassType(final Type type, final Type declaringType) {
|
|
||||||
if (TypeToken.isClassType(type)) return type;
|
|
||||||
//存在通配符则declaringType 必须是 ParameterizedType
|
|
||||||
if (!(declaringType instanceof ParameterizedType)) return Object.class;
|
|
||||||
if (type instanceof ParameterizedType) { // e.g. Map<String, String>
|
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
|
||||||
final Type[] paramTypes = pt.getActualTypeArguments();
|
|
||||||
for (int i = 0; i < paramTypes.length; i++) {
|
|
||||||
paramTypes[i] = createClassType(paramTypes[i], declaringType);
|
|
||||||
}
|
|
||||||
return TypeToken.createParameterizedType(pt.getOwnerType(), pt.getRawType(), paramTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
final ParameterizedType declaringPType = (ParameterizedType) declaringType;
|
|
||||||
final Type[] virTypes = ((Class) declaringPType.getRawType()).getTypeParameters();
|
|
||||||
final Type[] desTypes = declaringPType.getActualTypeArguments();
|
|
||||||
if (type instanceof WildcardType) { // e.g. <? extends Serializable>
|
|
||||||
final WildcardType wt = (WildcardType) type;
|
|
||||||
for (Type f : wt.getUpperBounds()) {
|
|
||||||
for (int i = 0; i < virTypes.length; i++) {
|
|
||||||
if (virTypes[i].equals(f)) return desTypes.length <= i ? Object.class : desTypes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type instanceof TypeVariable) { // e.g. <? extends E>
|
|
||||||
for (int i = 0; i < virTypes.length; i++) {
|
|
||||||
if (virTypes[i].equals(type)) return desTypes.length <= i ? Object.class : desTypes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
|
|
||||||
// if (type instanceof Class) { //e.g. String
|
|
||||||
// return type;
|
|
||||||
// } else if (type instanceof ParameterizedType) { //e.g. Map<String, String>
|
|
||||||
// final ParameterizedType pt = (ParameterizedType) type;
|
|
||||||
// Type[] paramTypes = pt.getActualTypeArguments();
|
|
||||||
// final Type[] newTypes = new Type[paramTypes.length];
|
|
||||||
// int count = 0;
|
|
||||||
// for (int i = 0; i < newTypes.length; i++) {
|
|
||||||
// newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes);
|
|
||||||
// if (paramTypes[i] == newTypes[i]) count++;
|
|
||||||
// }
|
|
||||||
// if (count == paramTypes.length) return pt;
|
|
||||||
// return new ParameterizedType() {
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public Type[] getActualTypeArguments() {
|
|
||||||
// return newTypes;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public Type getRawType() {
|
|
||||||
// return pt.getRawType();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public Type getOwnerType() {
|
|
||||||
// return pt.getOwnerType();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// if (realGenericTypes == null) return type;
|
|
||||||
// if (type instanceof WildcardType) { // e.g. <? extends Serializable>
|
|
||||||
// final WildcardType wt = (WildcardType) type;
|
|
||||||
// for (Type f : wt.getUpperBounds()) {
|
|
||||||
// for (int i = 0; i < virGenericTypes.length; i++) {
|
|
||||||
// if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else if (type instanceof TypeVariable) { // e.g. <? extends E>
|
|
||||||
// for (int i = 0; i < virGenericTypes.length; i++) {
|
|
||||||
// if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return type;
|
|
||||||
// }
|
|
||||||
|
|
||||||
static boolean contains(String[] values, String value) {
|
|
||||||
for (String str : values) {
|
|
||||||
if (str.equals(value)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static String readGetSetFieldName(Method method) {
|
|
||||||
if (method == null) return null;
|
|
||||||
String fname = method.getName();
|
|
||||||
if (!fname.startsWith("is") && !fname.startsWith("get") && !fname.startsWith("set")) return fname;
|
|
||||||
fname = fname.substring(fname.startsWith("is") ? 2 : 3);
|
|
||||||
if (fname.length() > 1 && !(fname.charAt(1) >= 'A' && fname.charAt(1) <= 'Z')) {
|
|
||||||
fname = Character.toLowerCase(fname.charAt(0)) + fname.substring(1);
|
|
||||||
} else if (fname.length() == 1) {
|
|
||||||
fname = "" + Character.toLowerCase(fname.charAt(0));
|
|
||||||
}
|
|
||||||
return fname;
|
|
||||||
}
|
|
||||||
|
|
||||||
static String[] findConstructorProperties(Creator creator) {
|
|
||||||
try {
|
|
||||||
Creator.ConstructorParameters cps = creator.getClass().getMethod("create", Object[].class).getAnnotation(Creator.ConstructorParameters.class);
|
|
||||||
return cps == null ? null : cps.value();
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Attribute createAttribute(final Factory factory, Class clazz, final Field field, final Method getter, final Method setter) {
|
|
||||||
String fieldalias = null;
|
|
||||||
if (field != null) { // public field
|
|
||||||
ConvertColumnEntry ref = factory.findRef(field);
|
|
||||||
fieldalias = ref == null || ref.name().isEmpty() ? field.getName() : ref.name();
|
|
||||||
} else if (getter != null) {
|
|
||||||
ConvertColumnEntry ref = factory.findRef(getter);
|
|
||||||
String mfieldname = readGetSetFieldName(getter);
|
|
||||||
if (ref == null) {
|
|
||||||
try {
|
|
||||||
ref = factory.findRef(clazz.getDeclaredField(mfieldname));
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name();
|
|
||||||
} else { // setter != null
|
|
||||||
ConvertColumnEntry ref = factory.findRef(setter);
|
|
||||||
String mfieldname = readGetSetFieldName(setter);
|
|
||||||
if (ref == null) {
|
|
||||||
try {
|
|
||||||
ref = factory.findRef(clazz.getDeclaredField(mfieldname));
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name();
|
|
||||||
}
|
|
||||||
return Attributes.create(clazz, fieldalias, field, getter, setter);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public interface Reader {
|
|
||||||
|
|
||||||
public static final short SIGN_NULL = -1;
|
|
||||||
|
|
||||||
public static final short SIGN_NOLENGTH = -2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否还存在下个元素或字段
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean hasNext();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳过值(不包含值前面的字段)
|
|
||||||
*/
|
|
||||||
public void skipValue();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* /跳过字段与值之间的多余内容, json就是跳过:符, map跳过:
|
|
||||||
*/
|
|
||||||
public void skipBlank();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取对象的开头 返回字段数
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public int readObjectB();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取对象的尾端
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void readObjectE();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取数组的开头并返回数组的长度
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public int readArrayB();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取数组的尾端
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void readArrayE();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取map的开头并返回map的size
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public int readMapB();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取数组的尾端
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void readMapE();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据字段读取字段对应的DeMember
|
|
||||||
*
|
|
||||||
* @param index
|
|
||||||
* @param members
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public DeMember readField(final AtomicInteger index, final DeMember[] members);
|
|
||||||
|
|
||||||
public boolean readBoolean();
|
|
||||||
|
|
||||||
public byte readByte();
|
|
||||||
|
|
||||||
public char readChar();
|
|
||||||
|
|
||||||
public short readShort();
|
|
||||||
|
|
||||||
public int readInt();
|
|
||||||
|
|
||||||
public long readLong();
|
|
||||||
|
|
||||||
public float readFloat();
|
|
||||||
|
|
||||||
public double readDouble();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取无转义字符长度不超过255的字符串, 例如枚举值、字段名、类名字符串等
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String readSmallString();
|
|
||||||
|
|
||||||
public String readClassName();
|
|
||||||
|
|
||||||
public String readString();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public abstract class SimpledCoder<R extends Reader, W extends Writer, T> implements Decodeable<R, T>, Encodeable<W, T> {
|
|
||||||
|
|
||||||
private Type type;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public abstract void convertTo(final W out, final T value);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public abstract T convertFrom(final R in);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Class<T> getType() {
|
|
||||||
if (type == null) {
|
|
||||||
Type[] ts = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
|
|
||||||
type = ts[ts.length - 1];
|
|
||||||
}
|
|
||||||
return (Class<T>) type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.getClass().getSimpleName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert;
|
|
||||||
|
|
||||||
import org.redkale.util.Attribute;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public interface Writer {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 当tiny=true时, 字符串为空、boolean为false的字段值都会被跳过, 不会输出。
|
|
||||||
* <p>
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean isTiny();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出null值
|
|
||||||
*/
|
|
||||||
public void writeNull();
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param clazz
|
|
||||||
*/
|
|
||||||
public void wirteClassName(String clazz);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出一个对象前的操作
|
|
||||||
*
|
|
||||||
* @param fieldCount 字段个数
|
|
||||||
*
|
|
||||||
* @param obj
|
|
||||||
*/
|
|
||||||
public void writeObjectB(int fieldCount, Object obj);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出一个对象后的操作
|
|
||||||
*
|
|
||||||
* @param obj
|
|
||||||
*/
|
|
||||||
public void writeObjectE(Object obj);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出一个数组前的操作
|
|
||||||
*
|
|
||||||
* @param size 数组长度
|
|
||||||
*/
|
|
||||||
public void writeArrayB(int size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出数组元素间的间隔符
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void writeArrayMark();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出一个数组后的操作
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void writeArrayE();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出一个Map前的操作
|
|
||||||
*
|
|
||||||
* @param size map大小
|
|
||||||
*/
|
|
||||||
public void writeMapB(int size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出一个Map中key与value间的间隔符
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void writeMapMark();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出一个Map后的操作
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void writeMapE();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出一个字段
|
|
||||||
*
|
|
||||||
* @param comma 是否非第一个字段
|
|
||||||
* @param attribute
|
|
||||||
*/
|
|
||||||
public void writeField(boolean comma, Attribute attribute);
|
|
||||||
|
|
||||||
public void writeBoolean(boolean value);
|
|
||||||
|
|
||||||
public void writeByte(byte value);
|
|
||||||
|
|
||||||
public void writeChar(char value);
|
|
||||||
|
|
||||||
public void writeShort(short value);
|
|
||||||
|
|
||||||
public void writeInt(int value);
|
|
||||||
|
|
||||||
public void writeLong(long value);
|
|
||||||
|
|
||||||
public void writeFloat(float value);
|
|
||||||
|
|
||||||
public void writeDouble(double value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 写入无转义字符长度不超过255的字符串, 例如枚举值、字段名、类名字符串等 *
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
public void writeSmallString(String value);
|
|
||||||
|
|
||||||
public void writeString(String value);
|
|
||||||
}
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.bson;
|
|
||||||
|
|
||||||
import java.nio.*;
|
|
||||||
import java.util.function.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class BsonByteBufferWriter extends BsonWriter {
|
|
||||||
|
|
||||||
private final Supplier<ByteBuffer> supplier;
|
|
||||||
|
|
||||||
private ByteBuffer[] buffers;
|
|
||||||
|
|
||||||
private int index;
|
|
||||||
|
|
||||||
protected BsonByteBufferWriter(Supplier<ByteBuffer> supplier) {
|
|
||||||
super((byte[]) null);
|
|
||||||
this.supplier = supplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuffer[] toBuffers() {
|
|
||||||
if (buffers == null) return new ByteBuffer[0];
|
|
||||||
for (int i = index; i < this.buffers.length; i++) {
|
|
||||||
ByteBuffer buf = this.buffers[i];
|
|
||||||
if (buf.position() != 0) buf.flip();
|
|
||||||
}
|
|
||||||
return this.buffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] toArray() {
|
|
||||||
if (buffers == null) return new byte[0];
|
|
||||||
int pos = 0;
|
|
||||||
byte[] bytes = new byte[this.count];
|
|
||||||
for (ByteBuffer buf : toBuffers()) {
|
|
||||||
int r = buf.remaining();
|
|
||||||
buf.get(bytes, pos, r);
|
|
||||||
buf.flip();
|
|
||||||
pos += r;
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.getClass().getSimpleName() + "[count=" + this.count + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BsonByteBufferWriter setTiny(boolean tiny) {
|
|
||||||
this.tiny = tiny;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int expand(final int byteLength) {
|
|
||||||
if (this.buffers == null) {
|
|
||||||
this.index = 0;
|
|
||||||
this.buffers = new ByteBuffer[]{supplier.get()};
|
|
||||||
}
|
|
||||||
ByteBuffer buffer = this.buffers[index];
|
|
||||||
if (!buffer.hasRemaining()) {
|
|
||||||
buffer.flip();
|
|
||||||
buffer = supplier.get();
|
|
||||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
|
||||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
|
||||||
bufs[this.buffers.length] = buffer;
|
|
||||||
this.buffers = bufs;
|
|
||||||
this.index++;
|
|
||||||
}
|
|
||||||
int len = buffer.remaining();
|
|
||||||
int size = 0;
|
|
||||||
while (len < byteLength) {
|
|
||||||
buffer = supplier.get();
|
|
||||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
|
||||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
|
||||||
bufs[this.buffers.length] = buffer;
|
|
||||||
this.buffers = bufs;
|
|
||||||
len += buffer.remaining();
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
|
||||||
if (expand(len) == 0) {
|
|
||||||
this.buffers[index].put(chs, start, len);
|
|
||||||
} else {
|
|
||||||
ByteBuffer buffer = this.buffers[index];
|
|
||||||
final int end = start + len;
|
|
||||||
int remain = len; //还剩多少没有写
|
|
||||||
while (remain > 0) {
|
|
||||||
final int br = buffer.remaining();
|
|
||||||
if (remain > br) { //一个buffer写不完
|
|
||||||
buffer.put(chs, end - remain, br);
|
|
||||||
buffer = nextByteBuffer();
|
|
||||||
remain -= br;
|
|
||||||
} else {
|
|
||||||
buffer.put(chs, end - remain, remain);
|
|
||||||
remain = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.count += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ByteBuffer nextByteBuffer() {
|
|
||||||
this.buffers[this.index].flip();
|
|
||||||
return this.buffers[++this.index];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeTo(final byte ch) {
|
|
||||||
expand(1);
|
|
||||||
this.buffers[index].put(ch);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean recycle() {
|
|
||||||
this.index = 0;
|
|
||||||
this.buffers = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.bson;
|
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.nio.*;
|
|
||||||
import java.util.function.*;
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BSON协议格式:
|
|
||||||
* 1). 基本数据类型: 直接转换成byte[]
|
|
||||||
* 2). SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。
|
|
||||||
* 3). String: length(4 bytes) + byte[](utf8);
|
|
||||||
* 4). 数组: length(4 bytes) + byte[]...
|
|
||||||
* 5). Object:
|
|
||||||
* 1. realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值)
|
|
||||||
* 2. 空字符串(SmallString)
|
|
||||||
* 3. SIGN_OBJECTB 标记位,值固定为0xBB (short)
|
|
||||||
* 4. 循环字段值:
|
|
||||||
* 4.1 SIGN_HASNEXT 标记位,值固定为1 (byte)
|
|
||||||
* 4.2 字段类型; 1-9为基本类型&字符串; 101-109为基本类型&字符串的数组; 127为Object
|
|
||||||
* 4.3 字段名 (SmallString)
|
|
||||||
* 4.4 字段的值Object
|
|
||||||
* 5. SIGN_NONEXT 标记位,值固定为0 (byte)
|
|
||||||
* 6. SIGN_OBJECTE 标记位,值固定为0xEE (short)
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class BsonConvert extends Convert<BsonReader, BsonWriter> {
|
|
||||||
|
|
||||||
private static final ObjectPool<BsonReader> readerPool = BsonReader.createPool(Integer.getInteger("convert.bson.pool.size", 16));
|
|
||||||
|
|
||||||
private static final ObjectPool<BsonWriter> writerPool = BsonWriter.createPool(Integer.getInteger("convert.bson.pool.size", 16));
|
|
||||||
|
|
||||||
private final boolean tiny;
|
|
||||||
|
|
||||||
protected BsonConvert(Factory<BsonReader, BsonWriter> factory, boolean tiny) {
|
|
||||||
super(factory);
|
|
||||||
this.tiny = tiny;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonByteBufferWriter pollBsonWriter(final Supplier<ByteBuffer> supplier) {
|
|
||||||
return new BsonByteBufferWriter(supplier).setTiny(tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonWriter pollBsonWriter() {
|
|
||||||
return writerPool.get().setTiny(tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offerBsonWriter(BsonWriter out) {
|
|
||||||
if (out != null) writerPool.offer(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonReader pollBsonReader() {
|
|
||||||
return readerPool.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offerBsonReader(BsonReader in) {
|
|
||||||
if (in != null) readerPool.offer(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T convertFrom(final Type type, final byte[] bytes) {
|
|
||||||
if (bytes == null) return null;
|
|
||||||
return convertFrom(type, bytes, 0, bytes.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T convertFrom(final Type type, final byte[] bytes, int start, int len) {
|
|
||||||
if (type == null) return null;
|
|
||||||
final BsonReader in = readerPool.get();
|
|
||||||
in.setBytes(bytes, start, len);
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T rs = (T) factory.loadDecoder(type).convertFrom(in);
|
|
||||||
readerPool.offer(in);
|
|
||||||
return rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T convertFrom(final BsonReader in, final Type type) {
|
|
||||||
if (type == null) return null;
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T rs = (T) factory.loadDecoder(type).convertFrom(in);
|
|
||||||
return rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] convertTo(final Type type, Object value) {
|
|
||||||
if (type == null) return null;
|
|
||||||
final BsonWriter out = writerPool.get().setTiny(tiny);
|
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
|
||||||
byte[] result = out.toArray();
|
|
||||||
writerPool.offer(out);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void convertTo(final BsonWriter out, final Type type, Object value) {
|
|
||||||
if (type == null) return;
|
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, Object value) {
|
|
||||||
if (supplier == null || type == null) return null;
|
|
||||||
BsonByteBufferWriter out = new BsonByteBufferWriter(supplier);
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
|
||||||
}
|
|
||||||
return out.toBuffers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, Object value) {
|
|
||||||
if (supplier == null) return null;
|
|
||||||
BsonByteBufferWriter out = new BsonByteBufferWriter(supplier);
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
factory.loadEncoder(value.getClass()).convertTo(out, value);
|
|
||||||
}
|
|
||||||
return out.toBuffers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void convertTo(final BsonWriter out, Object value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
factory.loadEncoder(value.getClass()).convertTo(out, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] convertTo(Object value) {
|
|
||||||
if (value == null) {
|
|
||||||
final BsonWriter out = writerPool.get().setTiny(tiny);
|
|
||||||
out.writeNull();
|
|
||||||
byte[] result = out.toArray();
|
|
||||||
writerPool.offer(out);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return convertTo(value.getClass(), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonWriter convertToWriter(final Type type, Object value) {
|
|
||||||
if (type == null) return null;
|
|
||||||
final BsonWriter out = writerPool.get().setTiny(tiny);
|
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonWriter convertToWriter(Object value) {
|
|
||||||
if (value == null) return null;
|
|
||||||
return convertToWriter(value.getClass(), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.bson;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class BsonFactory extends Factory<BsonReader, BsonWriter> {
|
|
||||||
|
|
||||||
private static final BsonFactory instance = new BsonFactory(null, Boolean.getBoolean("convert.bson.tiny"));
|
|
||||||
|
|
||||||
static final Decodeable objectDecoder = instance.loadDecoder(Object.class);
|
|
||||||
|
|
||||||
static final Encodeable objectEncoder = instance.loadEncoder(Object.class);
|
|
||||||
|
|
||||||
static {
|
|
||||||
instance.register(Serializable.class, objectDecoder);
|
|
||||||
instance.register(Serializable.class, objectEncoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
private BsonFactory(BsonFactory parent, boolean tiny) {
|
|
||||||
super(parent, tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BsonFactory root() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final BsonConvert getConvert() {
|
|
||||||
if (convert == null) convert = new BsonConvert(this, tiny);
|
|
||||||
return (BsonConvert) convert;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BsonFactory createChild() {
|
|
||||||
return new BsonFactory(this, this.tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BsonFactory createChild(boolean tiny) {
|
|
||||||
return new BsonFactory(this, tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConvertType getConvertType() {
|
|
||||||
return ConvertType.BSON;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isReversible() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,324 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.bson;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.*;
|
|
||||||
import java.util.function.*;
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
import static org.redkale.convert.Reader.SIGN_NULL;
|
|
||||||
import org.redkale.convert.ext.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class BsonReader implements Reader {
|
|
||||||
|
|
||||||
public static final short SIGN_OBJECTB = (short) 0xBB;
|
|
||||||
|
|
||||||
public static final short SIGN_OBJECTE = (short) 0xEE;
|
|
||||||
|
|
||||||
public static final byte SIGN_HASNEXT = 1;
|
|
||||||
|
|
||||||
public static final byte SIGN_NONEXT = 0;
|
|
||||||
|
|
||||||
public static final byte VERBOSE_NO = 1;
|
|
||||||
|
|
||||||
public static final byte VERBOSE_YES = 2;
|
|
||||||
|
|
||||||
private int position = -1;
|
|
||||||
|
|
||||||
private byte typeval; //字段的类型值 对应 BsonWriter.writeField
|
|
||||||
|
|
||||||
private byte[] content;
|
|
||||||
|
|
||||||
public BsonReader() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ObjectPool<BsonReader> createPool(int max) {
|
|
||||||
return new ObjectPool<BsonReader>(max, new Creator<BsonReader>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BsonReader create(Object... params) {
|
|
||||||
return new BsonReader();
|
|
||||||
}
|
|
||||||
}, null, new Predicate<BsonReader>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(BsonReader t) {
|
|
||||||
return t.recycle();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonReader(byte[] bytes) {
|
|
||||||
setBytes(bytes, 0, bytes.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonReader(byte[] bytes, int start, int len) {
|
|
||||||
setBytes(bytes, start, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setBytes(byte[] bytes) {
|
|
||||||
if (bytes == null) {
|
|
||||||
this.position = 0;
|
|
||||||
} else {
|
|
||||||
setBytes(bytes, 0, bytes.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setBytes(byte[] bytes, int start, int len) {
|
|
||||||
if (bytes == null) {
|
|
||||||
this.position = 0;
|
|
||||||
} else {
|
|
||||||
this.content = bytes;
|
|
||||||
this.position = start - 1;
|
|
||||||
//this.limit = start + len - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean recycle() {
|
|
||||||
this.position = -1;
|
|
||||||
this.typeval = 0;
|
|
||||||
//this.limit = -1;
|
|
||||||
this.content = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
this.recycle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳过属性的值
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final void skipValue() {
|
|
||||||
if (typeval == 0) return;
|
|
||||||
final byte val = this.typeval;
|
|
||||||
this.typeval = 0;
|
|
||||||
switch (val) {
|
|
||||||
case 1: readBoolean();
|
|
||||||
break;
|
|
||||||
case 2: readByte();
|
|
||||||
break;
|
|
||||||
case 3: readShort();
|
|
||||||
break;
|
|
||||||
case 4: readChar();
|
|
||||||
break;
|
|
||||||
case 5: readInt();
|
|
||||||
break;
|
|
||||||
case 6: readLong();
|
|
||||||
break;
|
|
||||||
case 7: readFloat();
|
|
||||||
break;
|
|
||||||
case 8: readDouble();
|
|
||||||
break;
|
|
||||||
case 9: readString();
|
|
||||||
break;
|
|
||||||
case 101:
|
|
||||||
BoolArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 102:
|
|
||||||
ByteArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 103:
|
|
||||||
ShortArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 104:
|
|
||||||
CharArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 105:
|
|
||||||
IntArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 106:
|
|
||||||
LongArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 107:
|
|
||||||
FloatArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 108:
|
|
||||||
DoubleArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 109:
|
|
||||||
StringArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 127:
|
|
||||||
BsonFactory.objectDecoder.convertFrom(this);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断下一个非空白字节是否为{
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int readObjectB() {
|
|
||||||
short bt = readShort();
|
|
||||||
if (bt == Reader.SIGN_NULL) return bt;
|
|
||||||
if (bt != SIGN_OBJECTB) {
|
|
||||||
throw new ConvertException("a bson object must begin with " + (SIGN_OBJECTB)
|
|
||||||
+ " (position = " + position + ") but '" + this.content[this.position] + "'");
|
|
||||||
}
|
|
||||||
return bt;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readObjectE() {
|
|
||||||
if (readShort() != SIGN_OBJECTE) {
|
|
||||||
throw new ConvertException("a bson object must end with " + (SIGN_OBJECTE)
|
|
||||||
+ " (position = " + position + ") but '" + this.content[this.position] + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readMapB() {
|
|
||||||
return readArrayB();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readMapE() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断下一个非空白字节是否为[
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int readArrayB() {
|
|
||||||
short bt = readShort();
|
|
||||||
if (bt == Reader.SIGN_NULL) return bt;
|
|
||||||
return (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readArrayE() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断下一个非空白字节是否:
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void skipBlank() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
byte b = readByte();
|
|
||||||
if (b == SIGN_HASNEXT) return true;
|
|
||||||
if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT)
|
|
||||||
+ " or " + (SIGN_NONEXT) + ") but '" + b + "' at position(" + this.position + ")");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeMember readField(final AtomicInteger index, final DeMember[] members) {
|
|
||||||
final String exceptedfield = readSmallString();
|
|
||||||
this.typeval = readByte();
|
|
||||||
final int len = members.length;
|
|
||||||
int v = index.get();
|
|
||||||
if (v >= len) {
|
|
||||||
v = 0;
|
|
||||||
index.set(0);
|
|
||||||
}
|
|
||||||
for (int k = v; k < len; k++) {
|
|
||||||
if (exceptedfield.equals(members[k].getAttribute().field())) {
|
|
||||||
index.set(k);
|
|
||||||
return members[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int k = 0; k < v; k++) {
|
|
||||||
if (exceptedfield.equals(members[k].getAttribute().field())) {
|
|
||||||
index.set(k);
|
|
||||||
return members[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
@Override
|
|
||||||
public boolean readBoolean() {
|
|
||||||
return content[++this.position] == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readByte() {
|
|
||||||
return content[++this.position];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public char readChar() {
|
|
||||||
return (char) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short readShort() {
|
|
||||||
return (short) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readInt() {
|
|
||||||
return ((content[++this.position] & 0xff) << 24) | ((content[++this.position] & 0xff) << 16)
|
|
||||||
| ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readLong() {
|
|
||||||
return ((((long) content[++this.position] & 0xff) << 56)
|
|
||||||
| (((long) content[++this.position] & 0xff) << 48)
|
|
||||||
| (((long) content[++this.position] & 0xff) << 40)
|
|
||||||
| (((long) content[++this.position] & 0xff) << 32)
|
|
||||||
| (((long) content[++this.position] & 0xff) << 24)
|
|
||||||
| (((long) content[++this.position] & 0xff) << 16)
|
|
||||||
| (((long) content[++this.position] & 0xff) << 8)
|
|
||||||
| (((long) content[++this.position] & 0xff)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float readFloat() {
|
|
||||||
return Float.intBitsToFloat(readInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double readDouble() {
|
|
||||||
return Double.longBitsToDouble(readLong());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String readClassName() {
|
|
||||||
return readSmallString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String readSmallString() {
|
|
||||||
int len = 0xff & readByte();
|
|
||||||
if (len == 0) return "";
|
|
||||||
String value = new String(content, ++this.position, len);
|
|
||||||
this.position += len - 1;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String readString() {
|
|
||||||
int len = readInt();
|
|
||||||
if (len == SIGN_NULL) return null;
|
|
||||||
if (len == 0) return "";
|
|
||||||
String value = new String(Utility.decodeUTF8(content, ++this.position, len));
|
|
||||||
this.position += len - 1;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.bson;
|
|
||||||
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public abstract class BsonSimpledCoder<T> extends SimpledCoder<BsonReader, BsonWriter, T> {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,298 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.bson;
|
|
||||||
|
|
||||||
import java.nio.*;
|
|
||||||
import java.util.function.*;
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public class BsonWriter implements Writer {
|
|
||||||
|
|
||||||
private static final int defaultSize = Integer.getInteger("convert.bson.writer.buffer.defsize", 1024);
|
|
||||||
|
|
||||||
private byte[] content;
|
|
||||||
|
|
||||||
protected int count;
|
|
||||||
|
|
||||||
protected boolean tiny;
|
|
||||||
|
|
||||||
public static ObjectPool<BsonWriter> createPool(int max) {
|
|
||||||
return new ObjectPool<BsonWriter>(max, new Creator<BsonWriter>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BsonWriter create(Object... params) {
|
|
||||||
return new BsonWriter();
|
|
||||||
}
|
|
||||||
}, null, new Predicate<BsonWriter>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(BsonWriter t) {
|
|
||||||
return t.recycle();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] toArray() {
|
|
||||||
if (count == content.length) return content;
|
|
||||||
byte[] newdata = new byte[count];
|
|
||||||
System.arraycopy(content, 0, newdata, 0, count);
|
|
||||||
return newdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer[] toBuffers() {
|
|
||||||
return new ByteBuffer[]{ByteBuffer.wrap(content, 0, count)};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BsonWriter(byte[] bs) {
|
|
||||||
this.content = bs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonWriter() {
|
|
||||||
this(defaultSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonWriter(int size) {
|
|
||||||
this.content = new byte[size > 128 ? size : 128];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isTiny() {
|
|
||||||
return tiny;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonWriter setTiny(boolean tiny) {
|
|
||||||
this.tiny = tiny;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* 扩充指定长度的缓冲区
|
|
||||||
*
|
|
||||||
* @param len
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected int expand(int len) {
|
|
||||||
int newcount = count + len;
|
|
||||||
if (newcount <= content.length) return 0;
|
|
||||||
byte[] newdata = new byte[Math.max(content.length * 3 / 2, newcount)];
|
|
||||||
System.arraycopy(content, 0, newdata, 0, count);
|
|
||||||
this.content = newdata;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeTo(final byte ch) {
|
|
||||||
expand(1);
|
|
||||||
content[count++] = ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void writeTo(final byte... chs) {
|
|
||||||
writeTo(chs, 0, chs.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeTo(final byte[] chs, final int start, final int len) {
|
|
||||||
expand(len);
|
|
||||||
System.arraycopy(chs, start, content, count, len);
|
|
||||||
count += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean recycle() {
|
|
||||||
this.count = 0;
|
|
||||||
if (this.content.length > defaultSize) {
|
|
||||||
this.content = new byte[defaultSize];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.getClass().getSimpleName() + "[count=" + this.count + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
public final int count() {
|
|
||||||
return this.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeBoolean(boolean value) {
|
|
||||||
writeTo(value ? (byte) 1 : (byte) 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeByte(byte value) {
|
|
||||||
writeTo(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeChar(final char value) {
|
|
||||||
writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeShort(short value) {
|
|
||||||
writeTo((byte) (value >> 8), (byte) value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeInt(int value) {
|
|
||||||
writeTo((byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeLong(long value) {
|
|
||||||
writeTo((byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
|
|
||||||
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeFloat(float value) {
|
|
||||||
writeInt(Float.floatToIntBits(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeDouble(double value) {
|
|
||||||
writeLong(Double.doubleToLongBits(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void wirteClassName(String clazz) {
|
|
||||||
writeSmallString(clazz == null ? "" : clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeObjectB(int fieldCount, Object obj) {
|
|
||||||
writeSmallString("");
|
|
||||||
writeShort(BsonReader.SIGN_OBJECTB);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeObjectE(Object obj) {
|
|
||||||
writeByte(BsonReader.SIGN_NONEXT);
|
|
||||||
writeShort(BsonReader.SIGN_OBJECTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeField(boolean comma, Attribute attribute) {
|
|
||||||
writeByte(BsonReader.SIGN_HASNEXT);
|
|
||||||
writeSmallString(attribute.field());
|
|
||||||
byte typeval = 127; //字段的类型值
|
|
||||||
final Class type = attribute.type();
|
|
||||||
if (type == boolean.class || type == Boolean.class) {
|
|
||||||
typeval = 1;
|
|
||||||
} else if (type == byte.class || type == Byte.class) {
|
|
||||||
typeval = 2;
|
|
||||||
} else if (type == short.class || type == Short.class) {
|
|
||||||
typeval = 3;
|
|
||||||
} else if (type == char.class || type == Character.class) {
|
|
||||||
typeval = 4;
|
|
||||||
} else if (type == int.class || type == Integer.class) {
|
|
||||||
typeval = 5;
|
|
||||||
} else if (type == long.class || type == Long.class) {
|
|
||||||
typeval = 6;
|
|
||||||
} else if (type == float.class || type == Float.class) {
|
|
||||||
typeval = 7;
|
|
||||||
} else if (type == double.class || type == Double.class) {
|
|
||||||
typeval = 8;
|
|
||||||
} else if (type == String.class) {
|
|
||||||
typeval = 9;
|
|
||||||
} else if (type == boolean[].class || type == Boolean[].class) {
|
|
||||||
typeval = 101;
|
|
||||||
} else if (type == byte[].class || type == Byte[].class) {
|
|
||||||
typeval = 102;
|
|
||||||
} else if (type == short[].class || type == Short[].class) {
|
|
||||||
typeval = 103;
|
|
||||||
} else if (type == char[].class || type == Character[].class) {
|
|
||||||
typeval = 104;
|
|
||||||
} else if (type == int[].class || type == Integer[].class) {
|
|
||||||
typeval = 105;
|
|
||||||
} else if (type == long[].class || type == Long[].class) {
|
|
||||||
typeval = 106;
|
|
||||||
} else if (type == float[].class || type == Float[].class) {
|
|
||||||
typeval = 107;
|
|
||||||
} else if (type == double[].class || type == Double[].class) {
|
|
||||||
typeval = 108;
|
|
||||||
} else if (type == String[].class) {
|
|
||||||
typeval = 109;
|
|
||||||
}
|
|
||||||
writeByte(typeval);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对于类的字段名、枚举值这些长度一般不超过255且不会出现双字节字符的字符串采用writeSmallString处理, readSmallString用于读取
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final void writeSmallString(String value) {
|
|
||||||
if (value.isEmpty()) {
|
|
||||||
writeTo((byte) 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char[] chars = Utility.charArray(value);
|
|
||||||
if (chars.length > 255) throw new ConvertException("'" + value + "' has very long length");
|
|
||||||
byte[] bytes = new byte[chars.length + 1];
|
|
||||||
bytes[0] = (byte) chars.length;
|
|
||||||
for (int i = 0; i < chars.length; i++) {
|
|
||||||
if (chars[i] > Byte.MAX_VALUE) throw new ConvertException("'" + value + "' has double-word");
|
|
||||||
bytes[i + 1] = (byte) chars[i];
|
|
||||||
}
|
|
||||||
writeTo(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeString(String value) {
|
|
||||||
if (value == null) {
|
|
||||||
writeInt(Reader.SIGN_NULL);
|
|
||||||
return;
|
|
||||||
} else if (value.isEmpty()) {
|
|
||||||
writeInt(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
byte[] bytes = Utility.encodeUTF8(value);
|
|
||||||
writeInt(bytes.length);
|
|
||||||
writeTo(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeNull() {
|
|
||||||
writeShort(Reader.SIGN_NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeArrayB(int size) {
|
|
||||||
writeInt(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeArrayMark() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeArrayE() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeMapB(int size) {
|
|
||||||
writeArrayB(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeMapMark() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeMapE() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class BigIntegerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, BigInteger> {
|
|
||||||
|
|
||||||
public static final BigIntegerSimpledCoder instance = new BigIntegerSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, BigInteger value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ByteArraySimpledCoder.instance.convertTo(out, value.toByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigInteger convertFrom(R in) {
|
|
||||||
byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in);
|
|
||||||
return bytes == null ? null : new BigInteger(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class BoolArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, boolean[]> {
|
|
||||||
|
|
||||||
public static final BoolArraySimpledCoder instance = new BoolArraySimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, boolean[] values) {
|
|
||||||
if (values == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(values.length);
|
|
||||||
boolean flag = false;
|
|
||||||
for (boolean v : values) {
|
|
||||||
if (flag) out.writeArrayMark();
|
|
||||||
out.writeBoolean(v);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean[] convertFrom(R in) {
|
|
||||||
int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
int size = 0;
|
|
||||||
boolean[] data = new boolean[8];
|
|
||||||
while (in.hasNext()) {
|
|
||||||
if (size >= data.length) {
|
|
||||||
boolean[] newdata = new boolean[data.length + 4];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
data = newdata;
|
|
||||||
}
|
|
||||||
data[size++] = in.readBoolean();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
boolean[] newdata = new boolean[size];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
return newdata;
|
|
||||||
} else {
|
|
||||||
boolean[] values = new boolean[len];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
values[i] = in.readBoolean();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class BoolSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Boolean> {
|
|
||||||
|
|
||||||
public static final BoolSimpledCoder instance = new BoolSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Boolean value) {
|
|
||||||
out.writeBoolean(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean convertFrom(R in) {
|
|
||||||
return in.readBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class ByteArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, byte[]> {
|
|
||||||
|
|
||||||
public static final ByteArraySimpledCoder instance = new ByteArraySimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, byte[] values) {
|
|
||||||
if (values == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(values.length);
|
|
||||||
boolean flag = false;
|
|
||||||
for (byte v : values) {
|
|
||||||
if (flag) out.writeArrayMark();
|
|
||||||
out.writeByte(v);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] convertFrom(R in) {
|
|
||||||
int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
int size = 0;
|
|
||||||
byte[] data = new byte[8];
|
|
||||||
while (in.hasNext()) {
|
|
||||||
if (size >= data.length) {
|
|
||||||
byte[] newdata = new byte[data.length + 4];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
data = newdata;
|
|
||||||
}
|
|
||||||
data[size++] = in.readByte();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
byte[] newdata = new byte[size];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
return newdata;
|
|
||||||
} else {
|
|
||||||
byte[] values = new byte[len];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
values[i] = in.readByte();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class ByteSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Byte> {
|
|
||||||
|
|
||||||
public static final ByteSimpledCoder instance = new ByteSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Byte value) {
|
|
||||||
out.writeByte(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Byte convertFrom(R in) {
|
|
||||||
return in.readByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class CharArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, char[]> {
|
|
||||||
|
|
||||||
public static final CharArraySimpledCoder instance = new CharArraySimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, char[] values) {
|
|
||||||
if (values == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(values.length);
|
|
||||||
boolean flag = false;
|
|
||||||
for (char v : values) {
|
|
||||||
if (flag) out.writeArrayMark();
|
|
||||||
out.writeChar(v);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public char[] convertFrom(R in) {
|
|
||||||
int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
int size = 0;
|
|
||||||
char[] data = new char[8];
|
|
||||||
while (in.hasNext()) {
|
|
||||||
if (size >= data.length) {
|
|
||||||
char[] newdata = new char[data.length + 4];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
data = newdata;
|
|
||||||
}
|
|
||||||
data[size++] = in.readChar();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
char[] newdata = new char[size];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
return newdata;
|
|
||||||
} else {
|
|
||||||
char[] values = new char[len];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
values[i] = in.readChar();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public class CharSequenceSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, CharSequence> {
|
|
||||||
|
|
||||||
public static final CharSequenceSimpledCoder instance = new CharSequenceSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, CharSequence value) {
|
|
||||||
out.writeString(value == null ? null : value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CharSequence convertFrom(R in) {
|
|
||||||
return in.readString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class CharSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Character> {
|
|
||||||
|
|
||||||
public static final CharSimpledCoder instance = new CharSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Character value) {
|
|
||||||
out.writeChar(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Character convertFrom(R in) {
|
|
||||||
return in.readChar();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import java.nio.channels.*;
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class CompletionHandlerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, CompletionHandler> {
|
|
||||||
|
|
||||||
public static final CompletionHandlerSimpledCoder instance = new CompletionHandlerSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, CompletionHandler value) {
|
|
||||||
out.writeNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletionHandler convertFrom(R in) {
|
|
||||||
in.readObjectB();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class DLongSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, DLong> {
|
|
||||||
|
|
||||||
private static final ByteArraySimpledCoder bsSimpledCoder = ByteArraySimpledCoder.instance;
|
|
||||||
|
|
||||||
public static final DLongSimpledCoder instance = new DLongSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(final W out, final DLong value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
bsSimpledCoder.convertTo(out, value.directBytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DLong convertFrom(R in) {
|
|
||||||
byte[] bs = bsSimpledCoder.convertFrom(in);
|
|
||||||
if (bs == null) return null;
|
|
||||||
return DLong.create(bs);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class DateSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Date> {
|
|
||||||
|
|
||||||
public static final DateSimpledCoder instance = new DateSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Date value) {
|
|
||||||
out.writeLong(value.getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Date convertFrom(R in) {
|
|
||||||
return new Date(in.readLong());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class DoubleArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, double[]> {
|
|
||||||
|
|
||||||
public static final DoubleArraySimpledCoder instance = new DoubleArraySimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, double[] values) {
|
|
||||||
if (values == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(values.length);
|
|
||||||
boolean flag = false;
|
|
||||||
for (double v : values) {
|
|
||||||
if (flag) out.writeArrayMark();
|
|
||||||
out.writeDouble(v);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double[] convertFrom(R in) {
|
|
||||||
int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
int size = 0;
|
|
||||||
double[] data = new double[8];
|
|
||||||
while (in.hasNext()) {
|
|
||||||
if (size >= data.length) {
|
|
||||||
double[] newdata = new double[data.length + 4];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
data = newdata;
|
|
||||||
}
|
|
||||||
data[size++] = in.readDouble();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
double[] newdata = new double[size];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
return newdata;
|
|
||||||
} else {
|
|
||||||
double[] values = new double[len];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
values[i] = in.readDouble();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class DoubleSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Double> {
|
|
||||||
|
|
||||||
public static final DoubleSimpledCoder instance = new DoubleSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Double value) {
|
|
||||||
out.writeDouble(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Double convertFrom(R in) {
|
|
||||||
return in.readDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
* @param <E>
|
|
||||||
*/
|
|
||||||
public final class EnumSimpledCoder<R extends Reader, W extends Writer, E extends Enum> extends SimpledCoder<R, W, E> {
|
|
||||||
|
|
||||||
private final Class<E> type;
|
|
||||||
|
|
||||||
public EnumSimpledCoder(Class<E> type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(final W out, final E value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
out.writeSmallString(value.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public E convertFrom(final R in) {
|
|
||||||
String value = in.readSmallString();
|
|
||||||
if (value == null) return null;
|
|
||||||
return (E) Enum.valueOf(type, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class FloatArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, float[]> {
|
|
||||||
|
|
||||||
public static final FloatArraySimpledCoder instance = new FloatArraySimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, float[] values) {
|
|
||||||
if (values == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(values.length);
|
|
||||||
boolean flag = false;
|
|
||||||
for (float v : values) {
|
|
||||||
if (flag) out.writeArrayMark();
|
|
||||||
out.writeFloat(v);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float[] convertFrom(R in) {
|
|
||||||
int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
int size = 0;
|
|
||||||
float[] data = new float[8];
|
|
||||||
while (in.hasNext()) {
|
|
||||||
if (size >= data.length) {
|
|
||||||
float[] newdata = new float[data.length + 4];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
data = newdata;
|
|
||||||
}
|
|
||||||
data[size++] = in.readFloat();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
float[] newdata = new float[size];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
return newdata;
|
|
||||||
} else {
|
|
||||||
float[] values = new float[len];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
values[i] = in.readFloat();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class FloatSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Float> {
|
|
||||||
|
|
||||||
public static final FloatSimpledCoder instance = new FloatSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Float value) {
|
|
||||||
out.writeFloat(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Float convertFrom(R in) {
|
|
||||||
return in.readFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import java.net.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class InetAddressSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, InetAddress> {
|
|
||||||
|
|
||||||
public static final InetAddressSimpledCoder instance = new InetAddressSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, InetAddress value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ByteArraySimpledCoder.instance.convertTo(out, value.getAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InetAddress convertFrom(R in) {
|
|
||||||
byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in);
|
|
||||||
if (bytes == null) return null;
|
|
||||||
try {
|
|
||||||
return InetAddress.getByAddress(bytes);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final static class InetSocketAddressSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, InetSocketAddress> {
|
|
||||||
|
|
||||||
public static final InetSocketAddressSimpledCoder instance = new InetSocketAddressSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, InetSocketAddress value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ByteArraySimpledCoder.instance.convertTo(out, value.getAddress().getAddress());
|
|
||||||
out.writeInt(value.getPort());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InetSocketAddress convertFrom(R in) {
|
|
||||||
byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in);
|
|
||||||
if (bytes == null) return null;
|
|
||||||
int port = in.readInt();
|
|
||||||
try {
|
|
||||||
return new InetSocketAddress(InetAddress.getByAddress(bytes), port);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class IntArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, int[]> {
|
|
||||||
|
|
||||||
public static final IntArraySimpledCoder instance = new IntArraySimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, int[] values) {
|
|
||||||
if (values == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(values.length);
|
|
||||||
boolean flag = false;
|
|
||||||
for (int v : values) {
|
|
||||||
if (flag) out.writeArrayMark();
|
|
||||||
out.writeInt(v);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] convertFrom(R in) {
|
|
||||||
int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
int size = 0;
|
|
||||||
int[] data = new int[8];
|
|
||||||
while (in.hasNext()) {
|
|
||||||
if (size >= data.length) {
|
|
||||||
int[] newdata = new int[data.length + 4];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
data = newdata;
|
|
||||||
}
|
|
||||||
data[size++] = in.readInt();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
int[] newdata = new int[size];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
return newdata;
|
|
||||||
} else {
|
|
||||||
int[] values = new int[len];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
values[i] = in.readInt();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class IntSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Integer> {
|
|
||||||
|
|
||||||
public static final IntSimpledCoder instance = new IntSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Integer value) {
|
|
||||||
out.writeInt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer convertFrom(R in) {
|
|
||||||
return in.readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class LongArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, long[]> {
|
|
||||||
|
|
||||||
public static final LongArraySimpledCoder instance = new LongArraySimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, long[] values) {
|
|
||||||
if (values == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(values.length);
|
|
||||||
boolean flag = false;
|
|
||||||
for (long v : values) {
|
|
||||||
if (flag) out.writeArrayMark();
|
|
||||||
out.writeLong(v);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long[] convertFrom(R in) {
|
|
||||||
int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
int size = 0;
|
|
||||||
long[] data = new long[8];
|
|
||||||
while (in.hasNext()) {
|
|
||||||
if (size >= data.length) {
|
|
||||||
long[] newdata = new long[data.length + 4];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
data = newdata;
|
|
||||||
}
|
|
||||||
data[size++] = in.readLong();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
long[] newdata = new long[size];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
return newdata;
|
|
||||||
} else {
|
|
||||||
long[] values = new long[len];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
values[i] = in.readLong();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class LongSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Long> {
|
|
||||||
|
|
||||||
public static final LongSimpledCoder instance = new LongSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Long value) {
|
|
||||||
out.writeLong(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long convertFrom(R in) {
|
|
||||||
return in.readLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class NumberSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Number> {
|
|
||||||
|
|
||||||
public static final NumberSimpledCoder instance = new NumberSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Number value) {
|
|
||||||
out.writeLong(value == null ? 0L : value.longValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number convertFrom(R in) {
|
|
||||||
return in.readLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import java.util.regex.*;
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public class PatternSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Pattern> {
|
|
||||||
|
|
||||||
public static final PatternSimpledCoder instance = new PatternSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Pattern value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
out.writeString(value.flags() + "," + value.pattern());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Pattern convertFrom(R in) {
|
|
||||||
String value = in.readString();
|
|
||||||
if (value == null) return null;
|
|
||||||
int pos = value.indexOf(',');
|
|
||||||
return Pattern.compile(value.substring(pos + 1), Integer.parseInt(value.substring(0, pos)));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class ShortArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, short[]> {
|
|
||||||
|
|
||||||
public static final ShortArraySimpledCoder instance = new ShortArraySimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, short[] values) {
|
|
||||||
if (values == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(values.length);
|
|
||||||
boolean flag = false;
|
|
||||||
for (short v : values) {
|
|
||||||
if (flag) out.writeArrayMark();
|
|
||||||
out.writeShort(v);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short[] convertFrom(R in) {
|
|
||||||
int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
int size = 0;
|
|
||||||
short[] data = new short[8];
|
|
||||||
while (in.hasNext()) {
|
|
||||||
if (size >= data.length) {
|
|
||||||
short[] newdata = new short[data.length + 4];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
data = newdata;
|
|
||||||
}
|
|
||||||
data[size++] = in.readShort();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
short[] newdata = new short[size];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
return newdata;
|
|
||||||
} else {
|
|
||||||
short[] values = new short[len];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
values[i] = in.readShort();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class ShortSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Short> {
|
|
||||||
|
|
||||||
public static final ShortSimpledCoder instance = new ShortSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, Short value) {
|
|
||||||
out.writeShort(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Short convertFrom(R in) {
|
|
||||||
return in.readShort();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class StringArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, String[]> {
|
|
||||||
|
|
||||||
public static final StringArraySimpledCoder instance = new StringArraySimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, String[] values) {
|
|
||||||
if (values == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(values.length);
|
|
||||||
boolean flag = false;
|
|
||||||
for (String v : values) {
|
|
||||||
if (flag) out.writeArrayMark();
|
|
||||||
out.writeString(v);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] convertFrom(R in) {
|
|
||||||
int len = in.readArrayB();
|
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
int size = 0;
|
|
||||||
String[] data = new String[8];
|
|
||||||
while (in.hasNext()) {
|
|
||||||
if (size >= data.length) {
|
|
||||||
String[] newdata = new String[data.length + 4];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
data = newdata;
|
|
||||||
}
|
|
||||||
data[size++] = in.readString();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
String[] newdata = new String[size];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
return newdata;
|
|
||||||
} else {
|
|
||||||
String[] values = new String[len];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
values[i] = in.readString();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class StringSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, String> {
|
|
||||||
|
|
||||||
public static final StringSimpledCoder instance = new StringSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(W out, String value) {
|
|
||||||
out.writeString(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String convertFrom(R in) {
|
|
||||||
return in.readString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.ext;
|
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public class TypeSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Class> {
|
|
||||||
|
|
||||||
public static final TypeSimpledCoder instance = new TypeSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(final W out, final Class value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
out.writeSmallString(value.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class convertFrom(R in) {
|
|
||||||
String str = in.readSmallString();
|
|
||||||
if (str == null) return null;
|
|
||||||
try {
|
|
||||||
return Class.forName(str);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.json;
|
|
||||||
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public class DLongJsonSimpledCoder extends JsonSimpledCoder<DLong> {
|
|
||||||
|
|
||||||
public static final DLongJsonSimpledCoder instance = new DLongJsonSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(final JsonWriter out, final DLong value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
out.writeSmallString(value.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DLong convertFrom(JsonReader in) {
|
|
||||||
final String str = in.readString();
|
|
||||||
if (str == null) return null;
|
|
||||||
return DLong.create(Utility.hexToBin(str));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.json;
|
|
||||||
|
|
||||||
import java.net.*;
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
import org.redkale.convert.ext.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <R>
|
|
||||||
* @param <W>
|
|
||||||
*/
|
|
||||||
public final class InetAddressJsonSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<JsonReader, JsonWriter, InetAddress> {
|
|
||||||
|
|
||||||
public static final InetAddressJsonSimpledCoder instance = new InetAddressJsonSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(JsonWriter out, InetAddress value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
StringSimpledCoder.instance.convertTo(out, value.getHostAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InetAddress convertFrom(JsonReader in) {
|
|
||||||
String str = StringSimpledCoder.instance.convertFrom(in);
|
|
||||||
if (str == null) return null;
|
|
||||||
try {
|
|
||||||
return InetAddress.getByName(str);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final static class InetSocketAddressJsonSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<JsonReader, JsonWriter, InetSocketAddress> {
|
|
||||||
|
|
||||||
public static final InetSocketAddressJsonSimpledCoder instance = new InetSocketAddressJsonSimpledCoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void convertTo(JsonWriter out, InetSocketAddress value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
StringSimpledCoder.instance.convertTo(out, value.getHostString() + ":" + value.getPort());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InetSocketAddress convertFrom(JsonReader in) {
|
|
||||||
String str = StringSimpledCoder.instance.convertFrom(in);
|
|
||||||
if (str == null) return null;
|
|
||||||
try {
|
|
||||||
int pos = str.indexOf(':');
|
|
||||||
return new InetSocketAddress(str.substring(0, pos), Integer.parseInt(str.substring(pos + 1)));
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,349 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.json;
|
|
||||||
|
|
||||||
import java.nio.*;
|
|
||||||
import java.nio.charset.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class JsonByteBufferWriter extends JsonWriter {
|
|
||||||
|
|
||||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
|
||||||
|
|
||||||
private final Charset charset;
|
|
||||||
|
|
||||||
private final Supplier<ByteBuffer> supplier;
|
|
||||||
|
|
||||||
private ByteBuffer[] buffers;
|
|
||||||
|
|
||||||
private int index;
|
|
||||||
|
|
||||||
protected JsonByteBufferWriter(Supplier<ByteBuffer> supplier) {
|
|
||||||
this(null, supplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JsonByteBufferWriter(Charset charset, Supplier<ByteBuffer> supplier) {
|
|
||||||
this.charset = UTF8.equals(charset) ? null : charset;
|
|
||||||
this.supplier = supplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonByteBufferWriter setTiny(boolean tiny) {
|
|
||||||
this.tiny = tiny;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean recycle() {
|
|
||||||
this.index = 0;
|
|
||||||
this.buffers = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuffer[] toBuffers() {
|
|
||||||
if (buffers == null) return new ByteBuffer[0];
|
|
||||||
for (int i = index; i < this.buffers.length; i++) {
|
|
||||||
ByteBuffer buf = this.buffers[i];
|
|
||||||
if (buf.position() != 0) buf.flip();
|
|
||||||
}
|
|
||||||
return this.buffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int count() {
|
|
||||||
if (this.buffers == null) return 0;
|
|
||||||
int len = 0;
|
|
||||||
for (ByteBuffer buffer : buffers) {
|
|
||||||
len += buffer.remaining();
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int expand(final int byteLength) {
|
|
||||||
if (this.buffers == null) {
|
|
||||||
this.index = 0;
|
|
||||||
this.buffers = new ByteBuffer[]{supplier.get()};
|
|
||||||
}
|
|
||||||
ByteBuffer buffer = this.buffers[index];
|
|
||||||
if (!buffer.hasRemaining()) {
|
|
||||||
buffer.flip();
|
|
||||||
buffer = supplier.get();
|
|
||||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
|
||||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
|
||||||
bufs[this.buffers.length] = buffer;
|
|
||||||
this.buffers = bufs;
|
|
||||||
this.index++;
|
|
||||||
}
|
|
||||||
int len = buffer.remaining();
|
|
||||||
int size = 0;
|
|
||||||
while (len < byteLength) {
|
|
||||||
buffer = supplier.get();
|
|
||||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
|
||||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
|
||||||
bufs[this.buffers.length] = buffer;
|
|
||||||
this.buffers = bufs;
|
|
||||||
len += buffer.remaining();
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeTo(final char ch) {
|
|
||||||
if (ch > Byte.MAX_VALUE) throw new RuntimeException("writeTo char(int.value = " + (int) ch + ") must be less 127");
|
|
||||||
expand(1);
|
|
||||||
this.buffers[index].put((byte) ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeTo(final char[] chs, final int start, final int len) {
|
|
||||||
writeTo(-1, false, chs, start, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeTo(int expandsize, final boolean quote, final char[] chs, final int start, final int len) {
|
|
||||||
int byteLength = quote ? 2 : 0;
|
|
||||||
ByteBuffer bb = null;
|
|
||||||
if (charset == null) {
|
|
||||||
byteLength += encodeUTF8Length(chs, start, len);
|
|
||||||
} else {
|
|
||||||
bb = charset.encode(CharBuffer.wrap(chs, start, len));
|
|
||||||
byteLength += bb.remaining();
|
|
||||||
}
|
|
||||||
if (expandsize < 0) expandsize = expand(byteLength);
|
|
||||||
if (expandsize == 0) { // 只需要一个buffer
|
|
||||||
final ByteBuffer buffer = this.buffers[index];
|
|
||||||
if (quote) buffer.put((byte) '"');
|
|
||||||
|
|
||||||
if (charset == null) { //UTF-8
|
|
||||||
final int limit = start + len;
|
|
||||||
for (int i = start; i < limit; i++) {
|
|
||||||
char c = chs[i];
|
|
||||||
if (c < 0x80) {
|
|
||||||
buffer.put((byte) c);
|
|
||||||
} else if (c < 0x800) {
|
|
||||||
buffer.put((byte) (0xc0 | (c >> 6)));
|
|
||||||
buffer.put((byte) (0x80 | (c & 0x3f)));
|
|
||||||
} else {
|
|
||||||
buffer.put((byte) (0xe0 | ((c >> 12))));
|
|
||||||
buffer.put((byte) (0x80 | ((c >> 6) & 0x3f)));
|
|
||||||
buffer.put((byte) (0x80 | (c & 0x3f)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buffer.put(bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quote) buffer.put((byte) '"');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ByteBuffer buffer = this.buffers[index];
|
|
||||||
if (quote) {
|
|
||||||
if (!buffer.hasRemaining()) buffer = nextByteBuffer();
|
|
||||||
buffer.put((byte) '"');
|
|
||||||
}
|
|
||||||
if (charset == null) { //UTF-8
|
|
||||||
final int limit = start + len;
|
|
||||||
for (int i = start; i < limit; i++) {
|
|
||||||
buffer = putChar(buffer, chs[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while (bb.hasRemaining()) {
|
|
||||||
if (!buffer.hasRemaining()) buffer = nextByteBuffer();
|
|
||||||
buffer.put(bb.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (quote) {
|
|
||||||
if (!buffer.hasRemaining()) buffer = nextByteBuffer();
|
|
||||||
buffer.put((byte) '"');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ByteBuffer putChar(ByteBuffer buffer, char c) {
|
|
||||||
if (c < 0x80) {
|
|
||||||
if (!buffer.hasRemaining()) buffer = nextByteBuffer();
|
|
||||||
buffer.put((byte) c);
|
|
||||||
} else if (c < 0x800) {
|
|
||||||
if (!buffer.hasRemaining()) buffer = nextByteBuffer();
|
|
||||||
buffer.put((byte) (0xc0 | (c >> 6)));
|
|
||||||
if (!buffer.hasRemaining()) buffer = nextByteBuffer();
|
|
||||||
buffer.put((byte) (0x80 | (c & 0x3f)));
|
|
||||||
} else {
|
|
||||||
if (!buffer.hasRemaining()) buffer = nextByteBuffer();
|
|
||||||
buffer.put((byte) (0xe0 | ((c >> 12))));
|
|
||||||
if (!buffer.hasRemaining()) buffer = nextByteBuffer();
|
|
||||||
buffer.put((byte) (0x80 | ((c >> 6) & 0x3f)));
|
|
||||||
if (!buffer.hasRemaining()) buffer = nextByteBuffer();
|
|
||||||
buffer.put((byte) (0x80 | (c & 0x3f)));
|
|
||||||
}
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ByteBuffer nextByteBuffer() {
|
|
||||||
this.buffers[this.index].flip();
|
|
||||||
return this.buffers[++this.index];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int encodeUTF8Length(final char[] text, final int start, final int len) {
|
|
||||||
char c;
|
|
||||||
int size = 0;
|
|
||||||
final char[] chars = text;
|
|
||||||
final int limit = start + len;
|
|
||||||
for (int i = start; i < limit; i++) {
|
|
||||||
c = chars[i];
|
|
||||||
size += (c < 0x80 ? 1 : (c < 0x800 ? 2 : 3));
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int encodeEscapeUTF8Length(final char[] text, final int start, final int len) {
|
|
||||||
char c;
|
|
||||||
int size = 0;
|
|
||||||
final char[] chars = text;
|
|
||||||
final int limit = start + len;
|
|
||||||
for (int i = start; i < limit; i++) {
|
|
||||||
c = chars[i];
|
|
||||||
switch (c) {
|
|
||||||
case '\n': size += 2;
|
|
||||||
break;
|
|
||||||
case '\r': size += 2;
|
|
||||||
break;
|
|
||||||
case '\t': size += 2;
|
|
||||||
break;
|
|
||||||
case '\\': size += 2;
|
|
||||||
break;
|
|
||||||
case '"': size += 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
size += (c < 0x80 ? 1 : (c < 0x800 ? 2 : 3));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>注意:</b> 该String值不能为null且不会进行转义, 只用于不含需要转义字符的字符串,例如enum、double、BigInteger转换的String
|
|
||||||
*
|
|
||||||
* @param quote
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void writeTo(final boolean quote, final String value) {
|
|
||||||
char[] chs = Utility.charArray(value);
|
|
||||||
writeTo(-1, quote, chs, 0, chs.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeString(String value) {
|
|
||||||
if (value == null) {
|
|
||||||
writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final char[] chs = Utility.charArray(value);
|
|
||||||
int len = 0;
|
|
||||||
for (char ch : chs) {
|
|
||||||
switch (ch) {
|
|
||||||
case '\n': len += 2;
|
|
||||||
break;
|
|
||||||
case '\r': len += 2;
|
|
||||||
break;
|
|
||||||
case '\t': len += 2;
|
|
||||||
break;
|
|
||||||
case '\\': len += 2;
|
|
||||||
break;
|
|
||||||
case '"': len += 2;
|
|
||||||
break;
|
|
||||||
default: len++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (len == chs.length) {
|
|
||||||
writeTo(-1, true, chs, 0, len);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int expandsize = -1;
|
|
||||||
if (this.charset == null) { //UTF-8
|
|
||||||
final int byteLength = 2 + encodeEscapeUTF8Length(chs, 0, chs.length);
|
|
||||||
expandsize = expand(byteLength);
|
|
||||||
if (expandsize == 0) { // 只需要一个buffer
|
|
||||||
final ByteBuffer buffer = this.buffers[index];
|
|
||||||
buffer.put((byte) '"');
|
|
||||||
for (char c : chs) {
|
|
||||||
switch (c) {
|
|
||||||
case '\n': buffer.put((byte) '\\').put((byte) 'n');
|
|
||||||
break;
|
|
||||||
case '\r': buffer.put((byte) '\\').put((byte) 'r');
|
|
||||||
break;
|
|
||||||
case '\t': buffer.put((byte) '\\').put((byte) 't');
|
|
||||||
break;
|
|
||||||
case '\\': buffer.put((byte) '\\').put((byte) '\\');
|
|
||||||
break;
|
|
||||||
case '"': buffer.put((byte) '\\').put((byte) '"');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (c < 0x80) {
|
|
||||||
buffer.put((byte) c);
|
|
||||||
} else if (c < 0x800) {
|
|
||||||
buffer.put((byte) (0xc0 | (c >> 6)));
|
|
||||||
buffer.put((byte) (0x80 | (c & 0x3f)));
|
|
||||||
} else {
|
|
||||||
buffer.put((byte) (0xe0 | ((c >> 12))));
|
|
||||||
buffer.put((byte) (0x80 | ((c >> 6) & 0x3f)));
|
|
||||||
buffer.put((byte) (0x80 | (c & 0x3f)));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer.put((byte) '"');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder(len);
|
|
||||||
for (char ch : chs) {
|
|
||||||
switch (ch) {
|
|
||||||
case '\n': sb.append("\\n");
|
|
||||||
break;
|
|
||||||
case '\r': sb.append("\\r");
|
|
||||||
break;
|
|
||||||
case '\t': sb.append("\\t");
|
|
||||||
break;
|
|
||||||
case '\\': sb.append("\\\\");
|
|
||||||
break;
|
|
||||||
case '"': sb.append("\\\"");
|
|
||||||
break;
|
|
||||||
default: sb.append(ch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char[] cs = Utility.charArray(sb);
|
|
||||||
writeTo(expandsize, true, cs, 0, sb.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeField(boolean comma, Attribute attribute) {
|
|
||||||
if (comma) writeTo(',');
|
|
||||||
writeTo(true, attribute.field());
|
|
||||||
writeTo(':');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeSmallString(String value) {
|
|
||||||
writeTo(false, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return Objects.toString(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.json;
|
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.nio.*;
|
|
||||||
import java.nio.charset.*;
|
|
||||||
import java.util.function.*;
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class JsonConvert extends Convert<JsonReader, JsonWriter> {
|
|
||||||
|
|
||||||
public static final Type TYPE_MAP_STRING_STRING = new TypeToken<java.util.LinkedHashMap<String, String>>() {
|
|
||||||
}.getType();
|
|
||||||
|
|
||||||
private static final ObjectPool<JsonReader> readerPool = JsonReader.createPool(Integer.getInteger("convert.json.pool.size", 16));
|
|
||||||
|
|
||||||
private static final ObjectPool<JsonWriter> writerPool = JsonWriter.createPool(Integer.getInteger("convert.json.pool.size", 16));
|
|
||||||
|
|
||||||
private final boolean tiny;
|
|
||||||
|
|
||||||
protected JsonConvert(JsonFactory factory, boolean tiny) {
|
|
||||||
super(factory);
|
|
||||||
this.tiny = tiny;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonByteBufferWriter pollJsonWriter(final Supplier<ByteBuffer> supplier) {
|
|
||||||
return new JsonByteBufferWriter(supplier).setTiny(tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonByteBufferWriter pollJsonWriter(final Charset charset, final Supplier<ByteBuffer> supplier) {
|
|
||||||
return new JsonByteBufferWriter(charset, supplier).setTiny(tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonWriter pollJsonWriter() {
|
|
||||||
return writerPool.get().setTiny(tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offerJsonWriter(JsonWriter out) {
|
|
||||||
if (out != null) writerPool.offer(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonFactory getFactory() {
|
|
||||||
return (JsonFactory) factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T convertFrom(final Type type, final String text) {
|
|
||||||
if (text == null) return null;
|
|
||||||
return convertFrom(type, Utility.charArray(text));
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T convertFrom(final Type type, final char[] text) {
|
|
||||||
if (text == null) return null;
|
|
||||||
return convertFrom(type, text, 0, text.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T convertFrom(final Type type, final char[] text, int start, int len) {
|
|
||||||
if (text == null || type == null) return null;
|
|
||||||
final JsonReader in = readerPool.get();
|
|
||||||
in.setText(text, start, len);
|
|
||||||
T rs = (T) factory.loadDecoder(type).convertFrom(in);
|
|
||||||
readerPool.offer(in);
|
|
||||||
return rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String convertTo(final Type type, Object value) {
|
|
||||||
if (type == null) return null;
|
|
||||||
if (value == null) return "null";
|
|
||||||
final JsonWriter out = writerPool.get().setTiny(tiny);
|
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
|
||||||
String result = out.toString();
|
|
||||||
writerPool.offer(out);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String convertTo(Object value) {
|
|
||||||
if (value == null) return "null";
|
|
||||||
return convertTo(value.getClass(), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void convertTo(final JsonWriter out, final Type type, Object value) {
|
|
||||||
if (type == null) return;
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void convertTo(final JsonWriter out, Object value) {
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
factory.loadEncoder(value.getClass()).convertTo(out, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, Object value) {
|
|
||||||
return convertTo(null, supplier, type, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer[] convertTo(final Charset charset, final Supplier<ByteBuffer> supplier, final Type type, Object value) {
|
|
||||||
if (supplier == null || type == null) return null;
|
|
||||||
JsonByteBufferWriter out = new JsonByteBufferWriter(charset, supplier);
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
|
||||||
}
|
|
||||||
return out.toBuffers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, Object value) {
|
|
||||||
return convertTo(null, supplier, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer[] convertTo(final Charset charset, final Supplier<ByteBuffer> supplier, Object value) {
|
|
||||||
if (supplier == null) return null;
|
|
||||||
JsonByteBufferWriter out = new JsonByteBufferWriter(charset, supplier);
|
|
||||||
if (value == null) {
|
|
||||||
out.writeNull();
|
|
||||||
} else {
|
|
||||||
factory.loadEncoder(value.getClass()).convertTo(out, value);
|
|
||||||
}
|
|
||||||
return out.toBuffers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.json;
|
|
||||||
|
|
||||||
import org.redkale.convert.ConvertType;
|
|
||||||
import org.redkale.convert.Factory;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.net.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class JsonFactory extends Factory<JsonReader, JsonWriter> {
|
|
||||||
|
|
||||||
private static final JsonFactory instance = new JsonFactory(null, Boolean.getBoolean("convert.json.tiny"));
|
|
||||||
|
|
||||||
static {
|
|
||||||
instance.register(InetAddress.class, InetAddressJsonSimpledCoder.instance);
|
|
||||||
instance.register(InetSocketAddress.class, InetAddressJsonSimpledCoder.InetSocketAddressJsonSimpledCoder.instance);
|
|
||||||
instance.register(DLong.class, DLongJsonSimpledCoder.instance);
|
|
||||||
instance.register(Serializable.class, instance.loadEncoder(Object.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonFactory(JsonFactory parent, boolean tiny) {
|
|
||||||
super(parent, tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsonFactory root() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final JsonConvert getConvert() {
|
|
||||||
if (convert == null) convert = new JsonConvert(this, tiny);
|
|
||||||
return (JsonConvert) convert;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonFactory createChild() {
|
|
||||||
return new JsonFactory(this, this.tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonFactory createChild(boolean tiny) {
|
|
||||||
return new JsonFactory(this, tiny);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConvertType getConvertType() {
|
|
||||||
return ConvertType.JSON;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isReversible() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,578 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.json;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.*;
|
|
||||||
import java.util.function.*;
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
import static org.redkale.convert.Reader.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class JsonReader implements Reader {
|
|
||||||
|
|
||||||
private int position = -1;
|
|
||||||
|
|
||||||
private char[] text;
|
|
||||||
|
|
||||||
private int limit;
|
|
||||||
|
|
||||||
public static ObjectPool<JsonReader> createPool(int max) {
|
|
||||||
return new ObjectPool<JsonReader>(max, new Creator<JsonReader>() { //为了兼容 JDK 6
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonReader create(Object... params) {
|
|
||||||
return new JsonReader();
|
|
||||||
}
|
|
||||||
}, null, new Predicate<JsonReader>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(JsonReader t) {
|
|
||||||
return t.recycle();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonReader() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonReader(String json) {
|
|
||||||
setText(Utility.charArray(json));
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonReader(char[] text) {
|
|
||||||
setText(text, 0, text.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonReader(char[] text, int start, int len) {
|
|
||||||
setText(text, start, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setText(String text) {
|
|
||||||
JsonReader.this.setText(Utility.charArray(text));
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setText(char[] text) {
|
|
||||||
setText(text, 0, text.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setText(char[] text, int start, int len) {
|
|
||||||
this.text = text;
|
|
||||||
this.position = start - 1;
|
|
||||||
this.limit = start + len - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean recycle() {
|
|
||||||
this.position = -1;
|
|
||||||
this.limit = -1;
|
|
||||||
this.text = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
this.recycle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 找到指定的属性值 例如: {id : 1, data : { name : 'a', items : [1,2,3]}} seek('data.items') 直接跳转到 [1,2,3];
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
*/
|
|
||||||
public final void seek(String key) {
|
|
||||||
if (key == null || key.length() < 1) return;
|
|
||||||
final String[] keys = key.split("\\.");
|
|
||||||
nextGoodChar(); //读掉 { [
|
|
||||||
for (String key1 : keys) {
|
|
||||||
while (this.hasNext()) {
|
|
||||||
String field = this.readSmallString();
|
|
||||||
skipBlank();
|
|
||||||
if (key1.equals(field)) break;
|
|
||||||
skipValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳过属性的值
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final void skipValue() {
|
|
||||||
final char ch = nextGoodChar();
|
|
||||||
if (ch == '"' || ch == '\'') {
|
|
||||||
backChar(ch);
|
|
||||||
readString();
|
|
||||||
} else if (ch == '{') {
|
|
||||||
while (hasNext()) {
|
|
||||||
this.readSmallString(); //读掉field
|
|
||||||
this.skipBlank();
|
|
||||||
this.skipValue();
|
|
||||||
}
|
|
||||||
} else if (ch == '[') {
|
|
||||||
while (hasNext()) {
|
|
||||||
this.skipValue();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
char c;
|
|
||||||
for (;;) {
|
|
||||||
c = nextChar();
|
|
||||||
if (c <= ' ') return;
|
|
||||||
if (c == '}' || c == ']' || c == ',' || c == ':') {
|
|
||||||
backChar(c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取下一个字符, 不跳过空白字符
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected char nextChar() {
|
|
||||||
return this.text[++this.position];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳过空白字符, 返回一个非空白字符
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected char nextGoodChar() {
|
|
||||||
char c = nextChar();
|
|
||||||
if (c > ' ') return c;
|
|
||||||
for (;;) {
|
|
||||||
c = nextChar();
|
|
||||||
if (c > ' ') return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 回退最后读取的字符
|
|
||||||
*
|
|
||||||
* @param ch
|
|
||||||
*/
|
|
||||||
protected void backChar(char ch) {
|
|
||||||
this.position--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断下一个非空白字符是否为{
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int readObjectB() {
|
|
||||||
char ch = this.text[++this.position];
|
|
||||||
if (ch == '{') return SIGN_NOLENGTH;
|
|
||||||
if (ch <= ' ') {
|
|
||||||
for (;;) {
|
|
||||||
ch = this.text[++this.position];
|
|
||||||
if (ch > ' ') break;
|
|
||||||
}
|
|
||||||
if (ch == '{') return SIGN_NOLENGTH;
|
|
||||||
}
|
|
||||||
if (ch == 'n' && text[++position] == 'u' && text[++position] == 'l' && text[++position] == 'l') return SIGN_NULL;
|
|
||||||
if (ch == 'N' && text[++position] == 'U' && text[++position] == 'L' && text[++position] == 'L') return SIGN_NULL;
|
|
||||||
throw new ConvertException("a json object text must begin with '{' (position = " + position + ") but '" + ch + "' in (" + new String(this.text) + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readObjectE() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断下一个非空白字符是否为{
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int readMapB() {
|
|
||||||
return readArrayB();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readMapE() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断下一个非空白字符是否为[
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int readArrayB() {
|
|
||||||
char ch = this.text[++this.position];
|
|
||||||
if (ch == '[') return SIGN_NOLENGTH;
|
|
||||||
if (ch == '{') return SIGN_NOLENGTH;
|
|
||||||
if (ch <= ' ') {
|
|
||||||
for (;;) {
|
|
||||||
ch = this.text[++this.position];
|
|
||||||
if (ch > ' ') break;
|
|
||||||
}
|
|
||||||
if (ch == '[') return SIGN_NOLENGTH;
|
|
||||||
if (ch == '{') return SIGN_NOLENGTH;
|
|
||||||
}
|
|
||||||
if (ch == 'n' && text[++position] == 'u' && text[++position] == 'l' && text[++position] == 'l') return SIGN_NULL;
|
|
||||||
if (ch == 'N' && text[++position] == 'U' && text[++position] == 'L' && text[++position] == 'L') return SIGN_NULL;
|
|
||||||
throw new ConvertException("a json array text must begin with '[' (position = " + position + ") but '" + ch + "' in (" + new String(this.text) + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readArrayE() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断下一个非空白字符是否:
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void skipBlank() {
|
|
||||||
char ch = this.text[++this.position];
|
|
||||||
if (ch == ':') return;
|
|
||||||
if (ch <= ' ') {
|
|
||||||
for (;;) {
|
|
||||||
ch = this.text[++this.position];
|
|
||||||
if (ch > ' ') break;
|
|
||||||
}
|
|
||||||
if (ch == ':') return;
|
|
||||||
}
|
|
||||||
throw new ConvertException("'" + new String(text) + "'expected a ':' but '" + ch + "'(position = " + position + ") in (" + new String(this.text) + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
char ch = this.text[++this.position];
|
|
||||||
if (ch == ',') return true;
|
|
||||||
if (ch == '}' || ch == ']') return false;
|
|
||||||
if (ch <= ' ') {
|
|
||||||
for (;;) {
|
|
||||||
ch = this.text[++this.position];
|
|
||||||
if (ch > ' ') break;
|
|
||||||
}
|
|
||||||
if (ch == ',') return true;
|
|
||||||
if (ch == '}' || ch == ']') return false;
|
|
||||||
}
|
|
||||||
this.position--;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String readClassName() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String readSmallString() {
|
|
||||||
final int eof = this.limit;
|
|
||||||
if (this.position == eof) return null;
|
|
||||||
final char[] text0 = this.text;
|
|
||||||
int currpos = this.position;
|
|
||||||
char ch = text0[++currpos];
|
|
||||||
if (ch <= ' ') {
|
|
||||||
for (;;) {
|
|
||||||
ch = text0[++currpos];
|
|
||||||
if (ch > ' ') break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ch == '"' || ch == '\'') {
|
|
||||||
final char quote = ch;
|
|
||||||
final int start = currpos + 1;
|
|
||||||
for (;;) {
|
|
||||||
ch = text0[++currpos];
|
|
||||||
if (ch == '\\') {
|
|
||||||
this.position = currpos - 1;
|
|
||||||
return readEscapeValue(quote, start);
|
|
||||||
} else if (ch == quote) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.position = currpos;
|
|
||||||
char[] chs = new char[currpos - start];
|
|
||||||
System.arraycopy(text0, start, chs, 0, chs.length);
|
|
||||||
return new String(chs);
|
|
||||||
} else {
|
|
||||||
int start = currpos;
|
|
||||||
for (;;) {
|
|
||||||
if (currpos == eof) break;
|
|
||||||
ch = text0[++currpos];
|
|
||||||
if (ch == ',' || ch == ']' || ch == '}' || ch <= ' ' || ch == ':') break;
|
|
||||||
}
|
|
||||||
int len = currpos - start;
|
|
||||||
if (len < 1) {
|
|
||||||
this.position = currpos;
|
|
||||||
return String.valueOf(ch);
|
|
||||||
}
|
|
||||||
this.position = currpos - 1;
|
|
||||||
if (len == 4 && text0[start] == 'n' && text0[start + 1] == 'u' && text0[start + 2] == 'l' && text0[start + 3] == 'l') return null;
|
|
||||||
return new String(text0, start, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取一个int
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final int readInt() {
|
|
||||||
final char[] text0 = this.text;
|
|
||||||
final int eof = this.limit;
|
|
||||||
int currpos = this.position;
|
|
||||||
char firstchar = text0[++currpos];
|
|
||||||
if (firstchar <= ' ') {
|
|
||||||
for (;;) {
|
|
||||||
firstchar = text0[++currpos];
|
|
||||||
if (firstchar > ' ') break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (firstchar == '"' || firstchar == '\'') {
|
|
||||||
firstchar = text0[++currpos];
|
|
||||||
if (firstchar == '"' || firstchar == '\'') {
|
|
||||||
this.position = currpos;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int value = 0;
|
|
||||||
final boolean negative = firstchar == '-';
|
|
||||||
if (!negative) {
|
|
||||||
if (firstchar < '0' || firstchar > '9') throw new NumberFormatException("illegal escape(" + firstchar + ") (position = " + currpos + ") in (" + new String(this.text) + ")");
|
|
||||||
value = firstchar - '0';
|
|
||||||
}
|
|
||||||
for (;;) {
|
|
||||||
if (currpos == eof) break;
|
|
||||||
char ch = text0[++currpos];
|
|
||||||
if (ch >= '0' && ch <= '9') {
|
|
||||||
value = (value << 3) + (value << 1) + (ch - '0');
|
|
||||||
} else if (ch == '"' || ch == '\'') {
|
|
||||||
} else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
throw new NumberFormatException("illegal escape(" + ch + ") (position = " + currpos + ") in (" + new String(this.text) + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.position = currpos - 1;
|
|
||||||
return negative ? -value : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取一个long
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public final long readLong() {
|
|
||||||
final char[] text0 = this.text;
|
|
||||||
final int eof = this.limit;
|
|
||||||
int currpos = this.position;
|
|
||||||
char firstchar = text0[++currpos];
|
|
||||||
if (firstchar <= ' ') {
|
|
||||||
for (;;) {
|
|
||||||
firstchar = text0[++currpos];
|
|
||||||
if (firstchar > ' ') break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (firstchar == '"' || firstchar == '\'') {
|
|
||||||
firstchar = text0[++currpos];
|
|
||||||
if (firstchar == '"' || firstchar == '\'') {
|
|
||||||
this.position = currpos;
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
long value = 0;
|
|
||||||
final boolean negative = firstchar == '-';
|
|
||||||
if (!negative) {
|
|
||||||
if (firstchar < '0' || firstchar > '9') throw new NumberFormatException("illegal escape(" + firstchar + ") (position = " + currpos + ") in (" + new String(this.text) + ")");
|
|
||||||
value = firstchar - '0';
|
|
||||||
}
|
|
||||||
for (;;) {
|
|
||||||
if (currpos == eof) break;
|
|
||||||
char ch = text0[++currpos];
|
|
||||||
if (ch >= '0' && ch <= '9') {
|
|
||||||
value = (value << 3) + (value << 1) + (ch - '0');
|
|
||||||
} else if (ch == '"' || ch == '\'') {
|
|
||||||
} else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
throw new NumberFormatException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.position = currpos - 1;
|
|
||||||
return negative ? -value : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeMember readField(final AtomicInteger index, final DeMember[] members) {
|
|
||||||
final String exceptedfield = this.readSmallString();
|
|
||||||
final int len = members.length;
|
|
||||||
int v = index.get();
|
|
||||||
if (v >= len) {
|
|
||||||
v = 0;
|
|
||||||
index.set(0);
|
|
||||||
}
|
|
||||||
for (int k = v; k < len; k++) {
|
|
||||||
if (exceptedfield.equals(members[k].getAttribute().field())) {
|
|
||||||
index.set(k);
|
|
||||||
return members[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int k = 0; k < v; k++) {
|
|
||||||
if (exceptedfield.equals(members[k].getAttribute().field())) {
|
|
||||||
index.set(k);
|
|
||||||
return members[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
//if (result == null && len == 1 && text0[start] == '@') return REFER;
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean readBoolean() {
|
|
||||||
return "true".equalsIgnoreCase(this.readSmallString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readByte() {
|
|
||||||
return (byte) readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public char readChar() {
|
|
||||||
return (char) readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short readShort() {
|
|
||||||
return (short) readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float readFloat() {
|
|
||||||
String chars = readSmallString();
|
|
||||||
if (chars == null || chars.isEmpty()) return 0.f;
|
|
||||||
return Float.parseFloat(chars);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double readDouble() {
|
|
||||||
String chars = readSmallString();
|
|
||||||
if (chars == null || chars.isEmpty()) return 0.0;
|
|
||||||
return Double.parseDouble(chars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取字符串, 必须是"或者'包围的字符串值
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String readString() {
|
|
||||||
final char[] text0 = this.text;
|
|
||||||
int currpos = this.position;
|
|
||||||
char expected = text0[++currpos];
|
|
||||||
if (expected <= ' ') {
|
|
||||||
for (;;) {
|
|
||||||
expected = text0[++currpos];
|
|
||||||
if (expected > ' ') break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (expected != '"' && expected != '\'') {
|
|
||||||
if (expected == 'n' && text0.length > currpos + 3) {
|
|
||||||
if (text0[++currpos] == 'u' && text0[++currpos] == 'l' && text0[++currpos] == 'l') {
|
|
||||||
this.position = currpos;
|
|
||||||
if (text0.length > currpos + 4) {
|
|
||||||
char ch = text0[currpos + 1];
|
|
||||||
if (ch == ',' || ch <= ' ' || ch == '}' || ch == ']' || ch == ':') return null;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final int start = currpos;
|
|
||||||
for (;;) {
|
|
||||||
char ch = text0[currpos];
|
|
||||||
if (ch == ',' || ch <= ' ' || ch == '}' || ch == ']' || ch == ':') break;
|
|
||||||
currpos++;
|
|
||||||
}
|
|
||||||
if (currpos == start) throw new ConvertException("expected a string after a key but '" + text0[position] + "' (position = " + position + ") in (" + new String(this.text) + ")");
|
|
||||||
this.position = currpos - 1;
|
|
||||||
return new String(text0, start, currpos - start);
|
|
||||||
}
|
|
||||||
this.position = currpos;
|
|
||||||
throw new ConvertException("expected a ':' after a key but '" + text0[position] + "' (position = " + position + ") in (" + new String(this.text) + ")");
|
|
||||||
}
|
|
||||||
final int start = ++currpos;
|
|
||||||
for (;;) {
|
|
||||||
char ch = text0[currpos];
|
|
||||||
if (ch == expected) {
|
|
||||||
break;
|
|
||||||
} else if (ch == '\\') {
|
|
||||||
this.position = currpos - 1;
|
|
||||||
return readEscapeValue(expected, start);
|
|
||||||
}
|
|
||||||
currpos++;
|
|
||||||
}
|
|
||||||
this.position = currpos;
|
|
||||||
return new String(text0, start, currpos - start);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String readEscapeValue(final char expected, int start) {
|
|
||||||
StringBuilder array = new StringBuilder();
|
|
||||||
final char[] text0 = this.text;
|
|
||||||
int pos = this.position;
|
|
||||||
array.append(text0, start, pos + 1 - start);
|
|
||||||
char c;
|
|
||||||
for (;;) {
|
|
||||||
c = text0[++pos];
|
|
||||||
if (c == expected) {
|
|
||||||
this.position = pos;
|
|
||||||
return array.toString();
|
|
||||||
} else if (c == '\\') {
|
|
||||||
c = text0[++pos];
|
|
||||||
switch (c) {
|
|
||||||
case '"':
|
|
||||||
case '\'':
|
|
||||||
case '\\':
|
|
||||||
case '/':
|
|
||||||
array.append(c);
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
array.append('\n');
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
array.append('\r');
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
array.append((char) Integer.parseInt(new String(new char[]{text0[++pos], text0[++pos], text0[++pos], text0[++pos]}), 16));
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
array.append('\t');
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
array.append('\b');
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
array.append('\f');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.position = pos;
|
|
||||||
throw new ConvertException("illegal escape(" + c + ") (position = " + this.position + ") in (" + new String(this.text) + ")");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
array.append(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.json;
|
|
||||||
|
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public abstract class JsonSimpledCoder<T> extends SimpledCoder<JsonReader, JsonWriter, T> {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,269 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.convert.json;
|
|
||||||
|
|
||||||
import java.nio.*;
|
|
||||||
import java.util.function.*;
|
|
||||||
import org.redkale.convert.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* writeTo系列的方法输出的字符不能含特殊字符
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public class JsonWriter implements Writer {
|
|
||||||
|
|
||||||
private static final char[] CHARS_TUREVALUE = "true".toCharArray();
|
|
||||||
|
|
||||||
private static final char[] CHARS_FALSEVALUE = "false".toCharArray();
|
|
||||||
|
|
||||||
private static final int defaultSize = Integer.getInteger("convert.json.writer.buffer.defsize", 1024);
|
|
||||||
|
|
||||||
private int count;
|
|
||||||
|
|
||||||
private char[] content;
|
|
||||||
|
|
||||||
protected boolean tiny;
|
|
||||||
|
|
||||||
public static ObjectPool<JsonWriter> createPool(int max) {
|
|
||||||
return new ObjectPool<JsonWriter>(max, new Creator<JsonWriter>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonWriter create(Object... params) {
|
|
||||||
return new JsonWriter();
|
|
||||||
}
|
|
||||||
}, null, new Predicate<JsonWriter>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(JsonWriter t) {
|
|
||||||
return t.recycle();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonWriter() {
|
|
||||||
this(defaultSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonWriter(int size) {
|
|
||||||
this.content = new char[size > 128 ? size : 128];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTiny() {
|
|
||||||
return tiny;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonWriter setTiny(boolean tiny) {
|
|
||||||
this.tiny = tiny;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
|
||||||
//-----------------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* 返回指定至少指定长度的缓冲区
|
|
||||||
*
|
|
||||||
* @param len
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private char[] expand(int len) {
|
|
||||||
int newcount = count + len;
|
|
||||||
if (newcount <= content.length) return content;
|
|
||||||
char[] newdata = new char[Math.max(content.length * 3 / 2, newcount)];
|
|
||||||
System.arraycopy(content, 0, newdata, 0, count);
|
|
||||||
this.content = newdata;
|
|
||||||
return newdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeTo(final char ch) { //只能是 0 - 127 的字符
|
|
||||||
expand(1);
|
|
||||||
content[count++] = ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeTo(final char[] chs, final int start, final int len) { //只能是 0 - 127 的字符
|
|
||||||
expand(len);
|
|
||||||
System.arraycopy(chs, start, content, count, len);
|
|
||||||
count += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>注意:</b> 该String值不能为null且不会进行转义, 只用于不含需要转义字符的字符串,例如enum、double、BigInteger转换的String
|
|
||||||
*
|
|
||||||
* @param quote
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
public void writeTo(final boolean quote, final String value) {
|
|
||||||
int len = value.length();
|
|
||||||
expand(len + (quote ? 2 : 0));
|
|
||||||
if (quote) content[count++] = '"';
|
|
||||||
value.getChars(0, len, content, count);
|
|
||||||
count += len;
|
|
||||||
if (quote) content[count++] = '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean recycle() {
|
|
||||||
this.count = 0;
|
|
||||||
if (this.content.length > defaultSize) {
|
|
||||||
this.content = new char[defaultSize];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer[] toBuffers() {
|
|
||||||
return new ByteBuffer[]{ByteBuffer.wrap(Utility.encodeUTF8(content, 0, count))};
|
|
||||||
}
|
|
||||||
|
|
||||||
public int count() {
|
|
||||||
return this.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeString(String value) {
|
|
||||||
if (value == null) {
|
|
||||||
writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
expand(value.length() * 2 + 2);
|
|
||||||
content[count++] = '"';
|
|
||||||
for (char ch : Utility.charArray(value)) {
|
|
||||||
switch (ch) {
|
|
||||||
case '\n': content[count++] = '\\';
|
|
||||||
content[count++] = 'n';
|
|
||||||
break;
|
|
||||||
case '\r': content[count++] = '\\';
|
|
||||||
content[count++] = 'r';
|
|
||||||
break;
|
|
||||||
case '\t': content[count++] = '\\';
|
|
||||||
content[count++] = 't';
|
|
||||||
break;
|
|
||||||
case '\\': content[count++] = '\\';
|
|
||||||
content[count++] = ch;
|
|
||||||
break;
|
|
||||||
case '"': content[count++] = '\\';
|
|
||||||
content[count++] = ch;
|
|
||||||
break;
|
|
||||||
default: content[count++] = ch;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
content[count++] = '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeField(boolean comma, Attribute attribute) {
|
|
||||||
if (comma) writeTo(',');
|
|
||||||
writeTo(true, attribute.field());
|
|
||||||
writeTo(':');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeSmallString(String value) {
|
|
||||||
writeTo(true, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return new String(content, 0, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
|
||||||
public final void writeTo(final char... chs) { //只能是 0 - 127 的字符
|
|
||||||
writeTo(chs, 0, chs.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeBoolean(boolean value) {
|
|
||||||
writeTo(value ? CHARS_TUREVALUE : CHARS_FALSEVALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeByte(byte value) {
|
|
||||||
writeInt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeChar(char value) {
|
|
||||||
writeInt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeShort(short value) {
|
|
||||||
writeInt(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeInt(int value) {
|
|
||||||
writeTo(false, String.valueOf(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeLong(long value) {
|
|
||||||
writeTo(false, String.valueOf(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeFloat(float value) {
|
|
||||||
writeTo(false, String.valueOf(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeDouble(double value) {
|
|
||||||
writeTo(false, String.valueOf(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void wirteClassName(String clazz) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeObjectB(int fieldCount, Object obj) {
|
|
||||||
writeTo('{');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeObjectE(Object obj) {
|
|
||||||
writeTo('}');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeNull() {
|
|
||||||
writeTo('n', 'u', 'l', 'l');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeArrayB(int size) {
|
|
||||||
writeTo('[');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeArrayMark() {
|
|
||||||
writeTo(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeArrayE() {
|
|
||||||
writeTo(']');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeMapB(int size) {
|
|
||||||
writeTo('{');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeMapMark() {
|
|
||||||
writeTo(':');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeMapE() {
|
|
||||||
writeTo('}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.net.client;
|
|
||||||
|
|
||||||
import java.net.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 待开发……
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class HttpClient {
|
|
||||||
|
|
||||||
protected Map<String, HttpCookie> cookies;
|
|
||||||
|
|
||||||
protected Map<String, String> headers;
|
|
||||||
|
|
||||||
protected Map<String, String> params;
|
|
||||||
|
|
||||||
protected final HttpFactory root;
|
|
||||||
|
|
||||||
protected final URL url;
|
|
||||||
|
|
||||||
private String method = "GET";
|
|
||||||
|
|
||||||
HttpClient(HttpFactory root, URL url) {
|
|
||||||
this.root = root;
|
|
||||||
this.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient setTimeoutListener(Runnable runner) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient getMethod() {
|
|
||||||
this.method = "GET";
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient postMethod() {
|
|
||||||
this.method = "POST";
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getHeaders() {
|
|
||||||
return this.headers == null ? null : new HashMap<String, String>(this.headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient addHeader(String name, String value) {
|
|
||||||
if (this.headers == null && name != null) this.headers = new HashMap<String, String>();
|
|
||||||
this.headers.put(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient addHeader(final Map<String, String> headerMap) {
|
|
||||||
if (headerMap == null || headerMap.isEmpty()) return this;
|
|
||||||
if (this.headers == null) this.headers = new HashMap<String, String>();
|
|
||||||
this.headers.putAll(headerMap);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient removeHeader(String name) {
|
|
||||||
if (this.headers == null || name == null) return this;
|
|
||||||
headers.remove(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, HttpCookie> getCookies() {
|
|
||||||
return this.cookies == null ? null : new HashMap<String, HttpCookie>(this.cookies);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient addCookie(final HttpCookie cookie) {
|
|
||||||
if (this.cookies == null) this.cookies = new HashMap<String, HttpCookie>();
|
|
||||||
if (cookie != null) this.cookies.put(cookie.getName(), cookie);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient addCookie(final HttpCookie... httpCookies) {
|
|
||||||
if (httpCookies == null || httpCookies.length < 1) return this;
|
|
||||||
if (this.cookies == null) this.cookies = new HashMap<String, HttpCookie>();
|
|
||||||
for (HttpCookie c : httpCookies) {
|
|
||||||
if (c != null) this.cookies.put(c.getName(), c);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient removeCookie(final String name) {
|
|
||||||
if (this.cookies != null && name != null) this.cookies.remove(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
URL url = new URL("https://www.redkale.org");
|
|
||||||
System.out.println(url.openConnection().getClass());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.net.client;
|
|
||||||
|
|
||||||
import java.net.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 待开发……
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public class HttpFactory {
|
|
||||||
|
|
||||||
private static final HttpFactory instance = new HttpFactory(null);
|
|
||||||
|
|
||||||
final HttpFactory parent;
|
|
||||||
|
|
||||||
final Map<String, HttpCookie> defaultCookies = new ConcurrentHashMap<String, HttpCookie>();
|
|
||||||
|
|
||||||
final Map<String, String> defaultHeaders = new ConcurrentHashMap<String, String>();
|
|
||||||
|
|
||||||
private HttpFactory(HttpFactory parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpFactory parent() {
|
|
||||||
return this.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HttpFactory root() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpFactory createChild() {
|
|
||||||
return new HttpFactory(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getDefaultHeader() {
|
|
||||||
return new HashMap<String, String>(defaultHeaders);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpFactory addDefaultHeader(String name, String value) {
|
|
||||||
defaultHeaders.put(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpFactory removeDefaultHeader(String name) {
|
|
||||||
defaultHeaders.remove(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpFactory addDefaultCookie(HttpCookie cookie) {
|
|
||||||
if (cookie != null) defaultCookies.put(cookie.getName(), cookie);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpFactory addDefaultCookie(HttpCookie... cookies) {
|
|
||||||
if (cookies != null) {
|
|
||||||
for (HttpCookie c : cookies) {
|
|
||||||
if (c != null) defaultCookies.put(c.getName(), c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpFactory removeDefaultCookie(String name) {
|
|
||||||
defaultCookies.remove(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient open(URL url) {
|
|
||||||
return new HttpClient(this, url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.net.client;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import javax.net.ssl.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 待开发……
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public class WebSocketClient {
|
|
||||||
|
|
||||||
protected final boolean ssl;
|
|
||||||
|
|
||||||
protected final URI uri;
|
|
||||||
|
|
||||||
protected final Map<String, String> headers = new HashMap<String, String>();
|
|
||||||
|
|
||||||
private Proxy proxy;
|
|
||||||
|
|
||||||
private SSLContext sslContext;
|
|
||||||
|
|
||||||
private Socket socket;
|
|
||||||
|
|
||||||
private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
|
|
||||||
|
|
||||||
private WebSocketClient(URI uri, Map<String, String> headers0) {
|
|
||||||
this.uri = uri;
|
|
||||||
this.ssl = "wss".equalsIgnoreCase(uri.getScheme());
|
|
||||||
if (headers0 != null) this.headers.putAll(headers0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public URI getURI() {
|
|
||||||
return uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static WebSocketClient create(URI uri) {
|
|
||||||
return create(uri, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static WebSocketClient create(URI uri, Map<String, String> headers) {
|
|
||||||
return new WebSocketClient(uri, headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebSocketClient setSSLContext(SSLContext sslContext) {
|
|
||||||
this.sslContext = sslContext;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebSocketClient setProxy(Proxy proxy) {
|
|
||||||
this.proxy = proxy;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebSocketClient addHeader(String name, String value) {
|
|
||||||
this.headers.put(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPort() {
|
|
||||||
int port = uri.getPort();
|
|
||||||
if (port > 0) return port;
|
|
||||||
return ssl ? 443 : 80;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void connect() throws IOException {
|
|
||||||
if (ssl) {
|
|
||||||
if (proxy == null) {
|
|
||||||
this.socket = (sslContext == null ? Utility.getDefaultSSLContext() : sslContext).getSocketFactory().createSocket(uri.getHost(), getPort());
|
|
||||||
} else {
|
|
||||||
Socket s = new Socket(proxy);
|
|
||||||
this.socket.setSoTimeout(3000);
|
|
||||||
s.connect(new InetSocketAddress(uri.getHost(), getPort()));
|
|
||||||
this.socket = (sslContext == null ? Utility.getDefaultSSLContext() : sslContext).getSocketFactory().createSocket(s, uri.getHost(), getPort(), true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.socket = proxy == null ? new Socket() : new Socket(proxy);
|
|
||||||
this.socket.setSoTimeout(3000);
|
|
||||||
this.socket.connect(new InetSocketAddress(uri.getHost(), getPort()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
URI uri = new URI("ws://10.28.2.207:5050/pipes/ws/listen?test=aa");
|
|
||||||
WebSocketClient client = WebSocketClient.create(uri);
|
|
||||||
client.connect();
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onConnected() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMessage(String text) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPing(byte[] bytes) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPong(byte[] bytes) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMessage(byte[] bytes) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onFragment(String text, boolean last) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onFragment(byte[] bytes, boolean last) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onClose(int code, String reason) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前WebSocket下的属性
|
|
||||||
* <p>
|
|
||||||
* @param <T>
|
|
||||||
* @param name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final <T> T getAttribute(String name) {
|
|
||||||
return (T) attributes.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 移出当前WebSocket下的属性
|
|
||||||
* <p>
|
|
||||||
* @param <T>
|
|
||||||
* @param name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public final <T> T removeAttribute(String name) {
|
|
||||||
return (T) attributes.remove(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 给当前WebSocket下的增加属性
|
|
||||||
* <p>
|
|
||||||
* @param name
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
public final void setAttribute(String name, Object value) {
|
|
||||||
attributes.put(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,446 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.BiPredicate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 该类提供类似JSONObject的数据结构,主要用于读取xml配置文件和http-header存储
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public abstract class AnyValue {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 可读写的AnyValue默认实现类
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static final class DefaultAnyValue extends AnyValue {
|
|
||||||
|
|
||||||
public static final BiPredicate<String, String> EQUALS = new BiPredicate<String, String>() {
|
|
||||||
@Override
|
|
||||||
public boolean test(String name1, String name2) {
|
|
||||||
return name1.equals(name2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final BiPredicate<String, String> EQUALSIGNORE = new BiPredicate<String, String>() {
|
|
||||||
@Override
|
|
||||||
public boolean test(String name1, String name2) {
|
|
||||||
return name1.equalsIgnoreCase(name2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final BiPredicate<String, String> predicate;
|
|
||||||
|
|
||||||
private Entry<String>[] stringValues = new Entry[0];
|
|
||||||
|
|
||||||
private Entry<AnyValue>[] entityValues = new Entry[0];
|
|
||||||
|
|
||||||
public static final DefaultAnyValue create() {
|
|
||||||
return new DefaultAnyValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final DefaultAnyValue create(String name, String value) {
|
|
||||||
DefaultAnyValue conf = new DefaultAnyValue();
|
|
||||||
conf.addValue(name, value);
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final DefaultAnyValue create(String name, AnyValue value) {
|
|
||||||
DefaultAnyValue conf = new DefaultAnyValue();
|
|
||||||
conf.addValue(name, value);
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue() {
|
|
||||||
this(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue(boolean ignoreCase) {
|
|
||||||
this.predicate = ignoreCase ? EQUALSIGNORE : EQUALS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue(BiPredicate<String, String> predicate) {
|
|
||||||
this.predicate = predicate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue duplicate() {
|
|
||||||
DefaultAnyValue rs = new DefaultAnyValue(this.predicate);
|
|
||||||
rs.stringValues = this.stringValues;
|
|
||||||
rs.entityValues = this.entityValues;
|
|
||||||
return rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue addAll(final AnyValue av) {
|
|
||||||
if (av == null) return this;
|
|
||||||
if (av instanceof DefaultAnyValue) {
|
|
||||||
final DefaultAnyValue adv = (DefaultAnyValue) av;
|
|
||||||
if (adv.stringValues != null) {
|
|
||||||
for (Entry<String> en : adv.stringValues) {
|
|
||||||
this.addValue(en.name, en.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (adv.entityValues != null) {
|
|
||||||
for (Entry<AnyValue> en : adv.entityValues) {
|
|
||||||
this.addValue(en.name, en.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final Entry<String>[] strings = av.getStringEntrys();
|
|
||||||
if (strings != null) {
|
|
||||||
for (Entry<String> en : strings) {
|
|
||||||
this.addValue(en.name, en.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final Entry<AnyValue>[] anys = av.getAnyEntrys();
|
|
||||||
if (anys != null) {
|
|
||||||
for (Entry<AnyValue> en : anys) {
|
|
||||||
this.addValue(en.name, en.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue setAll(final AnyValue av) {
|
|
||||||
if (av == null) return this;
|
|
||||||
if (av instanceof DefaultAnyValue) {
|
|
||||||
final DefaultAnyValue adv = (DefaultAnyValue) av;
|
|
||||||
if (adv.stringValues != null) {
|
|
||||||
for (Entry<String> en : adv.stringValues) {
|
|
||||||
this.setValue(en.name, en.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (adv.entityValues != null) {
|
|
||||||
for (Entry<AnyValue> en : adv.entityValues) {
|
|
||||||
this.setValue(en.name, en.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final Entry<String>[] strings = av.getStringEntrys();
|
|
||||||
if (strings != null) {
|
|
||||||
for (Entry<String> en : strings) {
|
|
||||||
this.setValue(en.name, en.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final Entry<AnyValue>[] anys = av.getAnyEntrys();
|
|
||||||
if (anys != null) {
|
|
||||||
for (Entry<AnyValue> en : anys) {
|
|
||||||
this.setValue(en.name, en.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entry<String>[] getStringEntrys() {
|
|
||||||
return stringValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entry<AnyValue>[] getAnyEntrys() {
|
|
||||||
return entityValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getNames() {
|
|
||||||
Set<String> set = new LinkedHashSet();
|
|
||||||
for (Entry en : this.stringValues) {
|
|
||||||
set.add(en.name);
|
|
||||||
}
|
|
||||||
for (Entry en : this.entityValues) {
|
|
||||||
set.add(en.name);
|
|
||||||
}
|
|
||||||
return set.toArray(new String[set.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getValues(String... names) {
|
|
||||||
return Entry.getValues(this.predicate, String.class, this.stringValues, names);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AnyValue[] getAnyValues(String... names) {
|
|
||||||
return Entry.getValues(this.predicate, AnyValue.class, this.entityValues, names);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return toString(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue clear() {
|
|
||||||
this.stringValues = new Entry[0];
|
|
||||||
this.entityValues = new Entry[0];
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue setValue(String name, String value) {
|
|
||||||
if (name == null) return this;
|
|
||||||
if (getValue(name) == null) {
|
|
||||||
this.addValue(name, value);
|
|
||||||
} else {
|
|
||||||
for (Entry<String> en : this.stringValues) {
|
|
||||||
if (predicate.test(en.name, name)) {
|
|
||||||
en.value = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue setValue(String name, AnyValue value) {
|
|
||||||
if (name == null) return this;
|
|
||||||
if (getValue(name) == null) {
|
|
||||||
this.addValue(name, value);
|
|
||||||
} else {
|
|
||||||
for (Entry<AnyValue> en : this.entityValues) {
|
|
||||||
if (predicate.test(en.name, name)) {
|
|
||||||
en.value = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue addValue(String name, String value) {
|
|
||||||
if (name == null) return this;
|
|
||||||
int len = this.stringValues.length;
|
|
||||||
Entry[] news = new Entry[len + 1];
|
|
||||||
System.arraycopy(this.stringValues, 0, news, 0, len);
|
|
||||||
news[len] = new Entry(name, value);
|
|
||||||
this.stringValues = news;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultAnyValue addValue(String name, AnyValue value) {
|
|
||||||
if (name == null || value == null) return this;
|
|
||||||
int len = this.entityValues.length;
|
|
||||||
Entry[] news = new Entry[len + 1];
|
|
||||||
System.arraycopy(this.entityValues, 0, news, 0, len);
|
|
||||||
news[len] = new Entry(name, value);
|
|
||||||
this.entityValues = news;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AnyValue getAnyValue(String name) {
|
|
||||||
for (Entry<AnyValue> en : this.entityValues) {
|
|
||||||
if (predicate.test(en.name, name)) {
|
|
||||||
return en.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getValue(String name) {
|
|
||||||
for (Entry<String> en : this.stringValues) {
|
|
||||||
if (predicate.test(en.name, name)) {
|
|
||||||
return en.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getValues(String name) {
|
|
||||||
return Entry.getValues(this.predicate, String.class, this.stringValues, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AnyValue[] getAnyValues(String name) {
|
|
||||||
return Entry.getValues(this.predicate, AnyValue.class, this.entityValues, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Entry<T> {
|
|
||||||
|
|
||||||
public final String name;
|
|
||||||
|
|
||||||
T value;
|
|
||||||
|
|
||||||
public Entry(String name0, T value0) {
|
|
||||||
this.name = name0;
|
|
||||||
this.value = value0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static <T> T[] getValues(BiPredicate<String, String> comparison, Class<T> clazz, Entry<T>[] entitys, String name) {
|
|
||||||
int len = 0;
|
|
||||||
for (Entry en : entitys) {
|
|
||||||
if (comparison.test(en.name, name)) {
|
|
||||||
++len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (len == 0) return (T[]) Array.newInstance(clazz, len);
|
|
||||||
T[] rs = (T[]) Array.newInstance(clazz, len);
|
|
||||||
int i = 0;
|
|
||||||
for (Entry<T> en : entitys) {
|
|
||||||
if (comparison.test(en.name, name)) {
|
|
||||||
rs[i++] = en.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static <T> T[] getValues(BiPredicate<String, String> comparison, Class<T> clazz, Entry<T>[] entitys, String... names) {
|
|
||||||
int len = 0;
|
|
||||||
for (Entry en : entitys) {
|
|
||||||
for (String name : names) {
|
|
||||||
if (comparison.test(en.name, name)) {
|
|
||||||
++len;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (len == 0) return (T[]) Array.newInstance(clazz, len);
|
|
||||||
T[] rs = (T[]) Array.newInstance(clazz, len);
|
|
||||||
int i = 0;
|
|
||||||
for (Entry<T> en : entitys) {
|
|
||||||
for (String name : names) {
|
|
||||||
if (comparison.test(en.name, name)) {
|
|
||||||
rs[i++] = en.value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AnyValue create() {
|
|
||||||
return new DefaultAnyValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String toString(int len) {
|
|
||||||
if (len < 0) len = 0;
|
|
||||||
char[] chars = new char[len];
|
|
||||||
Arrays.fill(chars, ' ');
|
|
||||||
final String space = new String(chars);
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("{\r\n");
|
|
||||||
for (Entry<String> en : getStringEntrys()) {
|
|
||||||
sb.append(space).append(" '").append(en.name).append("': '").append(en.value).append("',\r\n");
|
|
||||||
}
|
|
||||||
for (Entry<AnyValue> en : getAnyEntrys()) {
|
|
||||||
sb.append(space).append(" '").append(en.name).append("': '").append(en.value.toString(len + 4)).append("',\r\n");
|
|
||||||
}
|
|
||||||
sb.append(space).append('}');
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Entry<String>[] getStringEntrys();
|
|
||||||
|
|
||||||
public abstract Entry<AnyValue>[] getAnyEntrys();
|
|
||||||
|
|
||||||
public abstract String[] getNames();
|
|
||||||
|
|
||||||
public abstract String[] getValues(String name);
|
|
||||||
|
|
||||||
public abstract String[] getValues(String... names);
|
|
||||||
|
|
||||||
public abstract AnyValue[] getAnyValues(String name);
|
|
||||||
|
|
||||||
public abstract AnyValue[] getAnyValues(String... names);
|
|
||||||
|
|
||||||
public abstract AnyValue getAnyValue(String name);
|
|
||||||
|
|
||||||
public abstract String getValue(String name);
|
|
||||||
|
|
||||||
public boolean getBoolValue(String name) {
|
|
||||||
return Boolean.parseBoolean(getValue(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getBoolValue(String name, boolean defaultValue) {
|
|
||||||
String value = getValue(name);
|
|
||||||
return value == null ? defaultValue : Boolean.parseBoolean(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte getByteValue(String name) {
|
|
||||||
return Byte.parseByte(getValue(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte getByteValue(String name, byte defaultValue) {
|
|
||||||
String value = getValue(name);
|
|
||||||
return value == null ? defaultValue : Byte.decode(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public char getCharValue(String name) {
|
|
||||||
return getValue(name).charAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public char getCharValue(String name, char defaultValue) {
|
|
||||||
String value = getValue(name);
|
|
||||||
return value == null || value.length() == 0 ? defaultValue : value.charAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getShortValue(String name) {
|
|
||||||
return Short.decode(getValue(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getShortValue(String name, short defaultValue) {
|
|
||||||
String value = getValue(name);
|
|
||||||
return value == null ? defaultValue : Short.decode(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIntValue(String name) {
|
|
||||||
return Integer.decode(getValue(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIntValue(String name, int defaultValue) {
|
|
||||||
String value = getValue(name);
|
|
||||||
return value == null ? defaultValue : Integer.decode(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLongValue(String name) {
|
|
||||||
return Long.decode(getValue(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLongValue(String name, long defaultValue) {
|
|
||||||
String value = getValue(name);
|
|
||||||
return value == null ? defaultValue : Long.decode(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getFloatValue(String name) {
|
|
||||||
return Float.parseFloat(getValue(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getFloatValue(String name, float defaultValue) {
|
|
||||||
String value = getValue(name);
|
|
||||||
return value == null ? defaultValue : Float.parseFloat(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getDoubleValue(String name) {
|
|
||||||
return Double.parseDouble(getValue(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getDoubleValue(String name, double defaultValue) {
|
|
||||||
String value = getValue(name);
|
|
||||||
return value == null ? defaultValue : Double.parseDouble(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue(String name, String defaultValue) {
|
|
||||||
String value = getValue(name);
|
|
||||||
return value == null ? defaultValue : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public class AsmMethodVisitor {
|
|
||||||
|
|
||||||
private final MethodVisitor visitor;
|
|
||||||
|
|
||||||
private boolean debug = false;
|
|
||||||
|
|
||||||
public AsmMethodVisitor setDebug(boolean d) {
|
|
||||||
debug = d;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Map<Label, Integer> labels = new LinkedHashMap();
|
|
||||||
|
|
||||||
private static final String[] opcodes = new String[200]; //0 -18
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
for (java.lang.reflect.Field field : Opcodes.class.getFields()) {
|
|
||||||
String name = field.getName();
|
|
||||||
if (name.startsWith("ASM")) continue;
|
|
||||||
if (name.startsWith("V1_")) continue;
|
|
||||||
if (name.startsWith("ACC_")) continue;
|
|
||||||
if (name.startsWith("T_")) continue;
|
|
||||||
if (name.startsWith("H_")) continue;
|
|
||||||
if (name.startsWith("F_")) continue;
|
|
||||||
if (field.getType() != int.class) continue;
|
|
||||||
opcodes[(int) (Integer) field.get(null)] = name;
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new RuntimeException(ex); //不可能会发生
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AsmMethodVisitor(MethodVisitor visitor) {
|
|
||||||
//super(Opcodes.ASM5, visitor);
|
|
||||||
this.visitor = visitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AnnotationVisitor visitParameterAnnotation(int i, String string, boolean bln) {
|
|
||||||
AnnotationVisitor av = visitor.visitParameterAnnotation(i, string, bln);
|
|
||||||
if (debug) System.out.println("mv.visitParameterAnnotation(" + i + ", \"" + string + "\", " + bln + ");");
|
|
||||||
return av;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AnnotationVisitor visitAnnotation(String desc, boolean flag) {
|
|
||||||
AnnotationVisitor av = visitor.visitAnnotation(desc, flag);
|
|
||||||
if (debug) System.out.println("mv.visitAnnotation(\"" + desc + "\", " + flag + ");");
|
|
||||||
return av;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitParameter(String name, int access) {
|
|
||||||
visitor.visitParameter(name, access);
|
|
||||||
if (debug) System.out.println("mv.visitParameter(" + name + ", " + access + ");");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitVarInsn(int opcode, int var) {
|
|
||||||
visitor.visitVarInsn(opcode, var);
|
|
||||||
if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitJumpInsn(int opcode, Label var) { //调用次方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
|
|
||||||
visitor.visitJumpInsn(opcode, var);
|
|
||||||
if (debug) {
|
|
||||||
Integer index = labels.get(var);
|
|
||||||
if (index == null) {
|
|
||||||
index = labels.size();
|
|
||||||
labels.put(var, index);
|
|
||||||
System.out.println("Label l" + index + " = new Label();");
|
|
||||||
}
|
|
||||||
System.out.println("mv.visitJumpInsn(" + opcodes[opcode] + ", l" + index + ");");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitCode() {
|
|
||||||
visitor.visitCode();
|
|
||||||
if (debug) System.out.println("mv.visitCode();");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitLabel(Label var) {
|
|
||||||
visitor.visitLabel(var);
|
|
||||||
if (debug) {
|
|
||||||
Integer index = labels.get(var);
|
|
||||||
if (index == null) {
|
|
||||||
index = labels.size();
|
|
||||||
labels.put(var, index);
|
|
||||||
System.out.println("Label l" + index + " = new Label();");
|
|
||||||
}
|
|
||||||
System.out.println("mv.visitLabel(l" + index + ");");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
|
|
||||||
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
|
|
||||||
if (debug) System.out.println("mv.visitMethodInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\", " + itf + ");");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
|
|
||||||
visitor.visitFieldInsn(opcode, owner, name, desc);
|
|
||||||
if (debug) System.out.println("mv.visitFieldInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\");");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitTypeInsn(int opcode, String type) {
|
|
||||||
visitor.visitTypeInsn(opcode, type);
|
|
||||||
if (debug) System.out.println("mv.visitTypeInsn(" + opcodes[opcode] + ", \"" + type + "\");");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitInsn(int opcode) {
|
|
||||||
visitor.visitInsn(opcode);
|
|
||||||
if (debug) System.out.println("mv.visitInsn(" + opcodes[opcode] + ");");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitIntInsn(int opcode, int value) {
|
|
||||||
visitor.visitIntInsn(opcode, value);
|
|
||||||
if (debug) System.out.println("mv.visitIntInsn(" + opcodes[opcode] + ", " + value + ");");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitIincInsn(int opcode, int value) {
|
|
||||||
visitor.visitIincInsn(opcode, value);
|
|
||||||
if (debug) System.out.println("mv.visitIincInsn(" + opcode + ", " + value + ");");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitLdcInsn(Object o) {
|
|
||||||
visitor.visitLdcInsn(o);
|
|
||||||
if (debug) System.out.println("mv.visitLdcInsn(" + o + ");");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitMaxs(int maxStack, int maxLocals) {
|
|
||||||
visitor.visitMaxs(maxStack, maxLocals);
|
|
||||||
if (debug) System.out.println("mv.visitMaxs(" + maxStack + ", " + maxLocals + ");");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitEnd() {
|
|
||||||
visitor.visitEnd();
|
|
||||||
if (debug) System.out.println("mv.visitEnd();\r\n\r\n\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,375 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 该类功能是动态映射一个Data类中成员对应的getter、setter方法; 代替低效的反射实现方式。
|
|
||||||
* 映射Field时,field必须满足以下条件之一:
|
|
||||||
* 1、field属性是public且非final
|
|
||||||
* 2、至少存在对应的getter、setter方法中的一个
|
|
||||||
* 当不存在getter方法时,get操作规定返回null
|
|
||||||
* 当不存在setter方法时,set操作为空方法
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
* @param <F>
|
|
||||||
*/
|
|
||||||
public interface Attribute<T, F> {
|
|
||||||
|
|
||||||
public Class<? extends F> type();
|
|
||||||
|
|
||||||
public Class<T> declaringClass();
|
|
||||||
|
|
||||||
public String field();
|
|
||||||
|
|
||||||
public F get(T obj);
|
|
||||||
|
|
||||||
public void set(T obj, F value);
|
|
||||||
|
|
||||||
public static abstract class Attributes {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据一个Field生成 Attribute 对象。
|
|
||||||
*
|
|
||||||
* @param <T>
|
|
||||||
* @param <F>
|
|
||||||
* @param field
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static <T, F> Attribute<T, F> create(final Field field) {
|
|
||||||
return create((Class<T>) field.getDeclaringClass(), field.getName(), field, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据一个Field和field的别名生成 Attribute 对象。
|
|
||||||
*
|
|
||||||
* @param <T>
|
|
||||||
* @param <F>
|
|
||||||
* @param fieldname 别名
|
|
||||||
* @param field
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static <T, F> Attribute<T, F> create(String fieldname, final Field field) {
|
|
||||||
return create((Class<T>) field.getDeclaringClass(), fieldname, field, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据一个Class和field名生成 Attribute 对象。
|
|
||||||
*
|
|
||||||
* @param <T>
|
|
||||||
* @param <F>
|
|
||||||
* @param clazz
|
|
||||||
* @param fieldname 字段名, 如果该字段不存在则抛异常
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static <T, F> Attribute<T, F> create(Class<T> clazz, final String fieldname) {
|
|
||||||
try {
|
|
||||||
return create(clazz, fieldname, clazz.getDeclaredField(fieldname), null, null);
|
|
||||||
} catch (NoSuchFieldException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
} catch (SecurityException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T, F> Attribute<T, F> create(Class<T> clazz, final java.lang.reflect.Field field) {
|
|
||||||
return create(clazz, field.getName(), field);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T, F> Attribute<T, F> create(Class<T> clazz, final String fieldname, final java.lang.reflect.Field field) {
|
|
||||||
return create(clazz, fieldname, field, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getter、setter不能全为null
|
|
||||||
*
|
|
||||||
* @param <T>
|
|
||||||
* @param <F>
|
|
||||||
* @param getter
|
|
||||||
* @param setter
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static <T, F> Attribute<T, F> create(final Method getter, final Method setter) {
|
|
||||||
return create((Class) (getter == null ? setter.getDeclaringClass() : getter.getDeclaringClass()), null, null, getter, setter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getter、setter不能全为null
|
|
||||||
*
|
|
||||||
* @param <T>
|
|
||||||
* @param <F>
|
|
||||||
* @param clazz
|
|
||||||
* @param getter
|
|
||||||
* @param setter
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static <T, F> Attribute<T, F> create(Class<T> clazz, final Method getter, final Method setter) {
|
|
||||||
return create(clazz, null, null, getter, setter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getter、setter不能全为null
|
|
||||||
*
|
|
||||||
* @param <T>
|
|
||||||
* @param <F>
|
|
||||||
* @param clazz
|
|
||||||
* @param fieldalias
|
|
||||||
* @param getter
|
|
||||||
* @param setter
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static <T, F> Attribute<T, F> create(Class<T> clazz, final String fieldalias, final Method getter, final Method setter) {
|
|
||||||
return create(clazz, fieldalias, null, getter, setter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* field、getter、setter不能全为null
|
|
||||||
*
|
|
||||||
* @param <T>
|
|
||||||
* @param <F>
|
|
||||||
* @param clazz
|
|
||||||
* @param fieldalias0
|
|
||||||
* @param field0
|
|
||||||
* @param getter0
|
|
||||||
* @param setter0
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T, F> Attribute<T, F> create(final Class<T> clazz, String fieldalias0, final Field field0, Method getter0, Method setter0) {
|
|
||||||
if (fieldalias0 != null && fieldalias0.isEmpty()) fieldalias0 = null;
|
|
||||||
int mod = field0 == null ? Modifier.STATIC : field0.getModifiers();
|
|
||||||
if (field0 != null && !Modifier.isStatic(mod) && !Modifier.isPublic(mod)) {
|
|
||||||
Class t = field0.getType();
|
|
||||||
char[] fs = field0.getName().toCharArray();
|
|
||||||
fs[0] = Character.toUpperCase(fs[0]);
|
|
||||||
String mn = new String(fs);
|
|
||||||
if (getter0 == null) {
|
|
||||||
String prefix = t == boolean.class || t == Boolean.class ? "is" : "get";
|
|
||||||
try {
|
|
||||||
getter0 = clazz.getMethod(prefix + mn);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (setter0 == null) {
|
|
||||||
try {
|
|
||||||
setter0 = clazz.getMethod("set" + mn, field0.getType());
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final Field field = field0 == null ? null : (!Modifier.isPublic(mod) || Modifier.isStatic(mod) ? null : field0);
|
|
||||||
final java.lang.reflect.Method getter = getter0;
|
|
||||||
final java.lang.reflect.Method setter = setter0;
|
|
||||||
if (fieldalias0 == null) {
|
|
||||||
if (field0 != null) {
|
|
||||||
fieldalias0 = field0.getName();
|
|
||||||
} else {
|
|
||||||
String s;
|
|
||||||
if (getter0 != null) {
|
|
||||||
s = getter0.getName().substring(getter0.getName().startsWith("is") ? 2 : 3);
|
|
||||||
} else {
|
|
||||||
s = setter0.getName().substring(3);
|
|
||||||
}
|
|
||||||
char[] d = s.toCharArray();
|
|
||||||
if (d.length < 2 || Character.isLowerCase(d[1])) {
|
|
||||||
d[0] = Character.toLowerCase(d[0]);
|
|
||||||
}
|
|
||||||
fieldalias0 = new String(d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (getter == null && setter == null && field == null) {
|
|
||||||
throw new RuntimeException("[" + clazz + "]have no public field or setter or getter");
|
|
||||||
}
|
|
||||||
final String fieldname = fieldalias0;
|
|
||||||
Class column;
|
|
||||||
if (field != null) { // public field
|
|
||||||
column = field.getType();
|
|
||||||
} else if (getter != null) {
|
|
||||||
column = getter.getReturnType();
|
|
||||||
} else { // setter != null
|
|
||||||
column = setter.getParameterTypes()[0];
|
|
||||||
}
|
|
||||||
final Class pcolumn = column;
|
|
||||||
if (column.isPrimitive()) column = Array.get(Array.newInstance(column, 1), 0).getClass();
|
|
||||||
final String supDynName = Attribute.class.getName().replace('.', '/');
|
|
||||||
final String interName = clazz.getName().replace('.', '/');
|
|
||||||
final String columnName = column.getName().replace('.', '/');
|
|
||||||
final String interDesc = Type.getDescriptor(clazz);
|
|
||||||
final String columnDesc = Type.getDescriptor(column);
|
|
||||||
|
|
||||||
ClassLoader loader = Attribute.class.getClassLoader();
|
|
||||||
String newDynName = supDynName + "_Dyn_" + clazz.getSimpleName() + "_"
|
|
||||||
+ fieldname.substring(fieldname.indexOf('.') + 1) + "_" + pcolumn.getSimpleName().replace("[]", "Array");
|
|
||||||
if (String.class.getClassLoader() != clazz.getClassLoader()) {
|
|
||||||
loader = clazz.getClassLoader();
|
|
||||||
newDynName = interName + "_Dyn" + Attribute.class.getSimpleName() + "_"
|
|
||||||
+ fieldname.substring(fieldname.indexOf('.') + 1) + "_" + pcolumn.getSimpleName().replace("[]", "Array");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return (Attribute) Class.forName(newDynName.replace('/', '.')).newInstance();
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
}
|
|
||||||
//---------------------------------------------------
|
|
||||||
final org.objectweb.asm.ClassWriter cw = new org.objectweb.asm.ClassWriter(0);
|
|
||||||
org.objectweb.asm.MethodVisitor mv;
|
|
||||||
|
|
||||||
cw.visit(V1_7, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + interDesc + columnDesc + ">;", "java/lang/Object", new String[]{supDynName});
|
|
||||||
|
|
||||||
{ //构造方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
mv.visitMaxs(1, 1);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
{ //field 方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "field", "()Ljava/lang/String;", null, null);
|
|
||||||
mv.visitLdcInsn(fieldname);
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs(1, 1);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{ //type 方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "type", "()Ljava/lang/Class;", null, null);
|
|
||||||
if (pcolumn == boolean.class) {
|
|
||||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
|
|
||||||
} else if (pcolumn == byte.class) {
|
|
||||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
|
|
||||||
} else if (pcolumn == char.class) {
|
|
||||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
|
|
||||||
} else if (pcolumn == short.class) {
|
|
||||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
|
|
||||||
} else if (pcolumn == int.class) {
|
|
||||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
|
|
||||||
} else if (pcolumn == float.class) {
|
|
||||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
|
|
||||||
} else if (pcolumn == long.class) {
|
|
||||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
|
|
||||||
} else if (pcolumn == double.class) {
|
|
||||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
|
|
||||||
} else {
|
|
||||||
mv.visitLdcInsn(Type.getType(pcolumn));
|
|
||||||
}
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs(1, 1);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{ //declaringClass 方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "declaringClass", "()Ljava/lang/Class;", null, null);
|
|
||||||
mv.visitLdcInsn(Type.getType(clazz));
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs(1, 1);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{ //get 方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "get", "(" + interDesc + ")" + columnDesc, null, null);
|
|
||||||
int m = 1;
|
|
||||||
if (getter == null) {
|
|
||||||
if (field == null) {
|
|
||||||
mv.visitInsn(ACONST_NULL);
|
|
||||||
} else { //public field
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitFieldInsn(GETFIELD, interName, field.getName(), Type.getDescriptor(pcolumn));
|
|
||||||
if (pcolumn != column) {
|
|
||||||
mv.visitMethodInsn(INVOKESTATIC, columnName, "valueOf", "(" + Type.getDescriptor(pcolumn) + ")" + columnDesc, false);
|
|
||||||
m = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, interName, getter.getName(), Type.getMethodDescriptor(getter), false);
|
|
||||||
if (pcolumn != column) {
|
|
||||||
mv.visitMethodInsn(INVOKESTATIC, columnName, "valueOf", "(" + Type.getDescriptor(pcolumn) + ")" + columnDesc, false);
|
|
||||||
m = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs(m, 2);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{ //set 方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "set", "(" + interDesc + columnDesc + ")V", null, null);
|
|
||||||
int m = 2;
|
|
||||||
if (setter == null) {
|
|
||||||
if (field == null || Modifier.isFinal(field.getModifiers())) {
|
|
||||||
m = 0;
|
|
||||||
} else { //public field
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitVarInsn(ALOAD, 2);
|
|
||||||
if (pcolumn != column) {
|
|
||||||
try {
|
|
||||||
java.lang.reflect.Method pm = column.getMethod(pcolumn.getSimpleName() + "Value");
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, columnName, pm.getName(), Type.getMethodDescriptor(pm), false);
|
|
||||||
m = 3;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new RuntimeException(ex); //不可能会发生
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mv.visitFieldInsn(PUTFIELD, interName, field.getName(), Type.getDescriptor(pcolumn));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitVarInsn(ALOAD, 2);
|
|
||||||
if (pcolumn != column) {
|
|
||||||
try {
|
|
||||||
java.lang.reflect.Method pm = column.getMethod(pcolumn.getSimpleName() + "Value");
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, columnName, pm.getName(), Type.getMethodDescriptor(pm), false);
|
|
||||||
m = 3;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new RuntimeException(ex); //不可能会发生
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, interName, setter.getName(), Type.getMethodDescriptor(setter), false);
|
|
||||||
}
|
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
mv.visitMaxs(m, 3);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{ //虚拟get
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitTypeInsn(CHECKCAST, interName);
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "get", "(" + interDesc + ")" + columnDesc, false);
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs(2, 2);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{//虚拟set
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitTypeInsn(CHECKCAST, interName);
|
|
||||||
mv.visitVarInsn(ALOAD, 2);
|
|
||||||
mv.visitTypeInsn(CHECKCAST, columnName);
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "set", "(" + interDesc + columnDesc + ")V", false);
|
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
mv.visitMaxs(3, 3);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
cw.visitEnd();
|
|
||||||
|
|
||||||
byte[] bytes = cw.toByteArray();
|
|
||||||
Class<Attribute> creatorClazz = (Class<Attribute>) new ClassLoader(loader) {
|
|
||||||
public final Class<?> loadClass(String name, byte[] b) {
|
|
||||||
return defineClass(name, b, 0, b.length);
|
|
||||||
}
|
|
||||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
|
||||||
try {
|
|
||||||
return creatorClazz.newInstance();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自动加载。 使用场景:
|
|
||||||
* 1、被标记为@AutoLoad(false)的Service类不会被自动加载
|
|
||||||
* 2、被标记为@AutoLoad(false)的Servlet类不会被自动加载
|
|
||||||
* 3、被标记为@AutoLoad且同时被标记为@javax.persistence.Cacheable的Entity类在被DataSource初始化时需要将Entity类对应的表数据全量加载进缓存中。
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Documented
|
|
||||||
@Target({TYPE})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
public @interface AutoLoad {
|
|
||||||
|
|
||||||
boolean value() default true;
|
|
||||||
}
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.nio.*;
|
|
||||||
import java.nio.charset.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 简单的byte[]操作类。
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class ByteArray {
|
|
||||||
|
|
||||||
private byte[] content;
|
|
||||||
|
|
||||||
private int count;
|
|
||||||
|
|
||||||
public ByteArray() {
|
|
||||||
this(1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteArray(int size) {
|
|
||||||
content = new byte[Math.max(128, size)];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
this.count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int find(byte value) {
|
|
||||||
return find(0, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equal(final byte[] bytes) {
|
|
||||||
if (bytes == null || count != bytes.length) return false;
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
if (content[i] != bytes[i]) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return count == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int count() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(byte[] buf) {
|
|
||||||
System.arraycopy(this.content, 0, buf, 0, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] directBytes() {
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int find(int offset, char value) {
|
|
||||||
return find(offset, (byte) value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int find(int offset, byte value) {
|
|
||||||
return find(offset, -1, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int find(int offset, int limit, char value) {
|
|
||||||
return find(offset, limit, (byte) value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int find(int offset, int limit, byte value) {
|
|
||||||
byte[] bytes = this.content;
|
|
||||||
int end = limit > 0 ? limit : count;
|
|
||||||
for (int i = offset; i < end; i++) {
|
|
||||||
if (bytes[i] == value) return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeLastByte() {
|
|
||||||
if (count > 0) count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addInt(int value) {
|
|
||||||
add((byte) (value >> 24 & 0xFF), (byte) (value >> 16 & 0xFF), (byte) (value >> 8 & 0xFF), (byte) (value & 0xFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(byte value) {
|
|
||||||
if (count >= content.length - 1) {
|
|
||||||
byte[] ns = new byte[content.length + 8];
|
|
||||||
System.arraycopy(content, 0, ns, 0, count);
|
|
||||||
this.content = ns;
|
|
||||||
}
|
|
||||||
content[count++] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(byte... values) {
|
|
||||||
if (count >= content.length - values.length) {
|
|
||||||
byte[] ns = new byte[content.length + values.length];
|
|
||||||
System.arraycopy(content, 0, ns, 0, count);
|
|
||||||
this.content = ns;
|
|
||||||
}
|
|
||||||
System.arraycopy(content, count, values, 0, values.length);
|
|
||||||
count += values.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(ByteBuffer buffer, int len) {
|
|
||||||
if (len < 1) return;
|
|
||||||
if (count >= content.length - len) {
|
|
||||||
byte[] ns = new byte[content.length + len];
|
|
||||||
System.arraycopy(content, 0, ns, 0, count);
|
|
||||||
this.content = ns;
|
|
||||||
}
|
|
||||||
buffer.get(content, count, len);
|
|
||||||
count += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return new String(content, 0, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString(final Charset charset) {
|
|
||||||
return toString(0, count, charset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString(final int offset, int len, final Charset charset) {
|
|
||||||
if (charset == null) return new String(Utility.decodeUTF8(content, offset, len));
|
|
||||||
return new String(content, offset, len, charset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toDecodeString(final int offset, int len, final Charset charset) {
|
|
||||||
int index = offset;
|
|
||||||
for (int i = offset; i < (offset + len); i++) {
|
|
||||||
switch (content[i]) {
|
|
||||||
case '+':
|
|
||||||
content[index] = ' ';
|
|
||||||
break;
|
|
||||||
case '%':
|
|
||||||
content[index] = (byte) ((hexBit(content[++i]) * 16 + hexBit(content[++i])));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
content[index] = content[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
for (int i = index + 1; i < (offset + len); i++) {
|
|
||||||
content[i] = ' ';
|
|
||||||
}
|
|
||||||
len = index - offset;
|
|
||||||
if (charset == null) return new String(Utility.decodeUTF8(content, offset, len));
|
|
||||||
return new String(content, offset, len, charset);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int hexBit(byte b) {
|
|
||||||
if ('0' <= b && '9' >= b) return b - '0';
|
|
||||||
if ('a' <= b && 'z' >= b) return b - 'a' + 10;
|
|
||||||
if ('A' <= b && 'Z' >= b) return b - 'A' + 10;
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,296 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this template, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.beans.*;
|
|
||||||
import java.io.*;
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实现一个类的构造方法。 代替低效的反射实现方式。 不支持数组类。
|
|
||||||
* 常见的无参数的构造函数类都可以自动生成Creator, 对应自定义的类可以提供一个静态构建Creator方法。
|
|
||||||
*
|
|
||||||
* 例如:
|
|
||||||
* public class Record {
|
|
||||||
*
|
|
||||||
* private final int id;
|
|
||||||
*
|
|
||||||
* private String name;
|
|
||||||
*
|
|
||||||
* Record(int id, String name) {
|
|
||||||
* this.id = id;
|
|
||||||
* this.name = name;
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* private static Creator createCreator() {
|
|
||||||
* return new Creator<Record>() {
|
|
||||||
* @Override
|
|
||||||
* @ConstructorParameters({"id", "name"})
|
|
||||||
* public Record create(Object... params) {
|
|
||||||
* return new Record((Integer) params[0], (String) params[1]);
|
|
||||||
* }
|
|
||||||
* };
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* 或者:
|
|
||||||
* public class Record {
|
|
||||||
*
|
|
||||||
* private final int id;
|
|
||||||
*
|
|
||||||
* private String name;
|
|
||||||
*
|
|
||||||
* @ConstructorProperties({"id", "name"})
|
|
||||||
* public Record(int id, String name) {
|
|
||||||
* this.id = id;
|
|
||||||
* this.name = name;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public interface Creator<T> {
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Target({METHOD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
public static @interface ConstructorParameters {
|
|
||||||
|
|
||||||
String[] value();
|
|
||||||
}
|
|
||||||
|
|
||||||
public T create(Object... params);
|
|
||||||
|
|
||||||
public abstract class Creators {
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T> Creator<T> create(Class<T> clazz) {
|
|
||||||
if (clazz.isAssignableFrom(ArrayList.class)) {
|
|
||||||
clazz = (Class<T>) ArrayList.class;
|
|
||||||
} else if (clazz.isAssignableFrom(HashMap.class)) {
|
|
||||||
clazz = (Class<T>) HashMap.class;
|
|
||||||
} else if (clazz.isAssignableFrom(HashSet.class)) {
|
|
||||||
clazz = (Class<T>) HashSet.class;
|
|
||||||
}
|
|
||||||
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) {
|
|
||||||
throw new RuntimeException("[" + clazz + "] is a interface or abstract class, cannot create it's Creator.");
|
|
||||||
}
|
|
||||||
for (final Method method : clazz.getDeclaredMethods()) {
|
|
||||||
if (!Modifier.isStatic(method.getModifiers())) continue;
|
|
||||||
if (method.getParameterTypes().length != 0) continue;
|
|
||||||
if (method.getReturnType() != Creator.class) continue;
|
|
||||||
try {
|
|
||||||
method.setAccessible(true);
|
|
||||||
return (Creator<T>) method.invoke(null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final String supDynName = Creator.class.getName().replace('.', '/');
|
|
||||||
final String interName = clazz.getName().replace('.', '/');
|
|
||||||
final String interDesc = Type.getDescriptor(clazz);
|
|
||||||
ClassLoader loader = Creator.class.getClassLoader();
|
|
||||||
String newDynName = supDynName + "_" + clazz.getSimpleName() + "_" + (System.currentTimeMillis() % 10000);
|
|
||||||
if (String.class.getClassLoader() != clazz.getClassLoader()) {
|
|
||||||
loader = clazz.getClassLoader();
|
|
||||||
newDynName = interName + "_Dyn" + Creator.class.getSimpleName();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return (Creator) Class.forName(newDynName.replace('/', '.')).newInstance();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
Constructor<T> constructor0 = null;
|
|
||||||
for (Constructor c : clazz.getConstructors()) {
|
|
||||||
if (c.getParameterTypes().length == 0) { //为了兼容android 而不使用 getParameterCount()
|
|
||||||
constructor0 = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (constructor0 == null) {
|
|
||||||
for (Constructor c : clazz.getDeclaredConstructors()) {
|
|
||||||
if (Modifier.isPrivate(c.getModifiers())) continue;
|
|
||||||
if (c.getAnnotation(ConstructorProperties.class) != null) {
|
|
||||||
constructor0 = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final Constructor<T> constructor = constructor0;
|
|
||||||
if (constructor == null) throw new RuntimeException("[" + clazz + "] have no public or java.beans.ConstructorProperties-Annotation constructor.");
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
|
||||||
FieldVisitor fv;
|
|
||||||
MethodVisitor mv;
|
|
||||||
AnnotationVisitor av0;
|
|
||||||
cw.visit(V1_7, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + interDesc + ">;", "java/lang/Object", new String[]{supDynName});
|
|
||||||
|
|
||||||
{//构造方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
mv.visitMaxs(1, 1);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{//create 方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)L" + interName + ";", null, null);
|
|
||||||
ConstructorProperties cps = constructor.getAnnotation(ConstructorProperties.class);
|
|
||||||
final String[] cparams = cps == null ? null : cps.value();
|
|
||||||
if (cparams != null) {
|
|
||||||
av0 = mv.visitAnnotation(Type.getDescriptor(ConstructorParameters.class), true);
|
|
||||||
AnnotationVisitor av1 = av0.visitArray("value");
|
|
||||||
for (String n : cps.value()) {
|
|
||||||
av1.visit(null, n);
|
|
||||||
}
|
|
||||||
av1.visitEnd();
|
|
||||||
av0.visitEnd();
|
|
||||||
}
|
|
||||||
final Class[] paramTypes = constructor.getParameterTypes();
|
|
||||||
final int[] iconsts = {ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5};
|
|
||||||
{ //有Primitive数据类型且值为null的参数需要赋默认值
|
|
||||||
for (int i = 0; i < paramTypes.length; i++) {
|
|
||||||
final Class pt = paramTypes[i];
|
|
||||||
if (!pt.isPrimitive()) continue;
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
if (i < 6) {
|
|
||||||
mv.visitInsn(iconsts[i]);
|
|
||||||
} else {
|
|
||||||
mv.visitIntInsn(BIPUSH, i);
|
|
||||||
}
|
|
||||||
mv.visitInsn(AALOAD);
|
|
||||||
Label lab = new Label();
|
|
||||||
mv.visitJumpInsn(IFNONNULL, lab);
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
if (i < 6) {
|
|
||||||
mv.visitInsn(iconsts[i]);
|
|
||||||
} else {
|
|
||||||
mv.visitIntInsn(BIPUSH, i);
|
|
||||||
}
|
|
||||||
if (pt == int.class) {
|
|
||||||
mv.visitInsn(ICONST_0);
|
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
|
|
||||||
} else if (pt == long.class) {
|
|
||||||
mv.visitInsn(LCONST_0);
|
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
|
|
||||||
} else if (pt == boolean.class) {
|
|
||||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;");
|
|
||||||
} else if (pt == short.class) {
|
|
||||||
mv.visitInsn(ICONST_0);
|
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
|
|
||||||
} else if (pt == float.class) {
|
|
||||||
mv.visitInsn(FCONST_0);
|
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
|
|
||||||
} else if (pt == byte.class) {
|
|
||||||
mv.visitInsn(ICONST_0);
|
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
|
|
||||||
} else if (pt == double.class) {
|
|
||||||
mv.visitInsn(DCONST_0);
|
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
|
|
||||||
} else if (pt == char.class) {
|
|
||||||
mv.visitInsn(ICONST_0);
|
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
|
|
||||||
}
|
|
||||||
mv.visitInsn(AASTORE);
|
|
||||||
mv.visitLabel(lab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mv.visitTypeInsn(NEW, interName);
|
|
||||||
mv.visitInsn(DUP);
|
|
||||||
//---------------------------------------
|
|
||||||
{
|
|
||||||
for (int i = 0; i < paramTypes.length; i++) {
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
if (i < 6) {
|
|
||||||
mv.visitInsn(iconsts[i]);
|
|
||||||
} else {
|
|
||||||
mv.visitIntInsn(BIPUSH, i);
|
|
||||||
}
|
|
||||||
mv.visitInsn(AALOAD);
|
|
||||||
final Class ct = paramTypes[i];
|
|
||||||
if (ct.isPrimitive()) {
|
|
||||||
final Class bigct = Array.get(Array.newInstance(ct, 1), 0).getClass();
|
|
||||||
mv.visitTypeInsn(CHECKCAST, bigct.getName().replace('.', '/'));
|
|
||||||
try {
|
|
||||||
Method pm = bigct.getMethod(ct.getSimpleName() + "Value");
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, bigct.getName().replace('.', '/'), pm.getName(), Type.getMethodDescriptor(pm), false);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new RuntimeException(ex); //不可能会发生
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mv.visitTypeInsn(CHECKCAST, ct.getName().replace('.', '/'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//---------------------------------------
|
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, interName, "<init>", Type.getConstructorDescriptor(constructor), false);
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs((paramTypes.length > 0 ? (paramTypes.length + 3) : 2), 2);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{ //虚拟 create 方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_VARARGS + ACC_SYNTHETIC, "create", "([Ljava/lang/Object;)Ljava/lang/Object;", null, null);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "create", "([Ljava/lang/Object;)" + interDesc, false);
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs(2, 2);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
cw.visitEnd();
|
|
||||||
final byte[] bytes = cw.toByteArray();
|
|
||||||
Class<?> resultClazz = null;
|
|
||||||
if (loader instanceof URLClassLoader) {
|
|
||||||
try {
|
|
||||||
final URLClassLoader urlLoader = (URLClassLoader) loader;
|
|
||||||
final URL url = new URL("memclass", "localhost", -1, "/" + newDynName.replace('/', '.') + "/", new URLStreamHandler() {
|
|
||||||
@Override
|
|
||||||
protected URLConnection openConnection(URL u) throws IOException {
|
|
||||||
return new URLConnection(u) {
|
|
||||||
@Override
|
|
||||||
public void connect() throws IOException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream getInputStream() throws IOException {
|
|
||||||
return new ByteArrayInputStream(bytes);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Method addURLMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
|
||||||
addURLMethod.setAccessible(true);
|
|
||||||
addURLMethod.invoke(urlLoader, url);
|
|
||||||
resultClazz = urlLoader.loadClass(newDynName.replace('/', '.'));
|
|
||||||
} catch (Throwable t) { //异常无需理会, 使用下一种loader方式
|
|
||||||
t.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (resultClazz == null) {
|
|
||||||
if (!Modifier.isPublic(constructor.getModifiers())) throw new RuntimeException("[" + clazz + "] have no public or java.beans.ConstructorProperties-Annotation constructor.");
|
|
||||||
resultClazz = new ClassLoader(loader) {
|
|
||||||
public final Class<?> loadClass(String name, byte[] b) {
|
|
||||||
return defineClass(name, b, 0, b.length);
|
|
||||||
}
|
|
||||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
|
||||||
}
|
|
||||||
return (Creator) resultClazz.newInstance();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.nio.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 16bytes数据结构
|
|
||||||
* 注意: 为了提高性能, DLong中的bytes是直接返回, 不得对bytes的内容进行修改。
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class DLong extends Number implements Comparable<DLong> {
|
|
||||||
|
|
||||||
public static final DLong ZERO = new DLong(new byte[16]);
|
|
||||||
|
|
||||||
protected final byte[] bytes;
|
|
||||||
|
|
||||||
protected DLong(long v1, long v2) { //暂时不用
|
|
||||||
this.bytes = new byte[]{(byte) (v1 >> 56), (byte) (v1 >> 48), (byte) (v1 >> 40), (byte) (v1 >> 32),
|
|
||||||
(byte) (v1 >> 24), (byte) (v1 >> 16), (byte) (v1 >> 8), (byte) v1, (byte) (v2 >> 56), (byte) (v2 >> 48), (byte) (v2 >> 40), (byte) (v2 >> 32),
|
|
||||||
(byte) (v2 >> 24), (byte) (v2 >> 16), (byte) (v2 >> 8), (byte) v2};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected DLong(byte[] bytes) {
|
|
||||||
if (bytes == null || bytes.length != 16) throw new NumberFormatException("Not 16 length bytes");
|
|
||||||
this.bytes = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBytes() {
|
|
||||||
return Arrays.copyOf(bytes, bytes.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] directBytes() {
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DLong create(byte[] bytes) {
|
|
||||||
if (ZERO.equals(bytes)) return ZERO;
|
|
||||||
return new DLong(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DLong read(ByteBuffer buffer) {
|
|
||||||
byte[] bs = new byte[16];
|
|
||||||
buffer.get(bs);
|
|
||||||
if (ZERO.equals(bs)) return ZERO;
|
|
||||||
return new DLong(bs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ByteBuffer write(ByteBuffer buffer, DLong value) {
|
|
||||||
buffer.put(value.bytes);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(byte[] bytes) {
|
|
||||||
return Arrays.equals(this.bytes, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj == null) return false;
|
|
||||||
if (getClass() != obj.getClass()) return false;
|
|
||||||
final DLong other = (DLong) obj;
|
|
||||||
return Arrays.equals(this.bytes, other.bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Arrays.hashCode(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
if (this == ZERO) return "0";
|
|
||||||
return new String(Utility.binToHex(bytes));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int intValue() {
|
|
||||||
return ((bytes[12] & 0xff) << 24) | ((bytes[113] & 0xff) << 16) | ((bytes[14] & 0xff) << 8) | (bytes[15] & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long longValue() {
|
|
||||||
return ((((long) bytes[8] & 0xff) << 56)
|
|
||||||
| (((long) bytes[9] & 0xff) << 48)
|
|
||||||
| (((long) bytes[10] & 0xff) << 40)
|
|
||||||
| (((long) bytes[11] & 0xff) << 32)
|
|
||||||
| (((long) bytes[12] & 0xff) << 24)
|
|
||||||
| (((long) bytes[13] & 0xff) << 16)
|
|
||||||
| (((long) bytes[14] & 0xff) << 8)
|
|
||||||
| (((long) bytes[15] & 0xff)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float floatValue() {
|
|
||||||
return (float) longValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double doubleValue() {
|
|
||||||
return (double) longValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(DLong o) {
|
|
||||||
if (o == null) return 1;
|
|
||||||
for (int i = 0; i < bytes.length; i++) {
|
|
||||||
if (this.bytes[i] != o.bytes[i]) return this.bytes[i] - o.bytes[i];
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用于忽略字段、方法或类。使用场景:
|
|
||||||
* 1、convert功能中被标记为@Ignore的字段或方法会被忽略
|
|
||||||
* 2、FilterBean中的被标记为@Ignore的字段会被忽略
|
|
||||||
* 3、被标记为@Ignore的Service类不会被自动加载
|
|
||||||
* 4、被标记为@Ignore的Servlet类不会被自动加载
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Documented
|
|
||||||
@Target({TYPE, FIELD, METHOD})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
public @interface Ignore {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 被标记的日志级别以上的才会被记录
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@Inherited
|
|
||||||
@Documented
|
|
||||||
@Target({TYPE})
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
public @interface LogLevel {
|
|
||||||
|
|
||||||
String value();
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public interface Nameable {
|
|
||||||
|
|
||||||
String name();
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this template, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import java.util.concurrent.atomic.*;
|
|
||||||
import java.util.function.*;
|
|
||||||
import java.util.logging.*;
|
|
||||||
import org.redkale.util.Creator.Creators;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public final class ObjectPool<T> implements Supplier<T> {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ObjectPool.class.getSimpleName());
|
|
||||||
|
|
||||||
private final boolean debug;
|
|
||||||
|
|
||||||
private final Queue<T> queue;
|
|
||||||
|
|
||||||
private Creator<T> creator;
|
|
||||||
|
|
||||||
private final Consumer<T> prepare;
|
|
||||||
|
|
||||||
private final Predicate<T> recycler;
|
|
||||||
|
|
||||||
private final AtomicLong creatCounter;
|
|
||||||
|
|
||||||
private final AtomicLong cycleCounter;
|
|
||||||
|
|
||||||
public ObjectPool(Class<T> clazz, Consumer<T> prepare, Predicate<T> recycler) {
|
|
||||||
this(2, clazz, prepare, recycler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObjectPool(int max, Class<T> clazz, Consumer<T> prepare, Predicate<T> recycler) {
|
|
||||||
this(max, Creators.create(clazz), prepare, recycler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObjectPool(Creator<T> creator, Consumer<T> prepare, Predicate<T> recycler) {
|
|
||||||
this(2, creator, prepare, recycler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObjectPool(int max, Creator<T> creator, Consumer<T> prepare, Predicate<T> recycler) {
|
|
||||||
this(null, null, max, creator, prepare, recycler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObjectPool(AtomicLong creatCounter, AtomicLong cycleCounter, int max, Creator<T> creator, Consumer<T> prepare, Predicate<T> recycler) {
|
|
||||||
this.creatCounter = creatCounter;
|
|
||||||
this.cycleCounter = cycleCounter;
|
|
||||||
this.creator = creator;
|
|
||||||
this.prepare = prepare;
|
|
||||||
this.recycler = recycler;
|
|
||||||
this.queue = new LinkedBlockingQueue(Math.max(Runtime.getRuntime().availableProcessors() * 2, max));
|
|
||||||
this.debug = logger.isLoggable(Level.FINER);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCreator(Creator<T> creator) {
|
|
||||||
this.creator = creator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T get() {
|
|
||||||
T result = queue.poll();
|
|
||||||
if (result == null) {
|
|
||||||
if (creatCounter != null) creatCounter.incrementAndGet();
|
|
||||||
result = this.creator.create();
|
|
||||||
}
|
|
||||||
if (prepare != null) prepare.accept(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offer(final T e) {
|
|
||||||
if (e != null && recycler.test(e)) {
|
|
||||||
if (cycleCounter != null) cycleCounter.incrementAndGet();
|
|
||||||
if (debug) {
|
|
||||||
for (T t : queue) {
|
|
||||||
if (t == e) {
|
|
||||||
logger.log(Level.WARNING, "[" + Thread.currentThread().getName() + "] repeat offer the same object(" + e + ")", new Exception());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
queue.offer(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCreatCount() {
|
|
||||||
return creatCounter.longValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCycleCount() {
|
|
||||||
return cycleCounter.longValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
|
|
||||||
public interface Reproduce<D, S> {
|
|
||||||
|
|
||||||
public D copy(D dest, S src);
|
|
||||||
|
|
||||||
public static abstract class Reproduces {
|
|
||||||
|
|
||||||
public static <D, S> Reproduce<D, S> create(final Class<D> destClass, final Class<S> srcClass) {
|
|
||||||
return create(destClass, srcClass, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <D, S> Reproduce<D, S> create(final Class<D> destClass, final Class<S> srcClass, final Predicate<String> columnPredicate) {
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
final String supDynName = Reproduce.class.getName().replace('.', '/');
|
|
||||||
final String destName = destClass.getName().replace('.', '/');
|
|
||||||
final String srcName = srcClass.getName().replace('.', '/');
|
|
||||||
final String destDesc = Type.getDescriptor(destClass);
|
|
||||||
final String srcDesc = Type.getDescriptor(srcClass);
|
|
||||||
String newDynName = supDynName + "Dyn_" + destClass.getSimpleName() + "_" + srcClass.getSimpleName();
|
|
||||||
ClassLoader loader = Reproduce.class.getClassLoader();
|
|
||||||
if (String.class.getClassLoader() != destClass.getClassLoader()) {
|
|
||||||
loader = destClass.getClassLoader();
|
|
||||||
newDynName = destName + "_Dyn" + Reproduce.class.getSimpleName() + "_" + srcClass.getSimpleName();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return (Reproduce) Class.forName(newDynName.replace('/', '.')).newInstance();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
ClassWriter cw = new ClassWriter(0);
|
|
||||||
FieldVisitor fv;
|
|
||||||
MethodVisitor mv;
|
|
||||||
AnnotationVisitor av0;
|
|
||||||
|
|
||||||
cw.visit(V1_7, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + destDesc + srcDesc + ">;", "java/lang/Object", new String[]{supDynName});
|
|
||||||
|
|
||||||
{ // 构造函数
|
|
||||||
mv = (cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
|
|
||||||
//mv.setDebug(true);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
mv.visitMaxs(1, 1);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
mv = (cw.visitMethod(ACC_PUBLIC, "copy", "(" + destDesc + srcDesc + ")" + destDesc, null, null));
|
|
||||||
//mv.setDebug(true);
|
|
||||||
|
|
||||||
for (java.lang.reflect.Field field : srcClass.getFields()) {
|
|
||||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
|
||||||
if (Modifier.isFinal(field.getModifiers())) continue;
|
|
||||||
if (!Modifier.isPublic(field.getModifiers())) continue;
|
|
||||||
final String fname = field.getName();
|
|
||||||
try {
|
|
||||||
if (!field.getType().equals(destClass.getField(fname).getType())) continue;
|
|
||||||
if (!columnPredicate.test(fname)) continue;
|
|
||||||
} catch (Exception e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitVarInsn(ALOAD, 2);
|
|
||||||
String td = Type.getDescriptor(field.getType());
|
|
||||||
mv.visitFieldInsn(GETFIELD, srcName, fname, td);
|
|
||||||
mv.visitFieldInsn(PUTFIELD, destName, fname, td);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (java.lang.reflect.Method getter : srcClass.getMethods()) {
|
|
||||||
if (Modifier.isStatic(getter.getModifiers())) continue;
|
|
||||||
if (getter.getParameterTypes().length > 0) continue;
|
|
||||||
if ("getClass".equals(getter.getName())) continue;
|
|
||||||
if (!getter.getName().startsWith("get") && !getter.getName().startsWith("is")) continue;
|
|
||||||
java.lang.reflect.Method setter;
|
|
||||||
boolean is = getter.getName().startsWith("is");
|
|
||||||
try {
|
|
||||||
setter = destClass.getMethod(getter.getName().replaceFirst(is ? "is" : "get", "set"), getter.getReturnType());
|
|
||||||
if (columnPredicate != null) {
|
|
||||||
String col = setter.getName().substring(3);
|
|
||||||
if (col.length() < 2 || Character.isLowerCase(col.charAt(1))) {
|
|
||||||
char[] cs = col.toCharArray();
|
|
||||||
cs[0] = Character.toLowerCase(cs[0]);
|
|
||||||
col = new String(cs);
|
|
||||||
}
|
|
||||||
if (!columnPredicate.test(col)) continue;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitVarInsn(ALOAD, 2);
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, srcName, getter.getName(), Type.getMethodDescriptor(getter), false);
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, destName, setter.getName(), Type.getMethodDescriptor(setter), false);
|
|
||||||
}
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs(3, 3);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
mv = (cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "copy", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null));
|
|
||||||
//mv.setDebug(true);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
|
||||||
mv.visitTypeInsn(CHECKCAST, destName);
|
|
||||||
mv.visitVarInsn(ALOAD, 2);
|
|
||||||
mv.visitTypeInsn(CHECKCAST, srcName);
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "copy", "(" + destDesc + srcDesc + ")" + destDesc, false);
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs(3, 3);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
cw.visitEnd();
|
|
||||||
// ------------------------------------------------------------------------------
|
|
||||||
byte[] bytes = cw.toByteArray();
|
|
||||||
Class<?> creatorClazz = new ClassLoader(loader) {
|
|
||||||
public final Class<?> loadClass(String name, byte[] b) {
|
|
||||||
return defineClass(name, b, 0, b.length);
|
|
||||||
}
|
|
||||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
|
||||||
try {
|
|
||||||
return (Reproduce) creatorClazz.newInstance();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import java.util.logging.*;
|
|
||||||
import java.util.regex.*;
|
|
||||||
import javax.annotation.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 如果Resource(name = "$") 表示资源name采用所属对象的name
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public final class ResourceFactory {
|
|
||||||
|
|
||||||
public static final String RESOURCE_PARENT_NAME = "$";
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ResourceFactory.class.getSimpleName());
|
|
||||||
|
|
||||||
private final ResourceFactory parent;
|
|
||||||
|
|
||||||
private static final ResourceFactory instance = new ResourceFactory(null);
|
|
||||||
|
|
||||||
private final ConcurrentHashMap<Type, Intercepter> interceptmap = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
private final ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, ?>> store = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
private final ConcurrentHashMap<Type, ConcurrentHashMap<String, ?>> gencstore = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
private ResourceFactory(ResourceFactory parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResourceFactory root() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceFactory createChild() {
|
|
||||||
return new ResourceFactory(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void release() {
|
|
||||||
this.store.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(final Class clazz, final Object rs) {
|
|
||||||
register("", clazz, rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(final Object rs) {
|
|
||||||
if (rs != null) register("", rs.getClass(), rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(final Type clazz, final Intercepter rs) {
|
|
||||||
if (clazz == null || rs == null) return;
|
|
||||||
interceptmap.put(clazz, rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(final String name, final Object rs) {
|
|
||||||
register(name, rs.getClass(), rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <A> void register(final String name, final Class<? extends A> clazz, final A rs) {
|
|
||||||
ConcurrentHashMap map = this.store.get(clazz);
|
|
||||||
if (map == null) {
|
|
||||||
ConcurrentHashMap<String, A> sub = new ConcurrentHashMap();
|
|
||||||
sub.put(name, rs);
|
|
||||||
store.put(clazz, sub);
|
|
||||||
} else {
|
|
||||||
map.put(name, rs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <A> void register(final String name, final Type clazz, final A rs) {
|
|
||||||
if (clazz instanceof Class) {
|
|
||||||
register(name, (Class) clazz, rs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ConcurrentHashMap map = this.gencstore.get(clazz);
|
|
||||||
if (map == null) {
|
|
||||||
ConcurrentHashMap<String, A> sub = new ConcurrentHashMap();
|
|
||||||
sub.put(name, rs);
|
|
||||||
gencstore.put(clazz, sub);
|
|
||||||
} else {
|
|
||||||
map.put(name, rs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <A> A find(Class<? extends A> clazz) {
|
|
||||||
return find("", clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <A> A find(String name, Type clazz) {
|
|
||||||
Map<String, ?> map = this.gencstore.get(clazz);
|
|
||||||
if (map != null) {
|
|
||||||
A rs = (A) map.get(name);
|
|
||||||
if (rs != null) return rs;
|
|
||||||
}
|
|
||||||
if (parent != null) return parent.find(name, clazz);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <A> A find(String name, Class<? extends A> clazz) {
|
|
||||||
Map<String, ?> map = this.store.get(clazz);
|
|
||||||
if (map != null) {
|
|
||||||
A rs = (A) map.get(name);
|
|
||||||
if (rs != null) return rs;
|
|
||||||
}
|
|
||||||
if (parent != null) return parent.find(name, clazz);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <A> A findChild(final String name, final Class<? extends A> clazz) {
|
|
||||||
A rs = find(name, clazz);
|
|
||||||
if (rs != null) return rs;
|
|
||||||
for (Map.Entry<Class<?>, ConcurrentHashMap<String, ?>> en : this.store.entrySet()) { //不用forEach为兼容JDK 6
|
|
||||||
if (!clazz.isAssignableFrom(en.getKey())) continue;
|
|
||||||
Object v = en.getValue().get(name);
|
|
||||||
if (v != null) return (A) v;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <A> Map<String, A> find(final Pattern reg, Class<? extends A> clazz, A exclude) {
|
|
||||||
Map<String, A> result = new LinkedHashMap();
|
|
||||||
load(reg, clazz, exclude, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <A> void load(final Pattern reg, Class<? extends A> clazz, final A exclude, final Map<String, A> result) {
|
|
||||||
ConcurrentHashMap<String, ?> map = this.store.get(clazz);
|
|
||||||
if (map != null) {
|
|
||||||
for (Map.Entry<String, ?> en : map.entrySet()) { // 不用forEach为兼容JDK 6
|
|
||||||
String x = en.getKey();
|
|
||||||
Object y = en.getValue();
|
|
||||||
if (y != exclude && reg.matcher(x).find() && result.get(x) == null) result.put(x, (A) y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (parent != null) parent.load(reg, clazz, exclude, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> boolean inject(final Object src) {
|
|
||||||
return inject(src, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> boolean inject(final Object src, final T attachment) {
|
|
||||||
return inject(src, attachment, new ArrayList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> boolean inject(final Object src, final T attachment, final List<Object> list) {
|
|
||||||
if (src == null) return false;
|
|
||||||
try {
|
|
||||||
list.add(src);
|
|
||||||
Class clazz = src.getClass();
|
|
||||||
do {
|
|
||||||
for (Field field : clazz.getDeclaredFields()) {
|
|
||||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
|
||||||
field.setAccessible(true);
|
|
||||||
final Class classtype = field.getType();
|
|
||||||
final Type genctype = field.getGenericType();
|
|
||||||
Resource rc = field.getAnnotation(Resource.class);
|
|
||||||
if (rc == null) {
|
|
||||||
boolean flag = true;
|
|
||||||
Object ns = field.get(src);
|
|
||||||
for (Object o : list) {
|
|
||||||
if (o == ns) {
|
|
||||||
flag = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ns == null) continue;
|
|
||||||
if (ns.getClass().isPrimitive() || ns.getClass().isArray() || ns.getClass().getName().startsWith("java")) continue;
|
|
||||||
if (flag) this.inject(ns, attachment, list);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (Modifier.isFinal(field.getModifiers())) continue;
|
|
||||||
final String rcname = (rc.name().contains(RESOURCE_PARENT_NAME) && src instanceof Nameable) ? rc.name().replace(RESOURCE_PARENT_NAME, ((Nameable) src).name()) : rc.name();
|
|
||||||
Object rs = genctype == classtype ? null : find(rcname, genctype);
|
|
||||||
if (rs == null) {
|
|
||||||
if (Map.class.isAssignableFrom(classtype)) {
|
|
||||||
rs = find(Pattern.compile(rcname.isEmpty() ? ".*" : rcname), (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[1], src);
|
|
||||||
} else if (rcname.startsWith("property.")) {
|
|
||||||
rs = find(rcname, String.class);
|
|
||||||
} else {
|
|
||||||
rs = find(rcname, classtype);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rs == null) {
|
|
||||||
Intercepter it = findIntercepter(field.getGenericType(), field);
|
|
||||||
if (it != null) it.invoke(this, src, field, attachment);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!rs.getClass().isPrimitive() && classtype.isPrimitive()) {
|
|
||||||
if (classtype == int.class) {
|
|
||||||
rs = Integer.decode(rs.toString());
|
|
||||||
} else if (classtype == long.class) {
|
|
||||||
rs = Long.decode(rs.toString());
|
|
||||||
} else if (classtype == short.class) {
|
|
||||||
rs = Short.decode(rs.toString());
|
|
||||||
} else if (classtype == boolean.class) {
|
|
||||||
rs = "true".equalsIgnoreCase(rs.toString());
|
|
||||||
} else if (classtype == byte.class) {
|
|
||||||
rs = Byte.decode(rs.toString());
|
|
||||||
} else if (classtype == float.class) {
|
|
||||||
rs = Float.parseFloat(rs.toString());
|
|
||||||
} else if (classtype == double.class) {
|
|
||||||
rs = Double.parseDouble(rs.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
field.set(src, rs);
|
|
||||||
}
|
|
||||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
|
||||||
return true;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logger.log(Level.FINER, "inject " + src + " error", ex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Intercepter findIntercepter(Type ft, Field field) {
|
|
||||||
Intercepter it = this.interceptmap.get(ft);
|
|
||||||
if (it != null) return it;
|
|
||||||
Class c = field.getType();
|
|
||||||
for (Map.Entry<Type, Intercepter> en : this.interceptmap.entrySet()) {
|
|
||||||
Type t = en.getKey();
|
|
||||||
if (t == ft) return en.getValue();
|
|
||||||
if (t instanceof Class && (((Class) t)).isAssignableFrom(c)) return en.getValue();
|
|
||||||
}
|
|
||||||
return parent == null ? null : parent.findIntercepter(ft, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface Intercepter {
|
|
||||||
|
|
||||||
public void invoke(ResourceFactory factory, Object src, Field field, Object attachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.*;
|
|
||||||
import java.util.regex.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public class SelectColumn implements Predicate<String> {
|
|
||||||
|
|
||||||
private Pattern[] patterns;
|
|
||||||
|
|
||||||
private String[] columns;
|
|
||||||
|
|
||||||
private boolean excludable; //是否排除
|
|
||||||
|
|
||||||
public SelectColumn() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SelectColumn(final String[] columns0, final boolean excludable) {
|
|
||||||
this.excludable = excludable;
|
|
||||||
final int len = columns0.length;
|
|
||||||
if (len < 1) return;
|
|
||||||
Pattern[] regs = null;
|
|
||||||
String[] cols = null;
|
|
||||||
int regcount = 0;
|
|
||||||
int colcount = 0;
|
|
||||||
for (String col : columns0) {
|
|
||||||
boolean reg = false;
|
|
||||||
for (int i = 0; i < col.length(); i++) {
|
|
||||||
char ch = col.charAt(i);
|
|
||||||
if (ch == '^' || ch == '$' || ch == '*' || ch == '?' || ch == '+' || ch == '[' || ch == '(') {
|
|
||||||
reg = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reg) {
|
|
||||||
if (regs == null) regs = new Pattern[len];
|
|
||||||
regs[regcount++] = Pattern.compile(col);
|
|
||||||
} else {
|
|
||||||
if (cols == null) cols = new String[len];
|
|
||||||
cols[colcount++] = col;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (regs != null) {
|
|
||||||
if (regcount == len) {
|
|
||||||
this.patterns = regs;
|
|
||||||
} else {
|
|
||||||
this.patterns = Arrays.copyOf(regs, regcount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cols != null) {
|
|
||||||
if (colcount == len) {
|
|
||||||
this.columns = cols;
|
|
||||||
} else {
|
|
||||||
this.columns = Arrays.copyOf(cols, colcount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* class中的字段名
|
|
||||||
*
|
|
||||||
* @param columns
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static SelectColumn createIncludes(String... columns) {
|
|
||||||
return new SelectColumn(columns, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* class中的字段名
|
|
||||||
*
|
|
||||||
* @param columns
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static SelectColumn createExcludes(String... columns) {
|
|
||||||
return new SelectColumn(columns, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(final String column) {
|
|
||||||
if (this.columns != null) {
|
|
||||||
for (String col : this.columns) {
|
|
||||||
if (col.equalsIgnoreCase(column)) return !excludable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.patterns != null) {
|
|
||||||
for (Pattern reg : this.patterns) {
|
|
||||||
if (reg.matcher(column).find()) return !excludable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return excludable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getColumns() {
|
|
||||||
return columns;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColumns(String[] columns) {
|
|
||||||
this.columns = columns;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExcludable() {
|
|
||||||
return excludable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExcludable(boolean excludable) {
|
|
||||||
this.excludable = excludable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pattern[] getPatterns() {
|
|
||||||
return patterns;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPatterns(Pattern[] patterns) {
|
|
||||||
this.patterns = patterns;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(getClass().getSimpleName()).append("{excludable=").append(excludable);
|
|
||||||
if (columns != null) sb.append(", columns=").append(Arrays.toString(columns));
|
|
||||||
if (patterns != null) sb.append(", patterns=").append(Arrays.toString(patterns));
|
|
||||||
return sb.append('}').toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 页集合。 结构由一个total总数和一个List列表组合而成。
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public class Sheet<T> implements java.io.Serializable {
|
|
||||||
|
|
||||||
private long total = -1;
|
|
||||||
|
|
||||||
private Collection<T> rows;
|
|
||||||
|
|
||||||
public Sheet() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Sheet(int total, Collection<? extends T> data) {
|
|
||||||
this((long) total, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Sheet(long total, Collection<? extends T> data) {
|
|
||||||
this.total = total;
|
|
||||||
this.rows = (Collection<T>) data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <E> Sheet<E> asSheet(Collection<E> data) {
|
|
||||||
return data == null ? new Sheet() : new Sheet(data.size(), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Sheet<T> copyTo(Sheet<T> copy) {
|
|
||||||
if (copy == null) return copy;
|
|
||||||
copy.total = this.total;
|
|
||||||
if (this.getRows() != null) {
|
|
||||||
copy.setRows(new ArrayList(this.getRows()));
|
|
||||||
} else {
|
|
||||||
copy.rows = null;
|
|
||||||
}
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断数据列表是否为空
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return this.rows == null || this.rows.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Sheet[total=" + this.total + ", rows=" + this.rows + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTotal() {
|
|
||||||
return this.total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTotal(long total) {
|
|
||||||
this.total = total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<T> getRows() {
|
|
||||||
return this.rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<T> list() {
|
|
||||||
return list(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<T> list(boolean created) {
|
|
||||||
if (this.rows == null) return created ? new ArrayList() : null;
|
|
||||||
return (this.rows instanceof List) ? (List<T>) this.rows : new ArrayList(this.rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRows(Collection<? extends T> data) {
|
|
||||||
this.rows = (Collection<T>) data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this template, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.WildcardType;
|
|
||||||
import java.lang.reflect.TypeVariable;
|
|
||||||
import java.lang.reflect.GenericArrayType;
|
|
||||||
import java.util.*;
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 获取泛型的Type类
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public abstract class TypeToken<T> {
|
|
||||||
|
|
||||||
private final Type type;
|
|
||||||
|
|
||||||
public TypeToken() {
|
|
||||||
type = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public final Type getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断Type是否能确定最终的class, 是则返回true,存在通配符或者不确定类型则返回false。
|
|
||||||
* 例如: Map< String, String > 返回 ture; Map< ? extends Serializable, String > 返回false;
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public final static boolean isClassType(final Type type) {
|
|
||||||
if (type instanceof Class) return true;
|
|
||||||
if (type instanceof WildcardType) return false;
|
|
||||||
if (type instanceof TypeVariable) return false;
|
|
||||||
if (type instanceof GenericArrayType) return isClassType(((GenericArrayType) type).getGenericComponentType());
|
|
||||||
if (!(type instanceof ParameterizedType)) return false; //只能是null了
|
|
||||||
final ParameterizedType ptype = (ParameterizedType) type;
|
|
||||||
if (ptype.getOwnerType() != null && !isClassType(ptype.getOwnerType())) return false;
|
|
||||||
if (!isClassType(ptype.getRawType())) return false;
|
|
||||||
for (Type t : ptype.getActualTypeArguments()) {
|
|
||||||
if (!isClassType(t)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 动态创建 ParameterizedType
|
|
||||||
*
|
|
||||||
* @param ownerType0
|
|
||||||
* @param rawType0
|
|
||||||
* @param actualTypeArguments0
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static Type createParameterizedType(final Type ownerType0, final Type rawType0, final Type... actualTypeArguments0) {
|
|
||||||
if (ownerType0 == null && rawType0 instanceof Class) {
|
|
||||||
int count = 0;
|
|
||||||
for (Type t : actualTypeArguments0) {
|
|
||||||
if (isClassType(t)) count++;
|
|
||||||
}
|
|
||||||
if (count == actualTypeArguments0.length) return createParameterizedType((Class) rawType0, actualTypeArguments0);
|
|
||||||
}
|
|
||||||
return new ParameterizedType() {
|
|
||||||
private final Class<?> rawType = (Class<?>) rawType0;
|
|
||||||
|
|
||||||
private final Type ownerType = ownerType0;
|
|
||||||
|
|
||||||
private final Type[] actualTypeArguments = actualTypeArguments0;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type[] getActualTypeArguments() {
|
|
||||||
return actualTypeArguments.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getRawType() {
|
|
||||||
return rawType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getOwnerType() {
|
|
||||||
return ownerType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Arrays.hashCode(actualTypeArguments) ^ Objects.hashCode(rawType) ^ Objects.hashCode(ownerType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof ParameterizedType)) return false;
|
|
||||||
final ParameterizedType that = (ParameterizedType) o;
|
|
||||||
if (this == that) return true;
|
|
||||||
return Objects.equals(ownerType, that.getOwnerType())
|
|
||||||
&& Objects.equals(rawType, that.getRawType())
|
|
||||||
&& Arrays.equals(actualTypeArguments, that.getActualTypeArguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
if (ownerType != null) sb.append((ownerType instanceof Class) ? (((Class) ownerType).getName()) : ownerType.toString()).append(".");
|
|
||||||
sb.append(rawType.getName());
|
|
||||||
|
|
||||||
if (actualTypeArguments != null && actualTypeArguments.length > 0) {
|
|
||||||
sb.append("<");
|
|
||||||
boolean first = true;
|
|
||||||
for (Type t : actualTypeArguments) {
|
|
||||||
if (!first) sb.append(", ");
|
|
||||||
sb.append(t);
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
sb.append(">");
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Type createParameterizedType(final Class rawType, final Type... actualTypeArguments) {
|
|
||||||
ClassLoader loader = TypeToken.class.getClassLoader();
|
|
||||||
String newDynName = TypeToken.class.getName().replace('.', '/') + "_Dyn" + System.currentTimeMillis();
|
|
||||||
for (;;) {
|
|
||||||
try {
|
|
||||||
Class.forName(newDynName.replace('/', '.'));
|
|
||||||
newDynName = TypeToken.class.getName().replace('.', '/') + "_Dyn" + Math.abs(System.nanoTime());
|
|
||||||
} catch (Exception ex) { //异常说明类不存在
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClassWriter cw = new ClassWriter(0);
|
|
||||||
FieldVisitor fv;
|
|
||||||
MethodVisitor mv;
|
|
||||||
cw.visit(V1_7, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, "java/lang/Object", null);
|
|
||||||
String rawTypeDesc = org.objectweb.asm.Type.getDescriptor(rawType);
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(rawTypeDesc.substring(0, rawTypeDesc.length() - 1)).append('<');
|
|
||||||
for (Type c : actualTypeArguments) {
|
|
||||||
sb.append(getClassTypeDescriptor(c));
|
|
||||||
}
|
|
||||||
sb.append(">;");
|
|
||||||
{
|
|
||||||
fv = cw.visitField(ACC_PUBLIC, "field", rawTypeDesc, sb.toString(), null);
|
|
||||||
fv.visitEnd();
|
|
||||||
}
|
|
||||||
{//构造方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
mv.visitMaxs(1, 1);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
cw.visitEnd();
|
|
||||||
byte[] bytes = cw.toByteArray();
|
|
||||||
Class<?> newClazz = new ClassLoader(loader) {
|
|
||||||
public final Class<?> loadClass(String name, byte[] b) {
|
|
||||||
return defineClass(name, b, 0, b.length);
|
|
||||||
}
|
|
||||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
|
||||||
try {
|
|
||||||
return newClazz.getField("field").getGenericType();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CharSequence getClassTypeDescriptor(Type type) {
|
|
||||||
if (!isClassType(type)) throw new IllegalArgumentException(type + " not a class type");
|
|
||||||
if (type instanceof Class) return org.objectweb.asm.Type.getDescriptor((Class) type);
|
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
|
||||||
CharSequence rawTypeDesc = getClassTypeDescriptor(pt.getRawType());
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(rawTypeDesc.subSequence(0, rawTypeDesc.length() - 1)).append('<');
|
|
||||||
for (Type c : pt.getActualTypeArguments()) {
|
|
||||||
sb.append(getClassTypeDescriptor(c));
|
|
||||||
}
|
|
||||||
sb.append(">;");
|
|
||||||
return sb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,554 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this template, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.util;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.*;
|
|
||||||
import java.util.*;
|
|
||||||
import javax.net.ssl.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class Utility {
|
|
||||||
|
|
||||||
private static final int zoneRawOffset = TimeZone.getDefault().getRawOffset();
|
|
||||||
|
|
||||||
private static final String format = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL";
|
|
||||||
|
|
||||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
|
||||||
|
|
||||||
private static final char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
|
||||||
|
|
||||||
private static final javax.net.ssl.SSLContext DEFAULTSSL_CONTEXT;
|
|
||||||
|
|
||||||
static {
|
|
||||||
|
|
||||||
try {
|
|
||||||
DEFAULTSSL_CONTEXT = javax.net.ssl.SSLContext.getInstance("SSL");
|
|
||||||
DEFAULTSSL_CONTEXT.init(null, new javax.net.ssl.TrustManager[]{new javax.net.ssl.X509TrustManager() {
|
|
||||||
@Override
|
|
||||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException {
|
|
||||||
}
|
|
||||||
}}, null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e); //不可能会发生
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Utility() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String now() {
|
|
||||||
return String.format(format, System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void println(String string, ByteBuffer buffer) {
|
|
||||||
if (buffer == null || !buffer.hasRemaining()) return;
|
|
||||||
byte[] bytes = new byte[buffer.remaining()];
|
|
||||||
buffer.get(bytes);
|
|
||||||
buffer.flip();
|
|
||||||
println(string, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void println(String string, byte... bytes) {
|
|
||||||
if (bytes == null) return;
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
if (string != null) sb.append(string);
|
|
||||||
sb.append(bytes.length).append(".[");
|
|
||||||
boolean last = false;
|
|
||||||
for (byte b : bytes) {
|
|
||||||
if (last) sb.append(',');
|
|
||||||
int v = b & 0xff;
|
|
||||||
if (v < 16) sb.append('0');
|
|
||||||
sb.append(Integer.toHexString(v));
|
|
||||||
last = true;
|
|
||||||
}
|
|
||||||
sb.append(']');
|
|
||||||
(System.out).println(sb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回本机的第一个内网IPv4地址, 没有则返回null
|
|
||||||
* <p>
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static InetAddress localInetAddress() {
|
|
||||||
InetAddress back = null;
|
|
||||||
try {
|
|
||||||
Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
|
|
||||||
while (nifs.hasMoreElements()) {
|
|
||||||
NetworkInterface nif = nifs.nextElement();
|
|
||||||
if (!nif.isUp()) continue;
|
|
||||||
Enumeration<InetAddress> eis = nif.getInetAddresses();
|
|
||||||
while (eis.hasMoreElements()) {
|
|
||||||
InetAddress ia = eis.nextElement();
|
|
||||||
if (ia.isLoopbackAddress()) back = ia;
|
|
||||||
if (ia.isSiteLocalAddress()) return ia;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return back;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当天凌晨零点的格林时间
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static long midnight() {
|
|
||||||
return midnight(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取指定时间当天凌晨零点的格林时间
|
|
||||||
*
|
|
||||||
* @param time
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static long midnight(long time) {
|
|
||||||
return (time + zoneRawOffset) / 86400000 * 86400000 - zoneRawOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当天20151231格式的int值
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static int today() {
|
|
||||||
final Calendar cal = Calendar.getInstance();
|
|
||||||
return cal.get(Calendar.YEAR) * 10000 + (cal.get(Calendar.MONTH) + 1) * 100 + cal.get(Calendar.DAY_OF_MONTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取时间点所在星期的周一
|
|
||||||
*
|
|
||||||
* @param time
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static long monday(long time) {
|
|
||||||
final Calendar cal = Calendar.getInstance();
|
|
||||||
cal.setTimeInMillis(time);
|
|
||||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
||||||
cal.set(Calendar.MINUTE, 0);
|
|
||||||
cal.set(Calendar.SECOND, 0);
|
|
||||||
cal.set(Calendar.MILLISECOND, 0);
|
|
||||||
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
|
|
||||||
return cal.getTimeInMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取时间点所在星期的周日
|
|
||||||
*
|
|
||||||
* @param time
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static long sunday(long time) {
|
|
||||||
final Calendar cal = Calendar.getInstance();
|
|
||||||
cal.setTimeInMillis(time);
|
|
||||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
||||||
cal.set(Calendar.MINUTE, 0);
|
|
||||||
cal.set(Calendar.SECOND, 0);
|
|
||||||
cal.set(Calendar.MILLISECOND, 0);
|
|
||||||
cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
|
|
||||||
return cal.getTimeInMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取时间点所在月份的1号
|
|
||||||
*
|
|
||||||
* @param time
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static long monthFirstDay(long time) {
|
|
||||||
final Calendar cal = Calendar.getInstance();
|
|
||||||
cal.setTimeInMillis(time);
|
|
||||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
||||||
cal.set(Calendar.MINUTE, 0);
|
|
||||||
cal.set(Calendar.SECOND, 0);
|
|
||||||
cal.set(Calendar.MILLISECOND, 0);
|
|
||||||
cal.set(Calendar.DAY_OF_MONTH, 1);
|
|
||||||
return cal.getTimeInMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String binToHexString(byte[] bytes) {
|
|
||||||
return new String(binToHex(bytes));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static char[] binToHex(byte[] bytes) {
|
|
||||||
return binToHex(bytes, 0, bytes.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String binToHexString(byte[] bytes, int offset, int len) {
|
|
||||||
return new String(binToHex(bytes, offset, len));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static char[] binToHex(byte[] bytes, int offset, int len) {
|
|
||||||
final char[] sb = new char[len * 2];
|
|
||||||
final int end = offset + len;
|
|
||||||
int index = 0;
|
|
||||||
final char[] hexs = hex;
|
|
||||||
for (int i = offset; i < end; i++) {
|
|
||||||
byte b = bytes[i];
|
|
||||||
sb[index++] = (hexs[((b >> 4) & 0xF)]);
|
|
||||||
sb[index++] = hexs[((b) & 0xF)];
|
|
||||||
}
|
|
||||||
return sb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] hexToBin(CharSequence src) {
|
|
||||||
return hexToBin(src, 0, src.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] hexToBin(CharSequence src, int offset, int len) {
|
|
||||||
final int size = (len + 1) / 2;
|
|
||||||
final byte[] bytes = new byte[size];
|
|
||||||
final int end = offset + len;
|
|
||||||
String digits = "0123456789abcdef";
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
int ch1 = src.charAt(offset + i * 2);
|
|
||||||
if ('A' <= ch1 && 'F' >= ch1) ch1 = ch1 - 'A' + 'a';
|
|
||||||
int ch2 = src.charAt(offset + i * 2 + 1);
|
|
||||||
if ('A' <= ch2 && 'F' >= ch2) ch2 = ch2 - 'A' + 'a';
|
|
||||||
int pos1 = digits.indexOf(ch1);
|
|
||||||
if (pos1 < 0) throw new NumberFormatException();
|
|
||||||
int pos2 = digits.indexOf(ch2);
|
|
||||||
if (pos2 < 0) throw new NumberFormatException();
|
|
||||||
bytes[i] = (byte) (pos1 * 0x10 + pos2);
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] hexToBin(String str) {
|
|
||||||
return hexToBin(charArray(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] hexToBin(char[] src) {
|
|
||||||
return hexToBin(src, 0, src.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] hexToBin(char[] src, int offset, int len) {
|
|
||||||
final int size = (len + 1) / 2;
|
|
||||||
final byte[] bytes = new byte[size];
|
|
||||||
final int end = offset + len;
|
|
||||||
String digits = "0123456789abcdef";
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
int ch1 = src[offset + i * 2];
|
|
||||||
if ('A' <= ch1 && 'F' >= ch1) ch1 = ch1 - 'A' + 'a';
|
|
||||||
int ch2 = src[offset + i * 2 + 1];
|
|
||||||
if ('A' <= ch2 && 'F' >= ch2) ch2 = ch2 - 'A' + 'a';
|
|
||||||
int pos1 = digits.indexOf(ch1);
|
|
||||||
if (pos1 < 0) throw new NumberFormatException();
|
|
||||||
int pos2 = digits.indexOf(ch2);
|
|
||||||
if (pos2 < 0) throw new NumberFormatException();
|
|
||||||
bytes[i] = (byte) (pos1 * 0x10 + pos2);
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
public static char[] decodeUTF8(final byte[] array) {
|
|
||||||
return decodeUTF8(array, 0, array.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static char[] decodeUTF8(final byte[] array, final int start, final int len) {
|
|
||||||
byte b;
|
|
||||||
int size = len;
|
|
||||||
final byte[] bytes = array;
|
|
||||||
final int limit = start + len;
|
|
||||||
for (int i = start; i < limit; i++) {
|
|
||||||
b = bytes[i];
|
|
||||||
if ((b >> 5) == -2) {
|
|
||||||
size--;
|
|
||||||
} else if ((b >> 4) == -2) {
|
|
||||||
size -= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final char[] text = new char[size];
|
|
||||||
size = 0;
|
|
||||||
for (int i = start; i < limit;) {
|
|
||||||
b = bytes[i++];
|
|
||||||
if (b >= 0) {
|
|
||||||
text[size++] = (char) b;
|
|
||||||
} else if ((b >> 5) == -2) {
|
|
||||||
text[size++] = (char) (((b << 6) ^ bytes[i++]) ^ (((byte) 0xC0 << 6) ^ ((byte) 0x80)));
|
|
||||||
} else if ((b >> 4) == -2) {
|
|
||||||
text[size++] = (char) ((b << 12) ^ (bytes[i++] << 6) ^ (bytes[i++] ^ (((byte) 0xE0 << 12) ^ ((byte) 0x80 << 6) ^ ((byte) 0x80))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] encodeUTF8(final String value) {
|
|
||||||
if (value == null) return new byte[0];
|
|
||||||
return encodeUTF8(value.toCharArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] encodeUTF8(final char[] array) {
|
|
||||||
return encodeUTF8(array, 0, array.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] encodeUTF8(final char[] text, final int start, final int len) {
|
|
||||||
char c;
|
|
||||||
int size = 0;
|
|
||||||
final char[] chars = text;
|
|
||||||
final int limit = start + len;
|
|
||||||
for (int i = start; i < limit; i++) {
|
|
||||||
c = chars[i];
|
|
||||||
if (c < 0x80) {
|
|
||||||
size++;
|
|
||||||
} else if (c < 0x800) {
|
|
||||||
size += 2;
|
|
||||||
} else {
|
|
||||||
size += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final byte[] bytes = new byte[size];
|
|
||||||
size = 0;
|
|
||||||
for (int i = start; i < limit; i++) {
|
|
||||||
c = chars[i];
|
|
||||||
if (c < 0x80) {
|
|
||||||
bytes[size++] = (byte) c;
|
|
||||||
} else if (c < 0x800) {
|
|
||||||
bytes[size++] = (byte) (0xc0 | (c >> 6));
|
|
||||||
bytes[size++] = (byte) (0x80 | (c & 0x3f));
|
|
||||||
} else {
|
|
||||||
bytes[size++] = (byte) (0xe0 | ((c >> 12)));
|
|
||||||
bytes[size++] = (byte) (0x80 | ((c >> 6) & 0x3f));
|
|
||||||
bytes[size++] = (byte) (0x80 | (c & 0x3f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static char[] charArray(String value) { //与JDK 8 的实现版本不一样
|
|
||||||
return value == null ? null : value.toCharArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static char[] charArray(StringBuilder value) { //与JDK 8 的实现版本不一样
|
|
||||||
return value == null ? null : value.toString().toCharArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, final char[] array) {
|
|
||||||
return encodeUTF8(buffer, array, 0, array.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, int bytesLength, final char[] array) {
|
|
||||||
return encodeUTF8(buffer, bytesLength, array, 0, array.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int encodeUTF8Length(String value) {
|
|
||||||
if (value == null) return -1;
|
|
||||||
return encodeUTF8Length(value.toCharArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int encodeUTF8Length(final char[] text) {
|
|
||||||
return encodeUTF8Length(text, 0, text.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int encodeUTF8Length(final char[] text, final int start, final int len) {
|
|
||||||
char c;
|
|
||||||
int size = 0;
|
|
||||||
final char[] chars = text;
|
|
||||||
final int limit = start + len;
|
|
||||||
for (int i = start; i < limit; i++) {
|
|
||||||
c = chars[i];
|
|
||||||
size += (c < 0x80 ? 1 : (c < 0x800 ? 2 : 3));
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将两个数字组装成一个long
|
|
||||||
* <p>
|
|
||||||
* @param high
|
|
||||||
* @param low
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static long merge(int high, int low) {
|
|
||||||
return (0L + high) << 32 | low;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, final char[] text, final int start, final int len) {
|
|
||||||
return encodeUTF8(buffer, encodeUTF8Length(text, start, len), text, start, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, int bytesLength, final char[] text, final int start, final int len) {
|
|
||||||
char c;
|
|
||||||
char[] chars = text;
|
|
||||||
final int limit = start + len;
|
|
||||||
int remain = buffer.remaining();
|
|
||||||
final ByteBuffer buffer2 = remain >= bytesLength ? null : ByteBuffer.allocate(bytesLength - remain + 3); //最差情况buffer最后两byte没有填充
|
|
||||||
ByteBuffer buf = buffer;
|
|
||||||
for (int i = start; i < limit; i++) {
|
|
||||||
c = chars[i];
|
|
||||||
if (c < 0x80) {
|
|
||||||
if (buf.remaining() < 1) buf = buffer2;
|
|
||||||
buf.put((byte) c);
|
|
||||||
} else if (c < 0x800) {
|
|
||||||
if (buf.remaining() < 2) buf = buffer2;
|
|
||||||
buf.put((byte) (0xc0 | (c >> 6)));
|
|
||||||
buf.put((byte) (0x80 | (c & 0x3f)));
|
|
||||||
} else {
|
|
||||||
if (buf.remaining() < 3) buf = buffer2;
|
|
||||||
buf.put((byte) (0xe0 | ((c >> 12))));
|
|
||||||
buf.put((byte) (0x80 | ((c >> 6) & 0x3f)));
|
|
||||||
buf.put((byte) (0x80 | (c & 0x3f)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (buffer2 != null) buffer2.flip();
|
|
||||||
return buffer2;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
public static javax.net.ssl.SSLContext getDefaultSSLContext() {
|
|
||||||
return DEFAULTSSL_CONTEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Socket createDefaultSSLSocket(InetSocketAddress address) throws IOException {
|
|
||||||
return createDefaultSSLSocket(address.getAddress(), address.getPort());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Socket createDefaultSSLSocket(InetAddress host, int port) throws IOException {
|
|
||||||
Socket socket = DEFAULTSSL_CONTEXT.getSocketFactory().createSocket(host, port);
|
|
||||||
|
|
||||||
return socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String postHttpContent(String url) throws IOException {
|
|
||||||
return remoteHttpContent(null, "POST", url, null, null).toString("UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String postHttpContent(String url, String body) throws IOException {
|
|
||||||
return remoteHttpContent(null, "POST", url, null, body).toString("UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String postHttpContent(String url, Map<String, String> headers, String body) throws IOException {
|
|
||||||
return remoteHttpContent(null, "POST", url, headers, body).toString("UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String postHttpContent(SSLContext ctx, String url) throws IOException {
|
|
||||||
return remoteHttpContent(ctx, "POST", url, null, null).toString("UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String postHttpContent(SSLContext ctx, String url, String body) throws IOException {
|
|
||||||
return remoteHttpContent(ctx, "POST", url, null, body).toString("UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String postHttpContent(SSLContext ctx, String url, Map<String, String> headers, String body) throws IOException {
|
|
||||||
return remoteHttpContent(ctx, "POST", url, headers, body).toString("UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] postHttpBytesContent(String url) throws IOException {
|
|
||||||
return remoteHttpContent(null, "POST", url, null, null).toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] postHttpBytesContent(SSLContext ctx, String url) throws IOException {
|
|
||||||
return remoteHttpContent(ctx, "POST", url, null, null).toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] postHttpBytesContent(String url, Map<String, String> headers, String body) throws IOException {
|
|
||||||
return remoteHttpContent(null, "POST", url, headers, body).toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] postHttpBytesContent(SSLContext ctx, String url, Map<String, String> headers, String body) throws IOException {
|
|
||||||
return remoteHttpContent(ctx, "POST", url, headers, body).toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getHttpContent(String url) throws IOException {
|
|
||||||
return remoteHttpContent(null, "GET", url, null, null).toString("UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getHttpContent(SSLContext ctx, String url) throws IOException {
|
|
||||||
return remoteHttpContent(ctx, "GET", url, null, null).toString("UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getHttpContent(SSLContext ctx, String url, Map<String, String> headers, String body) throws IOException {
|
|
||||||
return remoteHttpContent(ctx, "GET", url, headers, body).toString("UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getHttpContent(String url, Map<String, String> headers, String body) throws IOException {
|
|
||||||
return remoteHttpContent(null, "GET", url, headers, body).toString("UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] getHttpBytesContent(String url) throws IOException {
|
|
||||||
return remoteHttpContent(null, "GET", url, null, null).toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] getHttpBytesContent(SSLContext ctx, String url) throws IOException {
|
|
||||||
return remoteHttpContent(ctx, "GET", url, null, null).toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] getHttpBytesContent(String url, Map<String, String> headers, String body) throws IOException {
|
|
||||||
return remoteHttpContent(null, "GET", url, headers, body).toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] getHttpBytesContent(SSLContext ctx, String url, Map<String, String> headers, String body) throws IOException {
|
|
||||||
return remoteHttpContent(ctx, "GET", url, headers, body).toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static ByteArrayOutputStream remoteHttpContent(SSLContext ctx, String method, String url, Map<String, String> headers, String body) throws IOException {
|
|
||||||
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
|
||||||
conn.setConnectTimeout(3000);
|
|
||||||
conn.setReadTimeout(3000);
|
|
||||||
if (conn instanceof HttpsURLConnection) ((HttpsURLConnection) conn).setSSLSocketFactory((ctx == null ? DEFAULTSSL_CONTEXT : ctx).getSocketFactory());
|
|
||||||
conn.setRequestMethod(method);
|
|
||||||
if (headers != null) {
|
|
||||||
for (Map.Entry<String, String> en : headers.entrySet()) { //不用forEach是为了兼容JDK 6
|
|
||||||
conn.setRequestProperty(en.getKey(), en.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (body != null) {
|
|
||||||
conn.setDoInput(true);
|
|
||||||
conn.setDoOutput(true);
|
|
||||||
conn.getOutputStream().write(body.getBytes(UTF_8));
|
|
||||||
}
|
|
||||||
conn.connect();
|
|
||||||
int rs = conn.getResponseCode();
|
|
||||||
if (rs == 301 || rs == 302) {
|
|
||||||
String newurl = conn.getHeaderField("Location");
|
|
||||||
conn.disconnect();
|
|
||||||
return remoteHttpContent(ctx, method, newurl, headers, body);
|
|
||||||
}
|
|
||||||
InputStream in = conn.getInputStream();
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int pos;
|
|
||||||
while ((pos = in.read(bytes)) != -1) {
|
|
||||||
out.write(bytes, 0, pos);
|
|
||||||
}
|
|
||||||
conn.disconnect();
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String read(InputStream in) throws IOException {
|
|
||||||
return read(in, "UTF-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String read(InputStream in, String charsetName) throws IOException {
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int pos;
|
|
||||||
while ((pos = in.read(bytes)) != -1) {
|
|
||||||
out.write(bytes, 0, pos);
|
|
||||||
}
|
|
||||||
return charsetName == null ? out.toString() : out.toString(charsetName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.net.socks;
|
|
||||||
|
|
||||||
import org.redkale.net.Server;
|
|
||||||
import org.redkale.util.AnyValue;
|
|
||||||
import org.redkale.boot.Application;
|
|
||||||
import org.redkale.net.Servlet;
|
|
||||||
import org.redkale.boot.ClassFilter;
|
|
||||||
import org.redkale.boot.NodeServer;
|
|
||||||
import org.redkale.boot.NodeProtocol;
|
|
||||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
|
||||||
import static org.redkale.boot.NodeServer.LINE_SEPARATOR;
|
|
||||||
import org.redkale.util.AnyValue.DefaultAnyValue;
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.util.logging.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* < server protocol="SOCKS" host="0.0.0.0" port="1080" bindaddr="外网IP"> < /server>
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@NodeProtocol({"SOCKS"})
|
|
||||||
public class NodeSocksServer extends NodeServer {
|
|
||||||
|
|
||||||
private final SocksServer socksServer;
|
|
||||||
|
|
||||||
public NodeSocksServer(Application application, AnyValue serconf) {
|
|
||||||
super(application, application.getResourceFactory().createChild(), createServer(application, serconf));
|
|
||||||
this.socksServer = (SocksServer) server;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Server createServer(Application application, AnyValue serconf) {
|
|
||||||
return new SocksServer(application.getStartTime(), application.getWatchFactory());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InetSocketAddress getSocketAddress() {
|
|
||||||
return socksServer == null ? null : socksServer.getSocketAddress();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
|
||||||
return createClassFilter(null, null, SocksServlet.class, null, "servlets", "servlet");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter) throws Exception {
|
|
||||||
if (socksServer != null) loadSocksServlet(this.nodeConf.getAnyValue("servlets"), servletFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void loadSocksServlet(final AnyValue conf, ClassFilter<? extends Servlet> filter) throws Exception {
|
|
||||||
final StringBuilder sb = logger.isLoggable(Level.FINE) ? new StringBuilder() : null;
|
|
||||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
|
||||||
for (FilterEntry<? extends Servlet> en : filter.getFilterEntrys()) {
|
|
||||||
Class<SocksServlet> clazz = (Class<SocksServlet>) en.getType();
|
|
||||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
|
||||||
final SocksServlet servlet = clazz.newInstance();
|
|
||||||
factory.inject(servlet);
|
|
||||||
DefaultAnyValue servletConf = (DefaultAnyValue) en.getProperty();
|
|
||||||
this.socksServer.addSocksServlet(servlet, servletConf);
|
|
||||||
if (sb != null) sb.append(threadName).append(" Loaded ").append(clazz.getName()).append(" --> ").append(servletConf).append(LINE_SEPARATOR);
|
|
||||||
}
|
|
||||||
if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.net.socks;
|
|
||||||
|
|
||||||
import org.redkale.util.AnyValue;
|
|
||||||
import org.redkale.net.Context;
|
|
||||||
import org.redkale.util.Utility;
|
|
||||||
import org.redkale.util.AutoLoad;
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.*;
|
|
||||||
import java.nio.*;
|
|
||||||
import java.util.logging.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
@AutoLoad(false)
|
|
||||||
public class SocksConnectServlet extends SocksServlet {
|
|
||||||
|
|
||||||
private InetSocketAddress bindAddress;
|
|
||||||
|
|
||||||
private byte[] bindAddressBytes = new byte[0];
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Context context, AnyValue config) {
|
|
||||||
if (config == null) {
|
|
||||||
this.bindAddress = new InetSocketAddress(Utility.localInetAddress(), context.getServerAddress().getPort());
|
|
||||||
} else {
|
|
||||||
this.bindAddress = new InetSocketAddress(config.getValue("bindaddr", Utility.localInetAddress().getHostAddress()), context.getServerAddress().getPort());
|
|
||||||
}
|
|
||||||
Logger logger = context.getLogger();
|
|
||||||
if (logger.isLoggable(Level.INFO)) logger.info("[" + Thread.currentThread().getName() + "] bindAddress = " + bindAddress);
|
|
||||||
ByteBuffer bb;
|
|
||||||
InetAddress addr = bindAddress.getAddress();
|
|
||||||
if (addr instanceof Inet6Address) {
|
|
||||||
bb = ByteBuffer.allocate(1 + 16 + 2);
|
|
||||||
bb.put((byte) 0x04);
|
|
||||||
} else {
|
|
||||||
bb = ByteBuffer.allocate(1 + 4 + 2);
|
|
||||||
bb.put((byte) 0x01);
|
|
||||||
}
|
|
||||||
bb.put(addr.getAddress());
|
|
||||||
bb.putChar((char) bindAddress.getPort());
|
|
||||||
bb.flip();
|
|
||||||
this.bindAddressBytes = bb.array();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(SocksRequest request, SocksResponse response) throws IOException {
|
|
||||||
response.getContext().submit(new SocksRunner((SocksContext) response.getContext(), response.removeChannel(), bindAddressBytes));
|
|
||||||
response.finish(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.net.socks;
|
|
||||||
|
|
||||||
import java.net.*;
|
|
||||||
import java.nio.*;
|
|
||||||
import java.nio.channels.*;
|
|
||||||
import java.nio.charset.*;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import java.util.logging.*;
|
|
||||||
import org.redkale.net.*;
|
|
||||||
import org.redkale.net.http.*;
|
|
||||||
import org.redkale.util.*;
|
|
||||||
import org.redkale.watch.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public class SocksContext extends HttpContext {
|
|
||||||
|
|
||||||
protected final AsynchronousChannelGroup group;
|
|
||||||
|
|
||||||
public SocksContext(long serverStartTime, Logger logger, ExecutorService executor, int bufferCapacity, ObjectPool<ByteBuffer> bufferPool,
|
|
||||||
ObjectPool<Response> responsePool, int maxbody, Charset charset, InetSocketAddress address, PrepareServlet prepare,
|
|
||||||
WatchFactory watch, int readTimeoutSecond, int writeTimeoutSecond, String contextPath) {
|
|
||||||
super(serverStartTime, logger, executor, bufferCapacity, bufferPool, responsePool, maxbody, charset,
|
|
||||||
address, prepare, watch, readTimeoutSecond, writeTimeoutSecond, contextPath);
|
|
||||||
AsynchronousChannelGroup g = null;
|
|
||||||
try {
|
|
||||||
g = AsynchronousChannelGroup.withThreadPool(executor);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
this.group = g;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AsynchronousChannelGroup getAsynchronousChannelGroup() {
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.redkale.net.socks;
|
|
||||||
|
|
||||||
import org.redkale.util.AnyValue;
|
|
||||||
import org.redkale.net.Context;
|
|
||||||
import org.redkale.net.PrepareServlet;
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see http://www.redkale.org
|
|
||||||
* @author zhangjx
|
|
||||||
*/
|
|
||||||
public final class SocksPrepareServlet extends PrepareServlet<SocksRequest, SocksResponse> {
|
|
||||||
|
|
||||||
private SocksServlet socksServlet = new SocksConnectServlet();
|
|
||||||
|
|
||||||
private SocksProxyServlet proxyServlet = new SocksProxyServlet();
|
|
||||||
|
|
||||||
public SocksPrepareServlet() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Context context, AnyValue config) {
|
|
||||||
if (socksServlet != null) socksServlet.init(context, socksServlet.conf == null ? config : socksServlet.conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSocksServlet(SocksServlet servlet, AnyValue conf) {
|
|
||||||
servlet.conf = conf;
|
|
||||||
if (servlet != null) this.socksServlet = servlet;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
@Override
|
|
||||||
public void execute(SocksRequest request, SocksResponse response) throws IOException {
|
|
||||||
if (request.isHttp()) {
|
|
||||||
proxyServlet.execute(request, response);
|
|
||||||
} else {
|
|
||||||
socksServlet.execute(request, response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user