Rock
1 year ago
895 changed files with 0 additions and 139529 deletions
@ -1,6 +0,0 @@
|
||||
*.iml |
||||
.idea/ |
||||
.DS_Store |
||||
.project |
||||
.classpath |
||||
*.gradle |
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<parent> |
||||
<groupId>com.fr.third</groupId> |
||||
<artifactId>step1</artifactId> |
||||
<version>${revision}</version> |
||||
<relativePath>../base-third-project/base-third-step1</relativePath> |
||||
</parent> |
||||
|
||||
<artifactId>fine-jodd</artifactId> |
||||
<version>${revision}</version> |
||||
|
||||
|
||||
</project> |
@ -1,5 +0,0 @@
|
||||
## jodd |
||||
|
||||
版本:3.7.1 |
||||
|
||||
github地址:https://github.com/oblac/jodd/tree/v3.7.1 |
@ -1,43 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd; |
||||
|
||||
/** |
||||
* Jodd! |
||||
*/ |
||||
public class Jodd { |
||||
|
||||
/** |
||||
* Ascii art of Jodds name. Every serious framework needs one:) |
||||
*/ |
||||
public static String JODD = "\n" + |
||||
" __ __ __\n" + |
||||
" / /___ ____/ /___/ /\n" + |
||||
" __ / / __ \\/ __ / __ / \n" + |
||||
" / /_/ / /_/ / /_/ / /_/ / \n" + |
||||
" \\____/\\____/\\__,_/\\__,_/ \n"; |
||||
|
||||
} |
@ -1,188 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import static com.fr.third.jodd.util.StringPool.LEFT_SQ_BRACKET; |
||||
import static com.fr.third.jodd.util.StringPool.RIGHT_SQ_BRACKET; |
||||
|
||||
/** |
||||
* Powerful tool for copying properties from one bean into another. |
||||
* <code>BeanCopy</code> works with POJO beans, but also with <code>Map</code>. |
||||
* |
||||
* @see BeanVisitor |
||||
*/ |
||||
public class BeanCopy extends BeanVisitorImplBase<BeanCopy> { |
||||
|
||||
protected Object destination; |
||||
protected boolean forced; |
||||
protected boolean declaredTarget; |
||||
protected boolean isTargetMap; |
||||
|
||||
// ---------------------------------------------------------------- ctor
|
||||
|
||||
/** |
||||
* Creates new BeanCopy process between the source and the destination. |
||||
* Both source and destination can be a POJO object or a <code>Map</code>. |
||||
*/ |
||||
public BeanCopy(final Object source, final Object destination) { |
||||
this.source = source; |
||||
this.destination = destination; |
||||
} |
||||
|
||||
private BeanCopy(final Object source) { |
||||
this.source = source; |
||||
} |
||||
|
||||
/** |
||||
* Simple static factory for <code>BeanCopy</code>. |
||||
* @see #BeanCopy(Object, Object) |
||||
*/ |
||||
public static BeanCopy beans(final Object source, final Object destination) { |
||||
return new BeanCopy(source, destination); |
||||
} |
||||
|
||||
/** |
||||
* Creates <code>BeanCopy</code> with given POJO bean as a source. |
||||
*/ |
||||
public static BeanCopy fromBean(final Object source) { |
||||
return new BeanCopy(source); |
||||
} |
||||
|
||||
/** |
||||
* Creates <code>BeanCopy</code> with given <code>Map</code> as a source. |
||||
*/ |
||||
public static BeanCopy fromMap(final Map source) { |
||||
BeanCopy beanCopy = new BeanCopy(source); |
||||
|
||||
beanCopy.isSourceMap = true; |
||||
|
||||
return beanCopy; |
||||
} |
||||
|
||||
/** |
||||
* Defines source, detects a map. |
||||
*/ |
||||
public static BeanCopy from(final Object source) { |
||||
BeanCopy beanCopy = new BeanCopy(source); |
||||
|
||||
beanCopy.isSourceMap = source instanceof Map; |
||||
|
||||
return beanCopy; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- destination
|
||||
|
||||
/** |
||||
* Defines destination bean. |
||||
*/ |
||||
public BeanCopy toBean(final Object destination) { |
||||
this.destination = destination; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Defines destination map. |
||||
*/ |
||||
public BeanCopy toMap(final Map destination) { |
||||
this.destination = destination; |
||||
|
||||
isTargetMap = true; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Defines destination, detects a map. |
||||
*/ |
||||
public BeanCopy to(final Object destination) { |
||||
this.destination = destination; |
||||
|
||||
this.isTargetMap = destination instanceof Map; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- properties
|
||||
|
||||
/** |
||||
* Defines if all properties should be copied (when set to <code>true</code>) |
||||
* or only public (when set to <code>false</code>, default). |
||||
*/ |
||||
@Override |
||||
public BeanCopy declared(final boolean declared) { |
||||
this.declared = declared; |
||||
this.declaredTarget = declared; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Fine-tuning of the declared behaviour. |
||||
*/ |
||||
public BeanCopy declared(final boolean declaredSource, final boolean declaredTarget) { |
||||
this.declared = declaredSource; |
||||
this.declaredTarget = declaredTarget; |
||||
return this; |
||||
} |
||||
|
||||
public BeanCopy forced(final boolean forced) { |
||||
this.forced = forced; |
||||
return this; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- visitor
|
||||
|
||||
protected BeanUtil beanUtil; |
||||
|
||||
/** |
||||
* Performs the copying. |
||||
*/ |
||||
public void copy() { |
||||
beanUtil = new BeanUtilBean() |
||||
.declared(declared) |
||||
.forced(forced) |
||||
.silent(true); |
||||
visit(); |
||||
} |
||||
|
||||
/** |
||||
* Copies single property to the destination. |
||||
* Exceptions are ignored, so copying continues if |
||||
* destination does not have some of the sources properties. |
||||
*/ |
||||
@Override |
||||
protected boolean visitProperty(String name, final Object value) { |
||||
if (isTargetMap) { |
||||
name = LEFT_SQ_BRACKET + name + RIGHT_SQ_BRACKET; |
||||
} |
||||
|
||||
beanUtil.setProperty(destination, name, value); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
} |
@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.exception.UncheckedException; |
||||
|
||||
/** |
||||
* Unchecked bean exception. |
||||
*/ |
||||
public class BeanException extends UncheckedException { |
||||
|
||||
public BeanException(final Throwable t) { |
||||
super(t); |
||||
} |
||||
|
||||
public BeanException(final String message) { |
||||
super(message); |
||||
} |
||||
|
||||
public BeanException(final String message, final BeanProperty bp) { |
||||
super(message + ". Invalid property: " + bp); |
||||
} |
||||
|
||||
public BeanException(final String message, final Throwable t) { |
||||
super(message, t); |
||||
} |
||||
|
||||
public BeanException(final String message, final BeanProperty bp, final Throwable t) { |
||||
super(message + ". Invalid property: " + bp, t); |
||||
} |
||||
|
||||
} |
@ -1,150 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.introspector.ClassDescriptor; |
||||
import com.fr.third.jodd.introspector.ClassIntrospector; |
||||
import com.fr.third.jodd.introspector.Getter; |
||||
import com.fr.third.jodd.introspector.PropertyDescriptor; |
||||
import com.fr.third.jodd.introspector.Setter; |
||||
|
||||
import java.util.function.Supplier; |
||||
|
||||
/** |
||||
* Represents a bean named property. Contains two information: |
||||
* <ol> |
||||
* <li>Bean instance (and cached class descriptor)</li> |
||||
* <li>Property name</li> |
||||
* </ol> |
||||
* Used only internally by {@link BeanUtil} and similar utils. |
||||
*/ |
||||
class BeanProperty { |
||||
|
||||
BeanProperty(final BeanUtilBean beanUtilBean, final Object bean, final String propertyName) { |
||||
this.introspector = beanUtilBean.introspector; |
||||
setName(propertyName); |
||||
updateBean(bean); |
||||
this.last = true; |
||||
this.first = true; |
||||
this.fullName = bean.getClass().getSimpleName() + '#' + propertyName; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- bean and descriptor
|
||||
|
||||
final String fullName; // initial name
|
||||
final ClassIntrospector introspector; |
||||
Object bean; |
||||
private ClassDescriptor cd; |
||||
String name; // property name
|
||||
boolean last; // is it a last property (when nested)
|
||||
boolean first; // is it first property (when nested)
|
||||
String indexString; // indexString for index property
|
||||
|
||||
/** |
||||
* Sets current property name. |
||||
*/ |
||||
public void setName(final String name) { |
||||
this.name = name; |
||||
this.updateProperty = true; |
||||
} |
||||
|
||||
/** |
||||
* Sets new bean instance. |
||||
*/ |
||||
private void setBean(final Object bean) { |
||||
this.bean = bean; |
||||
this.cd = (bean == null ? null : introspector.lookup(bean.getClass())); |
||||
this.first = false; |
||||
this.updateProperty = true; |
||||
} |
||||
|
||||
/** |
||||
* Updates the bean. Detects special case of suppliers. |
||||
*/ |
||||
public void updateBean(final Object bean) { |
||||
this.setBean(bean); |
||||
|
||||
if (this.cd != null && this.cd.isSupplier()) { |
||||
final Object newBean = ((Supplier)this.bean).get(); |
||||
setBean(newBean); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- simple properties
|
||||
|
||||
// indicates that property descriptor has to be updated
|
||||
// since there was some property-related change of BeanProperty state
|
||||
private boolean updateProperty = true; |
||||
|
||||
// most recent property descriptor
|
||||
private PropertyDescriptor propertyDescriptor; |
||||
|
||||
/** |
||||
* Loads property descriptor, if property was updated. |
||||
*/ |
||||
private void loadPropertyDescriptor() { |
||||
if (updateProperty) { |
||||
if (cd == null) { |
||||
propertyDescriptor = null; |
||||
} else { |
||||
propertyDescriptor = cd.getPropertyDescriptor(name, true); |
||||
} |
||||
updateProperty = false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns getter. |
||||
*/ |
||||
public Getter getGetter(final boolean declared) { |
||||
loadPropertyDescriptor(); |
||||
return propertyDescriptor != null ? propertyDescriptor.getGetter(declared) : null; |
||||
} |
||||
|
||||
/** |
||||
* Returns setter. |
||||
*/ |
||||
public Setter getSetter(final boolean declared) { |
||||
loadPropertyDescriptor(); |
||||
return propertyDescriptor != null ? propertyDescriptor.getSetter(declared) : null; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if class is a map. |
||||
*/ |
||||
public boolean isMap() { |
||||
return cd != null && cd.isMap(); |
||||
} |
||||
|
||||
String index; |
||||
|
||||
// ---------------------------------------------------------------- toString
|
||||
|
||||
@Override |
||||
public String toString() { |
||||
return fullName + " (" + (bean != null ? bean.getClass().getSimpleName() : "?") + '#' + name + ')'; |
||||
} |
||||
} |
@ -1,60 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.template.ContextTemplateParser; |
||||
import com.fr.third.jodd.template.StringTemplateParser; |
||||
|
||||
/** |
||||
* Bean template is a string template with JSP-alike |
||||
* macros for injecting context values. |
||||
* This is a parser for such bean templates. |
||||
* <p> |
||||
* Once set, <code>BeanTemplateParser</code> instance is reusable |
||||
* as it doesn't store any parsing state. |
||||
* <p> |
||||
* Based on {@link StringTemplateParser}. |
||||
*/ |
||||
public class BeanTemplateParser extends StringTemplateParser { |
||||
|
||||
/** |
||||
* Creates bean-backed <code>MacroResolver</code>. |
||||
*/ |
||||
public ContextTemplateParser of(final Object context) { |
||||
return template -> parseWithBean(template, context); |
||||
} |
||||
|
||||
public String parseWithBean(final String template, final Object context) { |
||||
return super.parse(template, macroName -> { |
||||
Object value = BeanUtil.declaredSilent.getProperty(context, macroName); |
||||
|
||||
if (value == null) { |
||||
return null; |
||||
} |
||||
return value.toString(); |
||||
}); |
||||
} |
||||
} |
@ -1,154 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
/** |
||||
* Supreme utility for reading and writing bean properties. However, this one is the fastest available. |
||||
* Although it provides various methods, the whole thing can be easily extended to match most needs. |
||||
* <p> |
||||
* BeanUtil supports: |
||||
* <ul> |
||||
* <li>Nested properties: separated by a dot ('.')</li> |
||||
* <li>Indexed properties: arrays or Lists</li> |
||||
* <li>Simple properties: accessor or Map</li> |
||||
* </ul> |
||||
* |
||||
* <p> |
||||
* Variants includes combinations of forced, declared and silent writing. |
||||
* <ul> |
||||
* <li><i>Forced</i> setting property tries to create destination property so it can be set correctly.</li> |
||||
* <li><i>Silent</i> doesn't throw an exception if destination doesn't exist or if conversion fails.</li> |
||||
* <li><i>Declared</i> includes only declared (public) properties.</li> |
||||
* </ul> |
||||
* <p> |
||||
* This utility considers both bean property methods (set and get accessors), and bean fields. |
||||
* This is done because of several reasons: often there is no need for both set/get accessors, since |
||||
* bean logic requires just one functionality (e.g. just reading). In such case, other bean manipulation |
||||
* libraries still requires to have both accessors in order to set or get value. |
||||
* Another reason is that most common usage is to work with public accessors, and in that case |
||||
* private fields are ignored. |
||||
*/ |
||||
public interface BeanUtil { |
||||
|
||||
/** |
||||
* Default instance of {@link BeanUtilBean}. |
||||
*/ |
||||
BeanUtil pojo = new BeanUtilBean(); |
||||
|
||||
BeanUtil declared = new BeanUtilBean().declared(true); |
||||
|
||||
BeanUtil silent = new BeanUtilBean().silent(true); |
||||
|
||||
BeanUtil forced = new BeanUtilBean().forced(true); |
||||
|
||||
BeanUtil declaredSilent = new BeanUtilBean().declared(true).silent(true); |
||||
|
||||
BeanUtil declaredForced = new BeanUtilBean().declared(true).forced(true); |
||||
|
||||
BeanUtil declaredForcedSilent = new BeanUtilBean().declared(true).forced(true).silent(true); |
||||
|
||||
BeanUtil forcedSilent = new BeanUtilBean().forced(true).silent(true); |
||||
|
||||
// ---------------------------------------------------------------- SET
|
||||
|
||||
/** |
||||
* Sets Java Bean property. |
||||
* @param bean Java POJO bean or a Map |
||||
* @param name property name |
||||
* @param value property value |
||||
*/ |
||||
void setProperty(Object bean, String name, Object value); |
||||
|
||||
/** |
||||
* Sets indexed property. |
||||
*/ |
||||
void setIndexProperty(Object bean, String property, int index, Object value); |
||||
|
||||
/** |
||||
* Sets simple property. |
||||
*/ |
||||
void setSimpleProperty(Object bean, String property, Object value); |
||||
|
||||
|
||||
// ---------------------------------------------------------------- GET
|
||||
|
||||
/** |
||||
* Returns value of bean's property. |
||||
* <p> |
||||
* In silent mode, returning of <code>null</code> is ambiguous: it may means that property name |
||||
* is valid and property value is <code>null</code> or that property name is invalid. |
||||
* <p> |
||||
* Using forced mode does not have any influence on the result. |
||||
*/ |
||||
<T> T getProperty(Object bean, String name); |
||||
|
||||
/** |
||||
* Returns value of indexed property. |
||||
*/ |
||||
<T> T getIndexProperty(Object bean, String property, int index); |
||||
|
||||
/** |
||||
* Reads simple property. |
||||
*/ |
||||
<T> T getSimpleProperty(Object bean, String property); |
||||
|
||||
|
||||
// ---------------------------------------------------------------- HAS
|
||||
|
||||
/** |
||||
* Returns <code>true</code> if bean has a property. |
||||
*/ |
||||
boolean hasProperty(Object bean, String name); |
||||
|
||||
/** |
||||
* Returns <code>true</code> if bean has only a root property. |
||||
* If yes, this means that property may be injected into the bean. |
||||
* If not, bean does not contain the property. |
||||
*/ |
||||
boolean hasRootProperty(Object bean, String name); |
||||
|
||||
/** |
||||
* Returns <code>true</code> if simple property exist. |
||||
*/ |
||||
boolean hasSimpleProperty(Object bean, String property); |
||||
|
||||
|
||||
// ---------------------------------------------------------------- type
|
||||
|
||||
/** |
||||
* Returns property type. |
||||
*/ |
||||
Class<?> getPropertyType(Object bean, String name); |
||||
|
||||
|
||||
// ---------------------------------------------------------------- misc
|
||||
|
||||
/** |
||||
* Returns the very first name chunk of the property. |
||||
*/ |
||||
public String extractThisReference(String propertyName); |
||||
|
||||
} |
@ -1,559 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.introspector.Getter; |
||||
import com.fr.third.jodd.introspector.Setter; |
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
import com.fr.third.jodd.util.StringUtil; |
||||
|
||||
import java.lang.reflect.Array; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Instantiable version of {@link BeanUtil}. |
||||
*/ |
||||
public class BeanUtilBean extends BeanUtilUtil implements BeanUtil { |
||||
|
||||
/** |
||||
* Sets the declared flag. |
||||
*/ |
||||
public BeanUtilBean declared(final boolean declared) { |
||||
this.isDeclared = declared; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets the forced flag. |
||||
*/ |
||||
public BeanUtilBean forced(final boolean forced) { |
||||
this.isForced = forced; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets the silent flag. |
||||
*/ |
||||
public BeanUtilBean silent(final boolean silent) { |
||||
this.isSilent = silent; |
||||
return this; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- internal resolver
|
||||
|
||||
/** |
||||
* Resolves nested property name to the very last indexed property. |
||||
* If forced, <code>null</code> or non-existing properties will be created. |
||||
*/ |
||||
protected void resolveNestedProperties(final BeanProperty bp) { |
||||
String name = bp.name; |
||||
int dotNdx; |
||||
while ((dotNdx = indexOfDot(name)) != -1) { |
||||
bp.last = false; |
||||
bp.setName(name.substring(0, dotNdx)); |
||||
bp.updateBean(getIndexProperty(bp)); |
||||
name = name.substring(dotNdx + 1); |
||||
} |
||||
bp.last = true; |
||||
bp.setName(name); |
||||
} |
||||
|
||||
protected boolean resolveExistingNestedProperties(final BeanProperty bp) { |
||||
String name = bp.name; |
||||
int dotNdx; |
||||
while ((dotNdx = indexOfDot(name)) != -1) { |
||||
bp.last = false; |
||||
bp.setName(name.substring(0, dotNdx)); |
||||
final String temp = bp.name; |
||||
if (!hasIndexProperty(bp)) { |
||||
return false; |
||||
} |
||||
bp.setName(temp); |
||||
bp.updateBean(getIndexProperty(bp)); |
||||
name = name.substring(dotNdx + 1); |
||||
} |
||||
bp.last = true; |
||||
bp.setName(name); |
||||
return true; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- simple property
|
||||
|
||||
@Override |
||||
public boolean hasSimpleProperty(final Object bean, final String property) { |
||||
return hasSimpleProperty(new BeanProperty(this, bean, property)); |
||||
} |
||||
|
||||
protected boolean hasSimpleProperty(final BeanProperty bp) { |
||||
if (bp.bean == null) { |
||||
return false; |
||||
} |
||||
|
||||
// try: getter
|
||||
final Getter getter = bp.getGetter(isDeclared); |
||||
if (getter != null) { |
||||
return true; |
||||
} |
||||
|
||||
// try: (Map) get("property")
|
||||
if (bp.isMap()) { |
||||
Map map = (Map) bp.bean; |
||||
if (map.containsKey(bp.name)) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public <T> T getSimpleProperty(final Object bean, final String property) { |
||||
return (T) getSimpleProperty(new BeanProperty(this, bean, property)); |
||||
} |
||||
|
||||
protected Object getSimpleProperty(final BeanProperty bp) { |
||||
|
||||
if (bp.name.length() == 0) { |
||||
if (bp.indexString != null) { |
||||
// index string exist, but property name is missing
|
||||
return bp.bean; |
||||
} |
||||
throw new BeanException("Invalid property", bp); |
||||
} |
||||
|
||||
Getter getter = bp.getGetter(isDeclared); |
||||
|
||||
if (getter != null) { |
||||
Object result; |
||||
try { |
||||
result = getter.invokeGetter(bp.bean); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Getter failed: " + getter, ex); |
||||
} |
||||
|
||||
if ((result == null) && (isForced)) { |
||||
result = createBeanProperty(bp); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
// try: (Map) get("property")
|
||||
if (bp.isMap()) { |
||||
Map map = (Map) bp.bean; |
||||
Object key = convertIndexToMapKey(getter, bp.name); |
||||
|
||||
if (!map.containsKey(key)) { |
||||
if (!isForced) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Map key not found: " + bp.name, bp); |
||||
} |
||||
Map value = new HashMap(); |
||||
//noinspection unchecked
|
||||
map.put(key, value); |
||||
return value; |
||||
} |
||||
return map.get(key); |
||||
} |
||||
|
||||
// failed
|
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Simple property not found: " + bp.name, bp); |
||||
} |
||||
|
||||
@Override |
||||
public void setSimpleProperty(final Object bean, final String property, final Object value) { |
||||
setSimpleProperty(new BeanProperty(this, bean, property), value); |
||||
} |
||||
|
||||
/** |
||||
* Sets a value of simple property. |
||||
*/ |
||||
@SuppressWarnings({"unchecked"}) |
||||
protected void setSimpleProperty(final BeanProperty bp, final Object value) { |
||||
Setter setter = bp.getSetter(isDeclared); |
||||
|
||||
// try: setter
|
||||
if (setter != null) { |
||||
invokeSetter(setter, bp, value); |
||||
return; |
||||
} |
||||
|
||||
// try: put("property", value)
|
||||
if (bp.isMap()) { |
||||
((Map) bp.bean).put(bp.name, value); |
||||
return; |
||||
} |
||||
if (isSilent) { |
||||
return; |
||||
} |
||||
throw new BeanException("Simple property not found: " + bp.name, bp); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- indexed property
|
||||
|
||||
protected boolean hasIndexProperty(final BeanProperty bp) { |
||||
|
||||
if (bp.bean == null) { |
||||
return false; |
||||
} |
||||
String indexString = extractIndex(bp); |
||||
|
||||
if (indexString == null) { |
||||
return hasSimpleProperty(bp); |
||||
} |
||||
|
||||
Object resultBean = getSimpleProperty(bp); |
||||
|
||||
if (resultBean == null) { |
||||
return false; |
||||
} |
||||
|
||||
// try: property[index]
|
||||
if (resultBean.getClass().isArray()) { |
||||
int index = parseInt(indexString, bp); |
||||
return (index >= 0) && (index < Array.getLength(resultBean)); |
||||
} |
||||
|
||||
// try: list.get(index)
|
||||
if (resultBean instanceof List) { |
||||
int index = parseInt(indexString, bp); |
||||
return (index >= 0) && (index < ((List)resultBean).size()); |
||||
} |
||||
if (resultBean instanceof Map) { |
||||
return ((Map)resultBean).containsKey(indexString); |
||||
} |
||||
|
||||
// failed
|
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public <T> T getIndexProperty(final Object bean, final String property, final int index) { |
||||
BeanProperty bp = new BeanProperty(this, bean, property); |
||||
|
||||
bp.indexString = bp.index = String.valueOf(index); |
||||
|
||||
Object value = _getIndexProperty(bp); |
||||
|
||||
bp.indexString = null; |
||||
|
||||
return (T) value; |
||||
} |
||||
|
||||
/** |
||||
* Get non-nested property value: either simple or indexed property. |
||||
* If forced, missing bean will be created if possible. |
||||
*/ |
||||
protected Object getIndexProperty(final BeanProperty bp) { |
||||
bp.indexString = extractIndex(bp); |
||||
|
||||
Object value = _getIndexProperty(bp); |
||||
|
||||
bp.indexString = null; |
||||
|
||||
return value; |
||||
} |
||||
|
||||
private Object _getIndexProperty(final BeanProperty bp) { |
||||
Object resultBean = getSimpleProperty(bp); |
||||
Getter getter = bp.getGetter(isDeclared); |
||||
|
||||
if (bp.indexString == null) { |
||||
return resultBean; // no index, just simple bean
|
||||
} |
||||
if (resultBean == null) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Index property is null: " + bp.name, bp); |
||||
} |
||||
|
||||
// try: property[index]
|
||||
if (resultBean.getClass().isArray()) { |
||||
int index = parseInt(bp.indexString, bp); |
||||
if (isForced) { |
||||
return arrayForcedGet(bp, resultBean, index); |
||||
} else { |
||||
return Array.get(resultBean, index); |
||||
} |
||||
} |
||||
|
||||
// try: list.get(index)
|
||||
if (resultBean instanceof List) { |
||||
int index = parseInt(bp.indexString, bp); |
||||
List list = (List) resultBean; |
||||
if (!isForced) { |
||||
return list.get(index); |
||||
} |
||||
if (!bp.last) { |
||||
ensureListSize(list, index); |
||||
} |
||||
Object value = list.get(index); |
||||
if (value == null) { |
||||
Class listComponentType = extractGenericComponentType(getter); |
||||
if (listComponentType == Object.class) { |
||||
// not an error: when component type is unknown, use Map as generic bean
|
||||
listComponentType = Map.class; |
||||
} |
||||
try { |
||||
value = ClassUtil.newInstance(listComponentType); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Invalid list element: " + bp.name + '[' + index + ']', bp, ex); |
||||
} |
||||
//noinspection unchecked
|
||||
list.set(index, value); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
// try: map.get('index')
|
||||
if (resultBean instanceof Map) { |
||||
Map map = (Map) resultBean; |
||||
Object key = convertIndexToMapKey(getter, bp.indexString); |
||||
|
||||
if (!isForced) { |
||||
return map.get(key); |
||||
} |
||||
Object value = map.get(key); |
||||
if (!bp.last) { |
||||
if (value == null) { |
||||
Class mapComponentType = extractGenericComponentType(getter); |
||||
if (mapComponentType == Object.class) { |
||||
mapComponentType = Map.class; |
||||
} |
||||
try { |
||||
value = ClassUtil.newInstance(mapComponentType); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Invalid map element: " + bp.name + '[' + bp.indexString + ']', bp, ex); |
||||
} |
||||
|
||||
//noinspection unchecked
|
||||
map.put(key, value); |
||||
} |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
// failed
|
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Index property is not an array, list or map: " + bp.name, bp); |
||||
} |
||||
|
||||
@Override |
||||
public void setIndexProperty(final Object bean, final String property, final int index, final Object value) { |
||||
BeanProperty bp = new BeanProperty(this, bean, property); |
||||
|
||||
bp.indexString = bp.index = String.valueOf(index); |
||||
|
||||
_setIndexProperty(bp, value); |
||||
|
||||
bp.indexString = null; |
||||
} |
||||
|
||||
/** |
||||
* Sets indexed or regular properties (no nested!). |
||||
*/ |
||||
protected void setIndexProperty(final BeanProperty bp, final Object value) { |
||||
bp.indexString = extractIndex(bp); |
||||
|
||||
_setIndexProperty(bp, value); |
||||
|
||||
bp.indexString = null; |
||||
} |
||||
|
||||
@SuppressWarnings({"unchecked"}) |
||||
private void _setIndexProperty(final BeanProperty bp, Object value) { |
||||
if (bp.indexString == null) { |
||||
setSimpleProperty(bp, value); |
||||
return; |
||||
} |
||||
|
||||
// try: getInner()
|
||||
Object nextBean = getSimpleProperty(bp); |
||||
Getter getter = bp.getGetter(isDeclared); |
||||
|
||||
if (nextBean == null) { |
||||
if (isSilent) { |
||||
return; |
||||
} |
||||
throw new BeanException("Index property is null:" + bp.name, bp); |
||||
} |
||||
|
||||
// inner bean found
|
||||
if (nextBean.getClass().isArray()) { |
||||
int index = parseInt(bp.indexString, bp); |
||||
if (isForced) { |
||||
arrayForcedSet(bp, nextBean, index, value); |
||||
} else { |
||||
Array.set(nextBean, index, value); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
if (nextBean instanceof List) { |
||||
int index = parseInt(bp.indexString, bp); |
||||
Class listComponentType = extractGenericComponentType(getter); |
||||
if (listComponentType != Object.class) { |
||||
value = convertType(value, listComponentType); |
||||
} |
||||
List list = (List) nextBean; |
||||
if (isForced) { |
||||
ensureListSize(list, index); |
||||
} |
||||
list.set(index, value); |
||||
return; |
||||
} |
||||
if (nextBean instanceof Map) { |
||||
Map map = (Map) nextBean; |
||||
Object key = convertIndexToMapKey(getter, bp.indexString); |
||||
|
||||
Class mapComponentType = extractGenericComponentType(getter); |
||||
if (mapComponentType != Object.class) { |
||||
value = convertType(value, mapComponentType); |
||||
} |
||||
map.put(key, value); |
||||
return; |
||||
} |
||||
|
||||
// failed
|
||||
if (isSilent) { |
||||
return; |
||||
} |
||||
throw new BeanException("Index property is not an array, list or map: " + bp.name, bp); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- SET
|
||||
|
||||
@Override |
||||
public void setProperty(final Object bean, final String name, final Object value) { |
||||
BeanProperty beanProperty = new BeanProperty(this, bean, name); |
||||
|
||||
if (!isSilent) { |
||||
resolveNestedProperties(beanProperty); |
||||
setIndexProperty(beanProperty, value); |
||||
} |
||||
else { |
||||
try { |
||||
resolveNestedProperties(beanProperty); |
||||
setIndexProperty(beanProperty, value); |
||||
} |
||||
catch (Exception ignore) {} |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- GET
|
||||
|
||||
/** |
||||
* Returns value of bean's property. |
||||
*/ |
||||
@Override |
||||
public <T> T getProperty(final Object bean, final String name) { |
||||
BeanProperty beanProperty = new BeanProperty(this, bean, name); |
||||
if (!isSilent) { |
||||
resolveNestedProperties(beanProperty); |
||||
return (T) getIndexProperty(beanProperty); |
||||
} |
||||
else { |
||||
try { |
||||
resolveNestedProperties(beanProperty); |
||||
return (T) getIndexProperty(beanProperty); |
||||
} |
||||
catch (Exception ignore) { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- HAS
|
||||
|
||||
@Override |
||||
public boolean hasProperty(final Object bean, final String name) { |
||||
BeanProperty beanProperty = new BeanProperty(this, bean, name); |
||||
if (!resolveExistingNestedProperties(beanProperty)) { |
||||
return false; |
||||
} |
||||
return hasIndexProperty(beanProperty); |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasRootProperty(final Object bean, String name) { |
||||
int dotNdx = indexOfDot(name); |
||||
if (dotNdx != -1) { |
||||
name = name.substring(0, dotNdx); |
||||
} |
||||
BeanProperty beanProperty = new BeanProperty(this, bean, name); |
||||
extractIndex(beanProperty); |
||||
return hasSimpleProperty(beanProperty); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- type
|
||||
|
||||
@Override |
||||
public Class<?> getPropertyType(final Object bean, final String name) { |
||||
BeanProperty beanProperty = new BeanProperty(this, bean, name); |
||||
if (!resolveExistingNestedProperties(beanProperty)) { |
||||
return null; |
||||
} |
||||
hasIndexProperty(beanProperty); |
||||
return extractType(beanProperty); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- utilities
|
||||
|
||||
private static final char[] INDEX_CHARS = new char[] {'.', '['}; |
||||
|
||||
/** |
||||
* Extract the first name of this reference. |
||||
*/ |
||||
@Override |
||||
public String extractThisReference(final String propertyName) { |
||||
int ndx = StringUtil.indexOfChars(propertyName, INDEX_CHARS); |
||||
if (ndx == -1) { |
||||
return propertyName; |
||||
} |
||||
return propertyName.substring(0, ndx); |
||||
} |
||||
|
||||
} |
@ -1,346 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.introspector.ClassIntrospector; |
||||
import com.fr.third.jodd.introspector.Getter; |
||||
import com.fr.third.jodd.introspector.MapperFunction; |
||||
import com.fr.third.jodd.introspector.Setter; |
||||
import com.fr.third.jodd.typeconverter.TypeConverterManager; |
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Array; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Various bean property utilities that makes writings of {@link BeanUtil} classes easy. |
||||
*/ |
||||
abstract class BeanUtilUtil implements BeanUtil { |
||||
|
||||
// ---------------------------------------------------------------- flags
|
||||
|
||||
protected boolean isDeclared = false; |
||||
protected boolean isForced = false; |
||||
protected boolean isSilent = false; |
||||
|
||||
// ---------------------------------------------------------------- introspector
|
||||
|
||||
protected ClassIntrospector introspector = ClassIntrospector.get(); |
||||
protected TypeConverterManager typeConverterManager = TypeConverterManager.get(); |
||||
|
||||
/** |
||||
* Sets {@link ClassIntrospector introspector} implementation. |
||||
*/ |
||||
public void setIntrospector(final ClassIntrospector introspector) { |
||||
this.introspector = introspector; |
||||
} |
||||
|
||||
/** |
||||
* Sets {@link TypeConverterManager type converter manager} implementation. |
||||
*/ |
||||
public void setTypeConverterManager(final TypeConverterManager typeConverterManager) { |
||||
this.typeConverterManager = typeConverterManager; |
||||
} |
||||
|
||||
/** |
||||
* Converts object to destination type. Invoked before the |
||||
* value is set into destination. Throws <code>TypeConversionException</code> |
||||
* if conversion fails. |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
protected Object convertType(final Object value, final Class type) { |
||||
return typeConverterManager.convertType(value, type); |
||||
} |
||||
|
||||
/** |
||||
* Converter to collection. |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
protected Object convertToCollection(final Object value, final Class destinationType, final Class componentType) { |
||||
return typeConverterManager.convertToCollection(value, destinationType, componentType); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- accessors
|
||||
|
||||
/** |
||||
* Invokes setter, but first converts type to match the setter type. |
||||
*/ |
||||
protected Object invokeSetter(final Setter setter, final BeanProperty bp, Object value) { |
||||
try { |
||||
|
||||
final MapperFunction setterMapperFunction = setter.getMapperFunction(); |
||||
|
||||
if (setterMapperFunction != null) { |
||||
value = setterMapperFunction.apply(value); |
||||
} |
||||
|
||||
final Class type = setter.getSetterRawType(); |
||||
|
||||
if (ClassUtil.isTypeOf(type, Collection.class)) { |
||||
Class componentType = setter.getSetterRawComponentType(); |
||||
|
||||
value = convertToCollection(value, type, componentType); |
||||
} else { |
||||
// no collections
|
||||
value = convertType(value, type); |
||||
} |
||||
|
||||
setter.invokeSetter(bp.bean, value); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Setter failed: " + setter, ex); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- forced
|
||||
|
||||
/** |
||||
* Returns the element of an array forced. If value is <code>null</code>, it will be instantiated. |
||||
* If not the last part of indexed bean property, array will be expanded to the index if necessary. |
||||
*/ |
||||
protected Object arrayForcedGet(final BeanProperty bp, Object array, final int index) { |
||||
Class componentType = array.getClass().getComponentType(); |
||||
if (!bp.last) { |
||||
array = ensureArraySize(bp, array, componentType, index); |
||||
} |
||||
Object value = Array.get(array, index); |
||||
if (value == null) { |
||||
try { |
||||
//noinspection unchecked
|
||||
value = ClassUtil.newInstance(componentType); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Invalid array element: " + bp.name + '[' + index + ']', bp, ex); |
||||
} |
||||
Array.set(array, index, value); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
/** |
||||
* Sets the array element forced. If index is greater then arrays length, array will be expanded to the index. |
||||
* If speed is critical, it is better to allocate an array with proper size before using this method. |
||||
*/ |
||||
protected void arrayForcedSet(final BeanProperty bp, Object array, final int index, Object value) { |
||||
Class componentType = array.getClass().getComponentType(); |
||||
array = ensureArraySize(bp, array, componentType, index); |
||||
value = convertType(value, componentType); |
||||
Array.set(array, index, value); |
||||
} |
||||
|
||||
|
||||
@SuppressWarnings({"SuspiciousSystemArraycopy"}) |
||||
protected Object ensureArraySize(final BeanProperty bp, Object array, final Class componentType, final int index) { |
||||
int len = Array.getLength(array); |
||||
if (index >= len) { |
||||
Object newArray = Array.newInstance(componentType, index + 1); |
||||
System.arraycopy(array, 0, newArray, 0, len); |
||||
|
||||
Setter setter = bp.getSetter(true); |
||||
if (setter == null) { |
||||
// no point to check for bp.silent, throws NPE later
|
||||
throw new BeanException("Setter or field not found: " + bp.name, bp); |
||||
} |
||||
|
||||
newArray = invokeSetter(setter, bp, newArray); |
||||
|
||||
array = newArray; |
||||
} |
||||
return array; |
||||
} |
||||
|
||||
@SuppressWarnings({"unchecked"}) |
||||
protected void ensureListSize(final List list, final int size) { |
||||
int len = list.size(); |
||||
while (size >= len) { |
||||
list.add(null); |
||||
len++; |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- index
|
||||
|
||||
/** |
||||
* Finds the very first next dot. Ignores dots between index brackets. |
||||
* Returns <code>-1</code> when dot is not found. |
||||
*/ |
||||
protected int indexOfDot(final String name) { |
||||
int ndx = 0; |
||||
int len = name.length(); |
||||
|
||||
boolean insideBracket = false; |
||||
|
||||
while (ndx < len) { |
||||
char c = name.charAt(ndx); |
||||
|
||||
if (insideBracket) { |
||||
if (c == ']') { |
||||
insideBracket = false; |
||||
} |
||||
} else { |
||||
if (c == '.') { |
||||
return ndx; |
||||
} |
||||
if (c == '[') { |
||||
insideBracket = true; |
||||
} |
||||
} |
||||
ndx++; |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Extract index string from non-nested property name. |
||||
* If index is found, it is stripped from bean property name. |
||||
* If no index is found, it returns <code>null</code>. |
||||
*/ |
||||
protected String extractIndex(final BeanProperty bp) { |
||||
bp.index = null; |
||||
String name = bp.name; |
||||
int lastNdx = name.length() - 1; |
||||
if (lastNdx < 0) { |
||||
return null; |
||||
} |
||||
if (name.charAt(lastNdx) == ']') { |
||||
int leftBracketNdx = name.lastIndexOf('['); |
||||
if (leftBracketNdx != -1) { |
||||
bp.setName(name.substring(0, leftBracketNdx)); |
||||
bp.index = name.substring(leftBracketNdx + 1, lastNdx); |
||||
return bp.index; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
protected int parseInt(final String indexString, final BeanProperty bp) { |
||||
try { |
||||
return Integer.parseInt(indexString); |
||||
} catch (NumberFormatException nfex) { |
||||
// no point to use bp.silent, as will throw exception
|
||||
throw new BeanException("Invalid index: " + indexString, bp, nfex); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- create property
|
||||
|
||||
/** |
||||
* Creates new instance for current property name through its setter. |
||||
* It uses default constructor! |
||||
*/ |
||||
protected Object createBeanProperty(final BeanProperty bp) { |
||||
Setter setter = bp.getSetter(true); |
||||
if (setter == null) { |
||||
return null; |
||||
} |
||||
|
||||
Class type = setter.getSetterRawType(); |
||||
|
||||
Object newInstance; |
||||
try { |
||||
newInstance = ClassUtil.newInstance(type); |
||||
} catch (Exception ex) { |
||||
if (isSilent) { |
||||
return null; |
||||
} |
||||
throw new BeanException("Invalid property: " + bp.name, bp, ex); |
||||
} |
||||
|
||||
newInstance = invokeSetter(setter, bp, newInstance); |
||||
|
||||
return newInstance; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- generic and type
|
||||
|
||||
/** |
||||
* Extracts generic component type of a property. Returns <code>Object.class</code> |
||||
* when property does not have component. |
||||
*/ |
||||
protected Class extractGenericComponentType(final Getter getter) { |
||||
Class componentType = null; |
||||
|
||||
if (getter != null) { |
||||
componentType = getter.getGetterRawComponentType(); |
||||
} |
||||
|
||||
if (componentType == null) { |
||||
componentType = Object.class; |
||||
} |
||||
return componentType; |
||||
} |
||||
|
||||
/** |
||||
* Converts <b>Map</b> index to key type. If conversion fails, original value will be returned. |
||||
*/ |
||||
protected Object convertIndexToMapKey(final Getter getter, final Object index) { |
||||
Class indexType = null; |
||||
|
||||
if (getter != null) { |
||||
indexType = getter.getGetterRawKeyComponentType(); |
||||
} |
||||
|
||||
// check if set
|
||||
if (indexType == null) { |
||||
indexType = Object.class; // marker for no generic type
|
||||
} |
||||
|
||||
if (indexType == Object.class) { |
||||
return index; |
||||
} |
||||
|
||||
try { |
||||
return convertType(index, indexType); |
||||
} catch (Exception ignore) { |
||||
return index; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Extracts type of current property. |
||||
*/ |
||||
protected Class extractType(final BeanProperty bp) { |
||||
Getter getter = bp.getGetter(isDeclared); |
||||
if (getter != null) { |
||||
if (bp.index != null) { |
||||
Class type = getter.getGetterRawComponentType(); |
||||
return type == null ? Object.class : type; |
||||
} |
||||
return getter.getGetterRawType(); |
||||
} |
||||
|
||||
return null; // this should not happens
|
||||
} |
||||
|
||||
} |
@ -1,194 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import com.fr.third.jodd.inex.InExRuleMatcher; |
||||
import com.fr.third.jodd.inex.InExRules; |
||||
import com.fr.third.jodd.introspector.ClassDescriptor; |
||||
import com.fr.third.jodd.introspector.ClassIntrospector; |
||||
import com.fr.third.jodd.introspector.FieldDescriptor; |
||||
import com.fr.third.jodd.introspector.MethodDescriptor; |
||||
import com.fr.third.jodd.introspector.PropertyDescriptor; |
||||
import com.fr.third.jodd.util.StringUtil; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import static com.fr.third.jodd.util.StringPool.LEFT_SQ_BRACKET; |
||||
import static com.fr.third.jodd.util.StringPool.RIGHT_SQ_BRACKET; |
||||
|
||||
/** |
||||
* Visitor for bean properties. It extracts properties names |
||||
* from the source bean and then visits one by one. |
||||
* |
||||
* @see BeanVisitorImplBase |
||||
*/ |
||||
public abstract class BeanVisitor implements InExRuleMatcher<String, String> { |
||||
|
||||
/** |
||||
* Source bean. |
||||
*/ |
||||
protected Object source; |
||||
/** |
||||
* Include/exclude rules. |
||||
*/ |
||||
protected InExRules<String, String, String> rules = new InExRules<>(this); |
||||
/** |
||||
* Flag for enabling declared properties, or just public ones. |
||||
*/ |
||||
protected boolean declared; |
||||
/** |
||||
* Defines if null values should be ignored. |
||||
*/ |
||||
protected boolean ignoreNullValues; |
||||
/** |
||||
* Defines if empty string should be ignored. |
||||
*/ |
||||
protected boolean ignoreEmptyString; |
||||
/** |
||||
* Defines if fields should be included. |
||||
*/ |
||||
protected boolean includeFields; |
||||
/** |
||||
* Initial matching mode. |
||||
*/ |
||||
protected boolean blacklist = true; |
||||
/** |
||||
* Indicates the the source is a Map. |
||||
*/ |
||||
protected boolean isSourceMap = false; |
||||
|
||||
// ---------------------------------------------------------------- util
|
||||
|
||||
/** |
||||
* Returns all bean property names. |
||||
*/ |
||||
protected String[] getAllBeanPropertyNames(final Class type, final boolean declared) { |
||||
final ClassDescriptor classDescriptor = ClassIntrospector.get().lookup(type); |
||||
|
||||
final PropertyDescriptor[] propertyDescriptors = classDescriptor.getAllPropertyDescriptors(); |
||||
|
||||
final ArrayList<String> names = new ArrayList<>(propertyDescriptors.length); |
||||
|
||||
for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) { |
||||
final MethodDescriptor getter = propertyDescriptor.getReadMethodDescriptor(); |
||||
if (getter != null) { |
||||
if (getter.matchDeclared(declared)) { |
||||
names.add(propertyDescriptor.getName()); |
||||
} |
||||
} |
||||
else if (includeFields) { |
||||
final FieldDescriptor field = propertyDescriptor.getFieldDescriptor(); |
||||
if (field != null) { |
||||
if (field.matchDeclared(declared)) { |
||||
names.add(field.getName()); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
return names.toArray(new String[0]); |
||||
} |
||||
|
||||
/** |
||||
* Returns an array of bean properties. If bean is a <code>Map</code>, |
||||
* all its keys will be returned. |
||||
*/ |
||||
protected String[] resolveProperties(final Object bean, final boolean declared) { |
||||
final String[] properties; |
||||
|
||||
if (bean instanceof Map) { |
||||
final Set keys = ((Map) bean).keySet(); |
||||
|
||||
properties = new String[keys.size()]; |
||||
int ndx = 0; |
||||
for (final Object key : keys) { |
||||
properties[ndx] = key.toString(); |
||||
ndx++; |
||||
} |
||||
} else { |
||||
properties = getAllBeanPropertyNames(bean.getClass(), declared); |
||||
} |
||||
|
||||
return properties; |
||||
} |
||||
|
||||
/** |
||||
* Starts visiting properties. |
||||
*/ |
||||
public void visit() { |
||||
final String[] properties = resolveProperties(source, declared); |
||||
|
||||
for (final String name : properties) { |
||||
if (name == null) { |
||||
continue; |
||||
} |
||||
|
||||
if (!rules.match(name, blacklist)) { |
||||
continue; |
||||
} |
||||
|
||||
final Object value; |
||||
|
||||
String propertyName = name; |
||||
|
||||
if (isSourceMap) { |
||||
propertyName = LEFT_SQ_BRACKET + name + RIGHT_SQ_BRACKET; |
||||
} |
||||
|
||||
if (declared) { |
||||
value = BeanUtil.declared.getProperty(source, propertyName); |
||||
} else { |
||||
value = BeanUtil.pojo.getProperty(source, propertyName); |
||||
} |
||||
|
||||
if (value == null && ignoreNullValues) { |
||||
continue; |
||||
} |
||||
|
||||
if (ignoreEmptyString && value instanceof String && StringUtil.isEmpty((String) value)) { |
||||
continue; |
||||
} |
||||
|
||||
visitProperty(name, value); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Invoked for each visited property. Returns <code>true</code> if |
||||
* visiting should continue, otherwise <code>false</code> to stop. |
||||
*/ |
||||
protected abstract boolean visitProperty(String name, Object value); |
||||
|
||||
/** |
||||
* Compares property name to the rules. |
||||
*/ |
||||
@Override |
||||
public boolean accept(final String propertyName, final String rule, final boolean include) { |
||||
return propertyName.equals(rule); |
||||
} |
||||
} |
@ -1,131 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
/** |
||||
* Default implementation of {@link BeanVisitor} for just setting |
||||
* the properties in fluent way. |
||||
*/ |
||||
public abstract class BeanVisitorImplBase<T> extends BeanVisitor { |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
protected T _this() { |
||||
return (T) this; |
||||
} |
||||
|
||||
/** |
||||
* Excludes all properties, i.e. enables blacklist mode. |
||||
*/ |
||||
public T excludeAll() { |
||||
blacklist = false; |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines excluded property names. |
||||
*/ |
||||
public T exclude(final String... excludes) { |
||||
for (String ex : excludes) { |
||||
rules.exclude(ex); |
||||
} |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Exclude a property. |
||||
*/ |
||||
public T exclude(final String exclude) { |
||||
rules.exclude(exclude); |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines included property names. |
||||
*/ |
||||
public T include(final String... includes) { |
||||
for (String in : includes) { |
||||
rules.include(in); |
||||
} |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Include a property. |
||||
*/ |
||||
public T include(final String include) { |
||||
rules.include(include); |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines included property names as public properties |
||||
* of given template class. Sets to black list mode. |
||||
*/ |
||||
public T includeAs(final Class template) { |
||||
blacklist = false; |
||||
|
||||
String[] properties = getAllBeanPropertyNames(template, false); |
||||
|
||||
include(properties); |
||||
|
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines if <code>null</code> values should be ignored. |
||||
*/ |
||||
public T ignoreNulls(final boolean ignoreNulls) { |
||||
this.ignoreNullValues = ignoreNulls; |
||||
|
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines if <code>empty string</code> should be ignored. |
||||
*/ |
||||
public T ignoreEmptyString(final boolean ignoreEmptyString) { |
||||
this.ignoreEmptyString = ignoreEmptyString; |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines if all properties should be copied (when set to <code>true</code>) |
||||
* or only public (when set to <code>false</code>, default). |
||||
*/ |
||||
public T declared(final boolean declared) { |
||||
this.declared = declared; |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Defines if fields without getters should be copied too. |
||||
*/ |
||||
public T includeFields(final boolean includeFields) { |
||||
this.includeFields = includeFields; |
||||
return _this(); |
||||
} |
||||
|
||||
} |
@ -1,83 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.bean; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Walker over bean properties. |
||||
*/ |
||||
public class BeanWalker extends BeanVisitorImplBase<BeanWalker> { |
||||
|
||||
private final BeanWalkerCallback callback; |
||||
|
||||
/** |
||||
* Functional callback for walking. |
||||
*/ |
||||
public interface BeanWalkerCallback { |
||||
void visitProperty(String name, Object value); |
||||
} |
||||
|
||||
public BeanWalker(final BeanWalkerCallback callback) { |
||||
this.callback = callback; |
||||
} |
||||
|
||||
/** |
||||
* Static ctor. |
||||
*/ |
||||
public static BeanWalker walk(final BeanWalkerCallback callback) { |
||||
return new BeanWalker(callback); |
||||
} |
||||
|
||||
public void source(final Object source) { |
||||
this.source = source; |
||||
|
||||
isSourceMap = (source instanceof Map); |
||||
|
||||
visit(); |
||||
} |
||||
|
||||
public void bean(final Object bean) { |
||||
this.source = bean; |
||||
|
||||
visit(); |
||||
} |
||||
|
||||
public void map(final Map map) { |
||||
this.source = map; |
||||
|
||||
this.isSourceMap = true; |
||||
|
||||
visit(); |
||||
} |
||||
|
||||
@Override |
||||
protected boolean visitProperty(final String name, final Object value) { |
||||
callback.visitProperty(name, value); |
||||
return true; |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Java Bean utilities, provides <em>the fastest</em> bean manipulation. |
||||
*/ |
||||
package com.fr.third.jodd.bean; |
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code boolean} buffer. |
||||
*/ |
||||
public class FastBooleanBuffer { |
||||
|
||||
private boolean[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code boolean} buffer. The buffer capacity is |
||||
* initially 64 booleans, though its size increases if necessary. |
||||
*/ |
||||
public FastBooleanBuffer() { |
||||
this.buffer = new boolean[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code boolean} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastBooleanBuffer(final int size) { |
||||
this.buffer = new boolean[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code boolean} to buffer. |
||||
*/ |
||||
public void append(final boolean element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code boolean} array to buffer. |
||||
*/ |
||||
public FastBooleanBuffer append(final boolean[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code boolean} array to buffer. |
||||
*/ |
||||
public FastBooleanBuffer append(final boolean[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastBooleanBuffer append(final FastBooleanBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code boolean} array from buffered content. |
||||
*/ |
||||
public boolean[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code boolean} subarray from buffered content. |
||||
*/ |
||||
public boolean[] toArray(final int start, final int len) { |
||||
final boolean[] array = new boolean[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code boolean} element at given index. |
||||
*/ |
||||
public boolean get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code byte} buffer. Works faster for smaller buffer sizes. |
||||
* After eg. length of 2048 the performances are practically the same. |
||||
*/ |
||||
public class FastByteBuffer { |
||||
|
||||
private byte[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code byte} buffer. The buffer capacity is |
||||
* initially 64 bytes, though its size increases if necessary. |
||||
*/ |
||||
public FastByteBuffer() { |
||||
this.buffer = new byte[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code byte} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastByteBuffer(final int size) { |
||||
this.buffer = new byte[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code byte} to buffer. |
||||
*/ |
||||
public void append(final byte element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code byte} array to buffer. |
||||
*/ |
||||
public FastByteBuffer append(final byte[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code byte} array to buffer. |
||||
*/ |
||||
public FastByteBuffer append(final byte[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastByteBuffer append(final FastByteBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code byte} array from buffered content. |
||||
*/ |
||||
public byte[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code byte} subarray from buffered content. |
||||
*/ |
||||
public byte[] toArray(final int start, final int len) { |
||||
final byte[] array = new byte[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code byte} element at given index. |
||||
*/ |
||||
public byte get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
} |
@ -1,211 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import com.fr.third.jodd.util.CharArraySequence; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code char} buffer. |
||||
*/ |
||||
public class FastCharBuffer implements CharSequence, Appendable { |
||||
|
||||
private char[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code char} buffer. The buffer capacity is |
||||
* initially 64 chars, though its size increases if necessary. |
||||
*/ |
||||
public FastCharBuffer() { |
||||
this.buffer = new char[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code char} buffer, with a buffer capacity of |
||||
* the specified size, in chars. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastCharBuffer(final int size) { |
||||
this.buffer = new char[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code char} to buffer. |
||||
*/ |
||||
@Override |
||||
public FastCharBuffer append(final char element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code char} array to buffer. |
||||
*/ |
||||
public FastCharBuffer append(final char[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code char} array to buffer. |
||||
*/ |
||||
public FastCharBuffer append(final char[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastCharBuffer append(final FastCharBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
@Override |
||||
public int length() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code char} array from buffered content. |
||||
*/ |
||||
public char[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code char} subarray from buffered content. |
||||
*/ |
||||
public char[] toArray(final int start, final int len) { |
||||
final char[] array = new char[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code char} element at given index. |
||||
*/ |
||||
public char get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
/** |
||||
* Appends character sequence to buffer. |
||||
*/ |
||||
@Override |
||||
public FastCharBuffer append(final CharSequence csq) { |
||||
append(csq, 0, csq.length()); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends character sequence to buffer. |
||||
*/ |
||||
@Override |
||||
public FastCharBuffer append(final CharSequence csq, final int start, final int end) { |
||||
for (int i = start; i < end; i++) { |
||||
append(csq.charAt(i)); |
||||
} |
||||
return this; |
||||
} |
||||
@Override |
||||
public char charAt(final int index) { |
||||
return get(index); |
||||
} |
||||
|
||||
@Override |
||||
public CharSequence subSequence(final int start, final int end) { |
||||
return new CharArraySequence(buffer, start, end - start); |
||||
} |
||||
|
||||
/** |
||||
* Returns a String of the char buffer. |
||||
* Please use {@code StringBuilder} instead, it is faster. |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new String(toArray()); |
||||
} |
||||
} |
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code double} buffer. |
||||
*/ |
||||
public class FastDoubleBuffer { |
||||
|
||||
private double[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code double} buffer. The buffer capacity is |
||||
* initially 64 doubles, though its size increases if necessary. |
||||
*/ |
||||
public FastDoubleBuffer() { |
||||
this.buffer = new double[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code double} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastDoubleBuffer(final int size) { |
||||
this.buffer = new double[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code double} to buffer. |
||||
*/ |
||||
public void append(final double element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code double} array to buffer. |
||||
*/ |
||||
public FastDoubleBuffer append(final double[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code double} array to buffer. |
||||
*/ |
||||
public FastDoubleBuffer append(final double[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastDoubleBuffer append(final FastDoubleBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code double} array from buffered content. |
||||
*/ |
||||
public double[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code double} subarray from buffered content. |
||||
*/ |
||||
public double[] toArray(final int start, final int len) { |
||||
final double[] array = new double[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code double} element at given index. |
||||
*/ |
||||
public double get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -1,165 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code float} buffer. |
||||
*/ |
||||
public class FastFloatBuffer { |
||||
|
||||
private float[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code float} buffer. The buffer capacity is |
||||
* initially 64 floats, though its size increases if necessary. |
||||
*/ |
||||
public FastFloatBuffer() { |
||||
this.buffer = new float[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code float} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastFloatBuffer(final int size) { |
||||
this.buffer = new float[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code float} to buffer. |
||||
*/ |
||||
public void append(final float element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code float} array to buffer. |
||||
*/ |
||||
public FastFloatBuffer append(final float[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code float} array to buffer. |
||||
*/ |
||||
public FastFloatBuffer append(final float[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastFloatBuffer append(final FastFloatBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code float} array from buffered content. |
||||
*/ |
||||
public float[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code float} subarray from buffered content. |
||||
*/ |
||||
public float[] toArray(final int start, final int len) { |
||||
final float[] array = new float[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code float} element at given index. |
||||
*/ |
||||
public float get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
} |
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code int} buffer. |
||||
*/ |
||||
public class FastIntBuffer { |
||||
|
||||
private int[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code int} buffer. The buffer capacity is |
||||
* initially 64 ints, though its size increases if necessary. |
||||
*/ |
||||
public FastIntBuffer() { |
||||
this.buffer = new int[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code int} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastIntBuffer(final int size) { |
||||
this.buffer = new int[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code int} to buffer. |
||||
*/ |
||||
public void append(final int element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code int} array to buffer. |
||||
*/ |
||||
public FastIntBuffer append(final int[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code int} array to buffer. |
||||
*/ |
||||
public FastIntBuffer append(final int[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastIntBuffer append(final FastIntBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code int} array from buffered content. |
||||
*/ |
||||
public int[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code int} subarray from buffered content. |
||||
*/ |
||||
public int[] toArray(final int start, final int len) { |
||||
final int[] array = new int[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code int} element at given index. |
||||
*/ |
||||
public int get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code long} buffer. |
||||
*/ |
||||
public class FastLongBuffer { |
||||
|
||||
private long[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code long} buffer. The buffer capacity is |
||||
* initially 64 longs, though its size increases if necessary. |
||||
*/ |
||||
public FastLongBuffer() { |
||||
this.buffer = new long[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code long} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastLongBuffer(final int size) { |
||||
this.buffer = new long[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code long} to buffer. |
||||
*/ |
||||
public void append(final long element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code long} array to buffer. |
||||
*/ |
||||
public FastLongBuffer append(final long[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code long} array to buffer. |
||||
*/ |
||||
public FastLongBuffer append(final long[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastLongBuffer append(final FastLongBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code long} array from buffered content. |
||||
*/ |
||||
public long[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code long} subarray from buffered content. |
||||
*/ |
||||
public long[] toArray(final int start, final int len) { |
||||
final long[] array = new long[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code long} element at given index. |
||||
*/ |
||||
public long get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
|
||||
} |
@ -1,165 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.buffer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* Faster {@code short} buffer. |
||||
*/ |
||||
public class FastShortBuffer { |
||||
|
||||
private short[] buffer; |
||||
private int offset; |
||||
|
||||
/** |
||||
* Creates a new {@code short} buffer. The buffer capacity is |
||||
* initially 64 shorts, though its size increases if necessary. |
||||
*/ |
||||
public FastShortBuffer() { |
||||
this.buffer = new short[64]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@code short} buffer, with a buffer capacity of |
||||
* the specified size. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastShortBuffer(final int size) { |
||||
this.buffer = new short[size]; |
||||
} |
||||
|
||||
/** |
||||
* Grows the buffer. |
||||
*/ |
||||
private void grow(final int minCapacity) { |
||||
final int oldCapacity = buffer.length; |
||||
int newCapacity = oldCapacity << 1; |
||||
if (newCapacity - minCapacity < 0) { |
||||
// special case, min capacity is larger then a grow
|
||||
newCapacity = minCapacity + 512; |
||||
} |
||||
buffer = Arrays.copyOf(buffer, newCapacity); |
||||
} |
||||
|
||||
/** |
||||
* Appends single {@code short} to buffer. |
||||
*/ |
||||
public void append(final short element) { |
||||
if (offset - buffer.length >= 0) { |
||||
grow(offset); |
||||
} |
||||
|
||||
buffer[offset++] = element; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code short} array to buffer. |
||||
*/ |
||||
public FastShortBuffer append(final short[] array, final int off, final int len) { |
||||
if (offset + len - buffer.length > 0) { |
||||
grow(offset + len); |
||||
} |
||||
|
||||
System.arraycopy(array, off, buffer, offset, len); |
||||
offset += len; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Appends {@code short} array to buffer. |
||||
*/ |
||||
public FastShortBuffer append(final short[] array) { |
||||
return append(array, 0, array.length); |
||||
} |
||||
|
||||
/** |
||||
* Appends another fast buffer to this one. |
||||
*/ |
||||
public FastShortBuffer append(final FastShortBuffer buff) { |
||||
if (buff.offset == 0) { |
||||
return this; |
||||
} |
||||
append(buff.buffer, 0, buff.offset); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Returns buffer size. |
||||
*/ |
||||
public int size() { |
||||
return offset; |
||||
} |
||||
|
||||
/** |
||||
* Tests if this buffer has no elements. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return offset == 0; |
||||
} |
||||
|
||||
/** |
||||
* Resets the buffer content. |
||||
*/ |
||||
public void clear() { |
||||
offset = 0; |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code short} array from buffered content. |
||||
*/ |
||||
public short[] toArray() { |
||||
return Arrays.copyOf(buffer, offset); |
||||
} |
||||
|
||||
/** |
||||
* Creates {@code short} subarray from buffered content. |
||||
*/ |
||||
public short[] toArray(final int start, final int len) { |
||||
final short[] array = new short[len]; |
||||
|
||||
if (len == 0) { |
||||
return array; |
||||
} |
||||
|
||||
System.arraycopy(buffer, start, array, 0, len); |
||||
|
||||
return array; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code short} element at given index. |
||||
*/ |
||||
public short get(final int index) { |
||||
if (index >= offset) { |
||||
throw new IndexOutOfBoundsException(); |
||||
} |
||||
return buffer[index]; |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Faster primitive buffers, a simple wrappers over an array. |
||||
*/ |
||||
package com.fr.third.jodd.buffer; |
@ -1,344 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.Objects; |
||||
import java.util.concurrent.locks.StampedLock; |
||||
|
||||
/** |
||||
* Default implementation of timed and size cache map. |
||||
* Implementations should: |
||||
* <ul> |
||||
* <li>create a new cache map</li> |
||||
* <li>implements own <code>prune</code> strategy</li> |
||||
* </ul> |
||||
* Uses <code>ReentrantReadWriteLock</code> to synchronize access. |
||||
* Since upgrading from a read lock to the write lock is not possible, |
||||
* be careful withing {@link #get(Object)} method. |
||||
*/ |
||||
public abstract class AbstractCacheMap<K,V> implements Cache<K,V> { |
||||
|
||||
static class CacheObject<K2,V2> { |
||||
CacheObject(final K2 key, final V2 object, final long ttl) { |
||||
this.key = key; |
||||
this.cachedObject = object; |
||||
this.ttl = ttl; |
||||
this.lastAccess = System.currentTimeMillis(); |
||||
} |
||||
|
||||
final K2 key; |
||||
final V2 cachedObject; |
||||
long lastAccess; // time of last access
|
||||
long accessCount; // number of accesses
|
||||
long ttl; // objects timeout (time-to-live), 0 = no timeout
|
||||
|
||||
boolean isExpired() { |
||||
if (ttl == 0) { |
||||
return false; |
||||
} |
||||
return lastAccess + ttl < System.currentTimeMillis(); |
||||
} |
||||
V2 getObject() { |
||||
lastAccess = System.currentTimeMillis(); |
||||
accessCount++; |
||||
return cachedObject; |
||||
} |
||||
V2 peekObject() { |
||||
return cachedObject; |
||||
} |
||||
} |
||||
|
||||
protected Map<K,CacheObject<K,V>> cacheMap; |
||||
private final StampedLock lock = new StampedLock(); |
||||
|
||||
// ---------------------------------------------------------------- properties
|
||||
|
||||
protected int cacheSize; // max cache size, 0 = no limit
|
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public int limit() { |
||||
return cacheSize; |
||||
} |
||||
|
||||
protected long timeout; // default timeout, 0 = no timeout
|
||||
|
||||
/** |
||||
* Returns default cache timeout or <code>0</code> if it is not set. |
||||
* Timeout can be set individually for each object. |
||||
*/ |
||||
@Override |
||||
public long timeout() { |
||||
return timeout; |
||||
} |
||||
|
||||
/** |
||||
* Identifies if objects has custom timeouts. |
||||
* Should be used to determine if prune for existing objects is needed. |
||||
*/ |
||||
protected boolean existCustomTimeout; |
||||
|
||||
/** |
||||
* Returns <code>true</code> if prune of expired objects should be invoked. |
||||
* For internal use. |
||||
*/ |
||||
protected boolean isPruneExpiredActive() { |
||||
return (timeout != 0) || existCustomTimeout; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- put
|
||||
|
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public void put(final K key, final V object) { |
||||
put(key, object, timeout); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public void put(final K key, final V object, final long timeout) { |
||||
Objects.requireNonNull(object); |
||||
|
||||
final long stamp = lock.writeLock(); |
||||
|
||||
try { |
||||
final CacheObject<K,V> co = createCacheObject(key, object, timeout); |
||||
if (timeout != 0) { |
||||
existCustomTimeout = true; |
||||
} |
||||
if (isReallyFull(key)) { |
||||
pruneCache(); |
||||
} |
||||
cacheMap.put(key, co); |
||||
} |
||||
finally { |
||||
lock.unlockWrite(stamp); |
||||
} |
||||
} |
||||
|
||||
protected CacheObject<K, V> createCacheObject(K key, V object, long timeout) { |
||||
return new CacheObject<>(key, object, timeout); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
protected int hitCount; |
||||
protected int missCount; |
||||
|
||||
/** |
||||
* Returns hit count. |
||||
*/ |
||||
public int getHitCount() { |
||||
return hitCount; |
||||
} |
||||
|
||||
/** |
||||
* Returns miss count. |
||||
*/ |
||||
public int getMissCount() { |
||||
return missCount; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public V get(final K key) { |
||||
long stamp = lock.readLock(); |
||||
|
||||
try { |
||||
final CacheObject<K,V> co = cacheMap.get(key); |
||||
if (co == null) { |
||||
missCount++; |
||||
return null; |
||||
} |
||||
if (co.isExpired()) { |
||||
final long newStamp = lock.tryConvertToWriteLock(stamp); |
||||
|
||||
if (newStamp != 0L) { |
||||
stamp = newStamp; |
||||
// lock is upgraded to write lock
|
||||
} |
||||
else { |
||||
// manually upgrade lock to write lock
|
||||
lock.unlockRead(stamp); |
||||
stamp = lock.writeLock(); |
||||
} |
||||
|
||||
final CacheObject<K,V> removedCo = cacheMap.remove(key); |
||||
if (removedCo != null) { |
||||
onRemove(removedCo.key, removedCo.cachedObject); |
||||
} |
||||
|
||||
missCount++; |
||||
return null; |
||||
} |
||||
|
||||
hitCount++; |
||||
return co.getObject(); |
||||
} |
||||
finally { |
||||
lock.unlock(stamp); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/** |
||||
* Prune implementation. |
||||
*/ |
||||
protected abstract int pruneCache(); |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public final int prune() { |
||||
final long stamp = lock.writeLock(); |
||||
try { |
||||
return pruneCache(); |
||||
} |
||||
finally { |
||||
lock.unlockWrite(stamp); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- common
|
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public boolean isFull() { |
||||
if (cacheSize == 0) { |
||||
return false; |
||||
} |
||||
return cacheMap.size() >= cacheSize; |
||||
} |
||||
|
||||
protected boolean isReallyFull(final K key) { |
||||
if (cacheSize == 0) { |
||||
return false; |
||||
} |
||||
if (cacheMap.size() >= cacheSize) { |
||||
return !cacheMap.containsKey(key); |
||||
} |
||||
else { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public V remove(final K key) { |
||||
V removedValue = null; |
||||
final long stamp = lock.writeLock(); |
||||
try { |
||||
final CacheObject<K,V> co = cacheMap.remove(key); |
||||
|
||||
if (co != null) { |
||||
onRemove(co.key, co.cachedObject); |
||||
removedValue = co.cachedObject; |
||||
} |
||||
} |
||||
finally { |
||||
lock.unlockWrite(stamp); |
||||
} |
||||
return removedValue; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public void clear() { |
||||
final long stamp = lock.writeLock(); |
||||
try { |
||||
cacheMap.clear(); |
||||
} |
||||
finally { |
||||
lock.unlockWrite(stamp); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public int size() { |
||||
return cacheMap.size(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public boolean isEmpty() { |
||||
return size() == 0; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public Map<K, V> snapshot(final boolean peek) { |
||||
final long stamp = lock.writeLock(); |
||||
try { |
||||
final Map<K, V> map = new HashMap<>(cacheMap.size()); |
||||
cacheMap.forEach((key, cacheValue) -> { |
||||
if (!cacheValue.isExpired()) { |
||||
map.put(key, peek ? cacheValue.peekObject() : cacheValue.getObject()); |
||||
} |
||||
}); |
||||
return map; |
||||
} |
||||
finally { |
||||
lock.unlockWrite(stamp); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- protected
|
||||
|
||||
/** |
||||
* Callback called on item removal. The cache is still locked. |
||||
*/ |
||||
protected void onRemove(final K key, final V cachedObject) { |
||||
} |
||||
|
||||
} |
@ -1,108 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Cache interface. |
||||
*/ |
||||
public interface Cache<K, V> { |
||||
|
||||
/** |
||||
* Returns cache size or <code>0</code> if there is no size limit. |
||||
*/ |
||||
int limit(); |
||||
|
||||
/** |
||||
* Returns default timeout or <code>0</code> if it is not set. |
||||
*/ |
||||
long timeout(); |
||||
|
||||
/** |
||||
* Adds an object to the cache with default timeout. |
||||
* @see Cache#put(Object, Object, long) |
||||
*/ |
||||
void put(K key, V object); |
||||
|
||||
/** |
||||
* Adds an object to the cache with specified timeout after which it becomes expired. |
||||
* If cache is full, {@link #prune()} is invoked to make room for new object. |
||||
* Cached value must be non-null. |
||||
*/ |
||||
void put(K key, V object, long timeout); |
||||
|
||||
/** |
||||
* Retrieves an object from the cache. Returns <code>null</code> if object |
||||
* is not longer in cache or if it is expired. |
||||
*/ |
||||
V get(K key); |
||||
|
||||
/** |
||||
* Prunes objects from cache and returns the number of removed objects. |
||||
* Used strategy depends on cache implementation. |
||||
*/ |
||||
int prune(); |
||||
|
||||
/** |
||||
* Returns <code>true</code> if max cache capacity has been reached |
||||
* only if cache is size limited. |
||||
*/ |
||||
boolean isFull(); |
||||
|
||||
/** |
||||
* Removes an object from the cache and returns removed value of {@code null} |
||||
* if object was not in the cache or was expired. |
||||
*/ |
||||
V remove(K key); |
||||
|
||||
/** |
||||
* Clears current cache. |
||||
*/ |
||||
void clear(); |
||||
|
||||
/** |
||||
* Returns current cache size. |
||||
*/ |
||||
int size(); |
||||
|
||||
/** |
||||
* Returns <code>true</code> if cache is empty. |
||||
*/ |
||||
boolean isEmpty(); |
||||
|
||||
/** |
||||
* Creates a snapshot from current cache values. Returned values may not |
||||
* longer be valid or they might be already expired! Cache is locked during |
||||
* the snapshot creation. |
||||
* @param peek if set, snapshot will just peek the object and not get them (and modify last access) |
||||
*/ |
||||
Map<K, V> snapshot(boolean peek); |
||||
|
||||
default Map<K, V> snapshot() { |
||||
return this.snapshot(false); |
||||
} |
||||
} |
@ -1,89 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.Iterator; |
||||
import java.util.LinkedHashMap; |
||||
|
||||
/** |
||||
* FIFO (first in first out) cache. |
||||
* |
||||
* <p> |
||||
* FIFO (first in first out): just adds items to the cache as they are accessed, putting them in a queue or buffer and |
||||
* not changing their location in the buffer; when the cache is full, items are ejected in the order they were |
||||
* added. Cache access overhead is constant time regardless of the size of the cache. The advantage of this algorithm |
||||
* is that it's simple and fast; it can be implemented using a simple array and an index. The disadvantage is that |
||||
* it's not very smart; it doesn't make any effort to keep more commonly used items in cache. |
||||
* <p> |
||||
* Summary for FIFO: fast, not adaptive, not scan resistant. |
||||
*/ |
||||
public class FIFOCache<K, V> extends AbstractCacheMap<K, V> { |
||||
|
||||
public FIFOCache(final int cacheSize) { |
||||
this(cacheSize, 0); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new LRU cache. |
||||
*/ |
||||
public FIFOCache(final int cacheSize, final long timeout) { |
||||
this.cacheSize = cacheSize; |
||||
this.timeout = timeout; |
||||
cacheMap = new LinkedHashMap<>(cacheSize + 1, 1.0f, false); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/** |
||||
* Prune expired objects and, if cache is still full, the first one. |
||||
*/ |
||||
@Override |
||||
protected int pruneCache() { |
||||
int count = 0; |
||||
CacheObject<K,V> first = null; |
||||
Iterator<CacheObject<K,V>> values = cacheMap.values().iterator(); |
||||
while (values.hasNext()) { |
||||
CacheObject<K,V> co = values.next(); |
||||
if (co.isExpired()) { |
||||
values.remove(); |
||||
onRemove(co.key, co.cachedObject); |
||||
count++; |
||||
} |
||||
if (first == null) { |
||||
first = co; |
||||
} |
||||
} |
||||
if (isFull()) { |
||||
if (first != null) { |
||||
cacheMap.remove(first.key); |
||||
onRemove(first.key, first.cachedObject); |
||||
count++; |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
} |
@ -1,153 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import com.fr.third.jodd.io.FileUtil; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Base in-memory files cache. |
||||
*/ |
||||
public abstract class FileCache { |
||||
|
||||
protected final Cache<File, byte[]> cache; |
||||
protected final int maxSize; |
||||
protected final int maxFileSize; |
||||
protected final long timeout; |
||||
|
||||
protected int usedSize; |
||||
|
||||
/** |
||||
* Creates new File LFU cache. |
||||
* @param maxSize total cache size in bytes |
||||
* @param maxFileSize max available file size in bytes, may be 0 |
||||
* @param timeout timeout, may be 0 |
||||
*/ |
||||
protected FileCache(final int maxSize, final int maxFileSize, final long timeout) { |
||||
this.maxSize = maxSize; |
||||
this.maxFileSize = maxFileSize; |
||||
this.timeout = timeout; |
||||
this.cache = createCache(); |
||||
} |
||||
|
||||
/** |
||||
* Creates new cache instance for files content. |
||||
*/ |
||||
protected abstract Cache<File, byte[]> createCache(); |
||||
|
||||
/** |
||||
* Creates CacheObject that updates last access time based on files last modification. |
||||
*/ |
||||
protected AbstractCacheMap.CacheObject<File, byte[]> createFileCacheObject(File fileKey, byte[] object, long timeout) { |
||||
return new AbstractCacheMap.CacheObject<File, byte[]>(fileKey, object, timeout) { |
||||
@Override |
||||
boolean isExpired() { |
||||
if (fileKey.lastModified() > this.lastAccess) { |
||||
this.lastAccess = fileKey.lastModified(); |
||||
} |
||||
return super.isExpired(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns max cache size in bytes. |
||||
*/ |
||||
public int maxSize() { |
||||
return maxSize; |
||||
} |
||||
|
||||
/** |
||||
* Returns actually used size in bytes. |
||||
*/ |
||||
public int usedSize() { |
||||
return usedSize; |
||||
} |
||||
|
||||
/** |
||||
* Returns maximum allowed file size that can be added to the cache. |
||||
* Files larger than this value will be not added, even if there is |
||||
* enough room. |
||||
*/ |
||||
public int maxFileSize() { |
||||
return maxFileSize; |
||||
} |
||||
|
||||
/** |
||||
* Returns number of cached files. |
||||
*/ |
||||
public int cachedFilesCount() { |
||||
return cache.size(); |
||||
} |
||||
|
||||
/** |
||||
* Returns timeout. |
||||
*/ |
||||
public long cacheTimeout() { |
||||
return cache.timeout(); |
||||
} |
||||
|
||||
/** |
||||
* Clears the cache. |
||||
*/ |
||||
public void clear() { |
||||
cache.clear(); |
||||
usedSize = 0; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns cached file bytes. If file is not cached it will be |
||||
* read and put in the cache (if all the rules are satisfied). |
||||
*/ |
||||
public byte[] getFileBytes(final File file) throws IOException { |
||||
byte[] bytes = cache.get(file); |
||||
if (bytes != null) { |
||||
return bytes; |
||||
} |
||||
|
||||
// add file
|
||||
bytes = FileUtil.readBytes(file); |
||||
|
||||
if ((maxFileSize != 0) && (file.length() > maxFileSize)) { |
||||
// don't cache files that size exceed max allowed file size
|
||||
return bytes; |
||||
} |
||||
|
||||
usedSize += bytes.length; |
||||
|
||||
// put file into cache
|
||||
// if used size > total, purge() will be invoked
|
||||
cache.put(file, bytes); |
||||
|
||||
return bytes; |
||||
} |
||||
|
||||
} |
@ -1,82 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.io.File; |
||||
|
||||
/** |
||||
* Files LFU cache stores files content in memory to dramatically |
||||
* speed up performances for frequently read files. |
||||
*/ |
||||
public class FileLFUCache extends FileCache { |
||||
|
||||
/** |
||||
* Creates file LFU cache with specified size. Sets |
||||
* {@link #maxFileSize max available file size} to half of this value. |
||||
*/ |
||||
public FileLFUCache(final int maxSize) { |
||||
this(maxSize, maxSize / 2, 0); |
||||
} |
||||
|
||||
public FileLFUCache(final int maxSize, final int maxFileSize) { |
||||
this(maxSize, maxFileSize, 0); |
||||
} |
||||
|
||||
/** |
||||
* Creates new File LFU cache. |
||||
* @param maxSize total cache size in bytes |
||||
* @param maxFileSize max available file size in bytes, may be 0 |
||||
* @param timeout timeout, may be 0 |
||||
*/ |
||||
public FileLFUCache(final int maxSize, final int maxFileSize, final long timeout) { |
||||
super(maxSize, maxFileSize, timeout); |
||||
} |
||||
|
||||
@Override |
||||
protected Cache<File, byte[]> createCache() { |
||||
return new LFUCache<File, byte[]>(0, timeout) { |
||||
@Override |
||||
public boolean isFull() { |
||||
return usedSize > FileLFUCache.this.maxSize; |
||||
} |
||||
|
||||
@Override |
||||
protected boolean isReallyFull(final File file) { |
||||
return isFull(); |
||||
} |
||||
|
||||
@Override |
||||
protected void onRemove(final File key, final byte[] cachedObject) { |
||||
usedSize -= cachedObject.length; |
||||
} |
||||
|
||||
@Override |
||||
protected CacheObject<File, byte[]> createCacheObject(File key, byte[] object, long timeout) { |
||||
return createFileCacheObject(key, object, timeout); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -1,81 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.io.File; |
||||
|
||||
/** |
||||
* Cache of recently used files. |
||||
*/ |
||||
public class FileLRUCache extends FileCache { |
||||
|
||||
/** |
||||
* Creates file LRU cache with specified size. Sets |
||||
* {@link #maxFileSize max available file size} to half of this value. |
||||
*/ |
||||
public FileLRUCache(final int maxSize) { |
||||
this(maxSize, maxSize / 2, 0); |
||||
} |
||||
|
||||
public FileLRUCache(final int maxSize, final int maxFileSize) { |
||||
this(maxSize, maxFileSize, 0); |
||||
} |
||||
|
||||
/** |
||||
* Creates new File LRU cache. |
||||
* @param maxSize total cache size in bytes |
||||
* @param maxFileSize max available file size in bytes, may be 0 |
||||
* @param timeout timeout, may be 0 |
||||
*/ |
||||
public FileLRUCache(final int maxSize, final int maxFileSize, final long timeout) { |
||||
super(maxSize, maxFileSize, timeout); |
||||
} |
||||
|
||||
@Override |
||||
protected Cache<File, byte[]> createCache() { |
||||
return new LRUCache<File, byte[]>(0, timeout) { |
||||
@Override |
||||
public boolean isFull() { |
||||
return usedSize > FileLRUCache.this.maxSize; |
||||
} |
||||
|
||||
@Override |
||||
protected boolean isReallyFull(final File file) { |
||||
return isFull(); |
||||
} |
||||
|
||||
@Override |
||||
protected void onRemove(final File key, final byte[] cachedObject) { |
||||
usedSize -= cachedObject.length; |
||||
} |
||||
|
||||
@Override |
||||
protected CacheObject<File, byte[]> createCacheObject(File key, byte[] object, long timeout) { |
||||
return createFileCacheObject(key, object, timeout); |
||||
} |
||||
|
||||
}; |
||||
} |
||||
} |
@ -1,111 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* LFU (least frequently used) cache. Frequency is calculated as access count. This cache |
||||
* is resistant on 'new usages scenario': when some object is removed from the cache, |
||||
* access count of all items in cache is decreased by access count of removed value. |
||||
* This allows new frequent elements to come into the cache. |
||||
* <p> |
||||
* Frequency of use data is kept on all items. The most frequently used items are kept in the cache. |
||||
* Because of the bookkeeping requirements, cache access overhead increases logarithmically with cache size. |
||||
* The advantage is that long term usage patterns are captured well, incidentally making the algorithm scan resistant; |
||||
* the disadvantage, besides the larger access overhead, is that the algorithm doesn't adapt quickly to changing |
||||
* usage patterns, and in particular doesn't help with temporally clustered accesses. |
||||
* <p> |
||||
* Summary for LFU: not fast, captures frequency of use, scan resistant. |
||||
*/ |
||||
public class LFUCache<K,V> extends AbstractCacheMap<K,V> { |
||||
|
||||
public LFUCache(final int maxSize) { |
||||
this(maxSize, 0); |
||||
} |
||||
|
||||
public LFUCache(final int maxSize, final long timeout) { |
||||
this.cacheSize = maxSize; |
||||
this.timeout = timeout; |
||||
cacheMap = new HashMap<>(maxSize + 1); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/** |
||||
* Prunes expired and, if cache is still full, the LFU element(s) from the cache. |
||||
* On LFU removal, access count is normalized to value which had removed object. |
||||
* Returns the number of removed objects. |
||||
*/ |
||||
@Override |
||||
protected int pruneCache() { |
||||
int count = 0; |
||||
CacheObject<K,V> comin = null; |
||||
|
||||
// remove expired items and find cached object with minimal access count
|
||||
Iterator<CacheObject<K,V>> values = cacheMap.values().iterator(); |
||||
while (values.hasNext()) { |
||||
CacheObject<K,V> co = values.next(); |
||||
if (co.isExpired()) { |
||||
values.remove(); |
||||
onRemove(co.key, co.cachedObject); |
||||
count++; |
||||
continue; |
||||
} |
||||
|
||||
if (comin == null) { |
||||
comin = co; |
||||
} else { |
||||
if (co.accessCount < comin.accessCount) { |
||||
comin = co; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (!isFull()) { |
||||
return count; |
||||
} |
||||
|
||||
// decrease access count to all cached objects
|
||||
if (comin != null) { |
||||
long minAccessCount = comin.accessCount; |
||||
|
||||
values = cacheMap.values().iterator(); |
||||
while (values.hasNext()) { |
||||
CacheObject<K, V> co = values.next(); |
||||
co.accessCount -= minAccessCount; |
||||
if (co.accessCount <= 0) { |
||||
values.remove(); |
||||
onRemove(co.key, co.cachedObject); |
||||
count++; |
||||
} |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
|
||||
} |
@ -1,103 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.LinkedHashMap; |
||||
import java.util.Map; |
||||
import java.util.Iterator; |
||||
|
||||
|
||||
/** |
||||
* LRU (least recently used) cache. |
||||
* |
||||
* <p> |
||||
* Items are added to the cache as they are accessed; when the cache is full, the least recently used item is ejected. |
||||
* This type of cache is typically implemented as a linked list, so that an item in cache, when it is accessed again, |
||||
* can be moved back up to the head of the queue; items are ejected from the tail of the queue. Cache access overhead |
||||
* is again constant time. This algorithm is simple and fast, and it has a significant advantage over FIFO in being |
||||
* able to adapt somewhat to the data access pattern; frequently used items are less likely to be |
||||
* ejected from the cache. The main disadvantage is that it can still get filled up with items that are |
||||
* unlikely to be reaccessed soon; in particular, it can become useless in the face of scanning type accesses. |
||||
* Nonetheless, this is by far the most frequently used caching algorithm. |
||||
* <p> |
||||
* Implementation note: unfortunately, it was not possible to have <code>onRemove</code> callback method, |
||||
* since <code>LinkedHashMap</code> has its removal methods private. |
||||
* <p> |
||||
* Summary for LRU: fast, adaptive, not scan resistant. |
||||
*/ |
||||
public class LRUCache<K, V> extends AbstractCacheMap<K, V> { |
||||
|
||||
public LRUCache(final int cacheSize) { |
||||
this(cacheSize, 0); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new LRU cache. |
||||
*/ |
||||
public LRUCache(final int cacheSize, final long timeout) { |
||||
this.cacheSize = cacheSize; |
||||
this.timeout = timeout; |
||||
cacheMap = new LinkedHashMap<K, CacheObject<K,V>>(cacheSize + 1, 1.0f, true) { |
||||
@Override |
||||
protected boolean removeEldestEntry(final Map.Entry eldest) { |
||||
return LRUCache.this.removeEldestEntry(size()); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Removes the eldest entry if current cache size exceed cache size. |
||||
*/ |
||||
protected boolean removeEldestEntry(final int currentSize) { |
||||
if (cacheSize == 0) { |
||||
return false; |
||||
} |
||||
return currentSize > cacheSize; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/** |
||||
* Prune only expired objects, <code>LinkedHashMap</code> will take care of LRU if needed. |
||||
*/ |
||||
@Override |
||||
protected int pruneCache() { |
||||
if (!isPruneExpiredActive()) { |
||||
return 0; |
||||
} |
||||
int count = 0; |
||||
Iterator<CacheObject<K,V>> values = cacheMap.values().iterator(); |
||||
while (values.hasNext()) { |
||||
CacheObject<K,V> co = values.next(); |
||||
if (co.isExpired()) { |
||||
values.remove(); |
||||
onRemove(co.key, co.cachedObject); |
||||
count++; |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
} |
@ -1,96 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Simple no-cache implementations of {@link Cache} for situation when cache |
||||
* needs to be quickly turned-off. |
||||
*/ |
||||
public class NoCache<K, V> implements Cache<K, V> { |
||||
|
||||
@Override |
||||
public int limit() { |
||||
return 0; |
||||
} |
||||
|
||||
@Override |
||||
public long timeout() { |
||||
return 0; |
||||
} |
||||
|
||||
@Override |
||||
public void put(final K key, final V object) { |
||||
// ignore
|
||||
} |
||||
|
||||
@Override |
||||
public void put(final K key, final V object, final long timeout) { |
||||
// ignore
|
||||
} |
||||
|
||||
@Override |
||||
public V get(final K key) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public int prune() { |
||||
return 0; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isFull() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public V remove(final K key) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void clear() { |
||||
// ignore
|
||||
} |
||||
|
||||
@Override |
||||
public int size() { |
||||
return 0; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isEmpty() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public Map<K, V> snapshot(final boolean peek) { |
||||
return Collections.emptyMap(); |
||||
} |
||||
} |
@ -1,98 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Iterator; |
||||
import java.util.Timer; |
||||
import java.util.TimerTask; |
||||
|
||||
/** |
||||
* Timed cache. Not limited by size, objects are removed only when they are expired. |
||||
* Prune is not invoked explicitly by standard {@link Cache} methods, however, |
||||
* it is possible to schedule prunes on fined-rate delays. |
||||
*/ |
||||
public class TimedCache<K, V> extends AbstractCacheMap<K, V> { |
||||
|
||||
public TimedCache(final long timeout) { |
||||
this.cacheSize = 0; |
||||
this.timeout = timeout; |
||||
cacheMap = new HashMap<>(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- prune
|
||||
|
||||
/** |
||||
* Prunes expired elements from the cache. Returns the number of removed objects. |
||||
*/ |
||||
@Override |
||||
protected int pruneCache() { |
||||
int count = 0; |
||||
Iterator<CacheObject<K,V>> values = cacheMap.values().iterator(); |
||||
while (values.hasNext()) { |
||||
CacheObject co = values.next(); |
||||
if (co.isExpired()) { |
||||
values.remove(); |
||||
count++; |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- auto prune
|
||||
|
||||
protected Timer pruneTimer; |
||||
|
||||
/** |
||||
* Schedules prune. |
||||
*/ |
||||
public void schedulePrune(final long delay) { |
||||
if (pruneTimer != null) { |
||||
pruneTimer.cancel(); |
||||
} |
||||
pruneTimer = new Timer(); |
||||
pruneTimer.schedule( |
||||
new TimerTask() { |
||||
@Override |
||||
public void run() { |
||||
prune(); |
||||
} |
||||
}, delay, delay |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Cancels prune schedules. |
||||
*/ |
||||
public void cancelPruneSchedule() { |
||||
if (pruneTimer != null) { |
||||
pruneTimer.cancel(); |
||||
pruneTimer = null; |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,205 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cache; |
||||
|
||||
import java.util.AbstractMap; |
||||
import java.util.Collections; |
||||
import java.util.IdentityHashMap; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.WeakHashMap; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.function.Consumer; |
||||
import java.util.function.Function; |
||||
|
||||
/** |
||||
* Types cache. Provides several implementations depending on what you need to be addressed. |
||||
* There are two things you should take care off: |
||||
* <ul> |
||||
* <li>synchronization - especially on storing items. If not synchronized, one instance of an item may be put |
||||
* more then once into the map. This is usually fine, as it happens only during the initialization and makes not |
||||
* harm if something is created twice</li> |
||||
* <li>weak - if your key classes are replaced during the runtime, you should use weak map, in order to automatically |
||||
* remove obsolete keys.</li> |
||||
* </ul> |
||||
*/ |
||||
public class TypeCache<T> { |
||||
|
||||
// ---------------------------------------------------------------- builder
|
||||
|
||||
/** |
||||
* Creates a type cache by using a builder. |
||||
*/ |
||||
public static <A> Builder<A> create() { |
||||
return new Builder<>(); |
||||
} |
||||
|
||||
/** |
||||
* Creates default implementation of the type cache. |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public static <A> TypeCache<A> createDefault() { |
||||
return TypeCache.<A>create().get(); |
||||
} |
||||
|
||||
public static class Builder<A> { |
||||
private boolean threadsafe; |
||||
private boolean weak; |
||||
private boolean none; |
||||
|
||||
/** |
||||
* No cache will be used. |
||||
* Setting other properties will not have any affect. |
||||
*/ |
||||
public Builder<A> noCache() { |
||||
none = true; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Cache keys will be weak. |
||||
*/ |
||||
public Builder<A> weak(final boolean weak) { |
||||
this.weak = weak; |
||||
return this; |
||||
} |
||||
/** |
||||
* Cache will be thread-safe. |
||||
*/ |
||||
public Builder<A> threadsafe(final boolean threadsafe) { |
||||
this.threadsafe = threadsafe; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Builds a type cache. |
||||
*/ |
||||
public TypeCache<A> get() { |
||||
final Map<Class<?>, A> map; |
||||
if (none) { |
||||
map = new AbstractMap<Class<?>, A>() { |
||||
@Override |
||||
public A put(final Class<?> key, final A value) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public A get(final Object key) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public Set<Entry<Class<?>, A>> entrySet() { |
||||
return Collections.emptySet(); |
||||
} |
||||
}; |
||||
} |
||||
else if (weak) { |
||||
if (threadsafe) { |
||||
map = Collections.synchronizedMap(new WeakHashMap<>()); |
||||
} else { |
||||
map = new WeakHashMap<>(); |
||||
} |
||||
} else { |
||||
if (threadsafe) { |
||||
map = new ConcurrentHashMap<>(); |
||||
} else { |
||||
map = new IdentityHashMap<>(); |
||||
} |
||||
} |
||||
|
||||
return new TypeCache<>(map); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- map
|
||||
|
||||
private final Map<Class<?>, T> map; |
||||
|
||||
private TypeCache(final Map<Class<?>, T> backedMap) { |
||||
this.map = backedMap; |
||||
} |
||||
|
||||
/** |
||||
* Add values to the map. |
||||
*/ |
||||
public T put(final Class<?> type, final T value) { |
||||
return map.put(type, value); |
||||
} |
||||
|
||||
/** |
||||
* Returns value from the map or {@code null} if value does not exist. |
||||
*/ |
||||
public T get(final Class<?> key) { |
||||
return map.get(key); |
||||
} |
||||
|
||||
/** |
||||
* Returns existing value or add default supplied one. |
||||
* Use this method instead of {@code get-nullcheck-put} block when |
||||
* thread-safety is of importance. |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public <K> T get(final Class<K> key, final Function<Class<K>, ? extends T> mappingFunction) { |
||||
return map.computeIfAbsent(key, aClass -> mappingFunction.apply((Class<K>) aClass)); |
||||
} |
||||
|
||||
/** |
||||
* Removes element from the type cache. |
||||
*/ |
||||
public T remove(final Class<?> type) { |
||||
return map.remove(type); |
||||
} |
||||
|
||||
/** |
||||
* Clears complete cache. |
||||
*/ |
||||
public void clear() { |
||||
map.clear(); |
||||
} |
||||
|
||||
/** |
||||
* Returns cache size. |
||||
*/ |
||||
public int size() { |
||||
return map.size(); |
||||
} |
||||
|
||||
/** |
||||
* Returns {@code true} if cache is empty. |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return map.isEmpty(); |
||||
} |
||||
|
||||
/** |
||||
* Iterates all cached values. |
||||
*/ |
||||
public void forEachValue(final Consumer<? super T> valueConsumer) { |
||||
map.values().forEach(valueConsumer); |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Some useful caches: LRU, LFU, FIFO. |
||||
*/ |
||||
package com.fr.third.jodd.cache; |
@ -1,298 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.chalk; |
||||
|
||||
import com.fr.third.jodd.util.StringPool; |
||||
|
||||
/** |
||||
* Chalk allows you to color output going to console. |
||||
* @see Chalk256 |
||||
*/ |
||||
public class Chalk<T extends Chalk<T>> { |
||||
|
||||
/** |
||||
* Global flag that disables all the chalks. |
||||
* Useful for windows platforms :) |
||||
*/ |
||||
public static boolean enabled = true; |
||||
|
||||
protected static final String RESET = "0"; |
||||
|
||||
protected static final String BOLD = "1"; |
||||
protected static final String UNBOLD = "22"; // 21 isn't widely supported and 22 does the same thing
|
||||
protected static final String DIM = "2"; |
||||
protected static final String UNDIM = "22"; |
||||
protected static final String ITALIC = "3"; |
||||
protected static final String UNITALIC = "23"; |
||||
protected static final String UNDERLINE = "4"; |
||||
protected static final String UNUNDERLINE = "24"; |
||||
protected static final String INVERSE = "7"; |
||||
protected static final String UNINVERSE = "27"; |
||||
protected static final String HIDDEN = "8"; |
||||
protected static final String UNHIDDEN = "28"; |
||||
protected static final String STRIKETHROUGH = "9"; |
||||
protected static final String UNSTRIKETHROUGH = "29"; |
||||
|
||||
protected static final String COLOR_RESET = "39"; |
||||
protected static final String BLACK = "30"; |
||||
protected static final String RED = "31"; |
||||
protected static final String GREEN = "32"; |
||||
protected static final String YELLOW = "33"; |
||||
protected static final String BLUE = "34"; |
||||
protected static final String MAGENTA = "35"; |
||||
protected static final String CYAN = "36"; |
||||
protected static final String WHITE = "37"; |
||||
protected static final String GRAY = "90"; |
||||
|
||||
protected static final String BGCOLOR_RESET = "49"; |
||||
protected static final String BGBLACK = "40"; |
||||
protected static final String BGRED = "41"; |
||||
protected static final String BGGREEN = "42"; |
||||
protected static final String BGYELLOW = "43"; |
||||
protected static final String BGBLUE = "44"; |
||||
protected static final String BGMAGENTA = "45"; |
||||
protected static final String BGCYAN = "46"; |
||||
protected static final String BGWHITE = "47"; |
||||
|
||||
protected StringBuilder prefix; |
||||
protected StringBuilder suffix; |
||||
protected String text; |
||||
|
||||
/** |
||||
* Creates new chalk. |
||||
*/ |
||||
public static Chalk chalk() { |
||||
return new Chalk(); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
protected T _this() { |
||||
return (T) this; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- style
|
||||
|
||||
public T bold() { |
||||
startSequence(BOLD); |
||||
endSequence(UNBOLD); |
||||
return _this(); |
||||
} |
||||
|
||||
public T italic() { |
||||
startSequence(ITALIC); |
||||
endSequence(UNITALIC); |
||||
return _this(); |
||||
} |
||||
|
||||
public T dim() { |
||||
startSequence(DIM); |
||||
endSequence(UNDIM); |
||||
return _this(); |
||||
} |
||||
|
||||
public T underline() { |
||||
startSequence(UNDERLINE); |
||||
endSequence(UNUNDERLINE); |
||||
return _this(); |
||||
} |
||||
|
||||
public T inverse() { |
||||
startSequence(INVERSE); |
||||
endSequence(UNINVERSE); |
||||
return _this(); |
||||
} |
||||
|
||||
public T hidden() { |
||||
startSequence(HIDDEN); |
||||
endSequence(UNHIDDEN); |
||||
return _this(); |
||||
} |
||||
public T strikeThrough() { |
||||
startSequence(STRIKETHROUGH); |
||||
endSequence(UNSTRIKETHROUGH); |
||||
return _this(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- colors
|
||||
|
||||
public T black() { |
||||
startSequence(BLACK); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T red() { |
||||
startSequence(RED); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T green() { |
||||
startSequence(GREEN); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T yellow() { |
||||
startSequence(YELLOW); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T blue() { |
||||
startSequence(BLUE); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T magenta() { |
||||
startSequence(MAGENTA); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T cyan() { |
||||
startSequence(CYAN); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T white() { |
||||
startSequence(WHITE); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T gray() { |
||||
startSequence(GRAY); |
||||
endSequence(COLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T grey() { |
||||
return gray(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- bg colors
|
||||
|
||||
public T bgBlack() { |
||||
startSequence(BGBLACK); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgRed() { |
||||
startSequence(BGRED); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgGreen() { |
||||
startSequence(BGGREEN); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgYellow() { |
||||
startSequence(BGYELLOW); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgBlue() { |
||||
startSequence(BGBLUE); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgMagenta() { |
||||
startSequence(BGMAGENTA); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgCyan() { |
||||
startSequence(BGCYAN); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
public T bgWhite() { |
||||
startSequence(BGWHITE); |
||||
endSequence(BGCOLOR_RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- internal
|
||||
|
||||
protected void startSequence(final String value) { |
||||
if (prefix == null) { |
||||
prefix = new StringBuilder(); |
||||
prefix.append("\u001B["); |
||||
} |
||||
else { |
||||
prefix.append(StringPool.SEMICOLON); |
||||
} |
||||
|
||||
prefix.append(value); |
||||
} |
||||
|
||||
protected void endSequence(final String value) { |
||||
if (suffix == null) { |
||||
suffix = new StringBuilder(); |
||||
suffix |
||||
.append("\u001B[") |
||||
.append(value); |
||||
} |
||||
else { |
||||
suffix.insert(2, value + StringPool.SEMICOLON); |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- out
|
||||
|
||||
/** |
||||
* Returns chalked string. |
||||
*/ |
||||
public String on(final String string) { |
||||
if (!enabled) { |
||||
return string; |
||||
} |
||||
|
||||
final StringBuilder sb = new StringBuilder(); |
||||
|
||||
if (prefix != null) { |
||||
sb.append(prefix).append("m"); |
||||
} |
||||
|
||||
sb.append(string); |
||||
|
||||
if (suffix != null) { |
||||
sb.append(suffix).append("m"); |
||||
} |
||||
|
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Prints chalked string to system output. |
||||
*/ |
||||
public void print(final String string) { |
||||
System.out.print(on(string)); |
||||
} |
||||
|
||||
/** |
||||
* Prints chalked string to system output. |
||||
*/ |
||||
public void println(final String string) { |
||||
System.out.println(on(string)); |
||||
} |
||||
|
||||
} |
@ -1,123 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.chalk; |
||||
|
||||
/** |
||||
* Chalk256 allows you to color output going to ansi-256 console. |
||||
* @see Chalk |
||||
*/ |
||||
public class Chalk256 extends Chalk<Chalk256> { |
||||
|
||||
private static final String[] FG_CODES = new String[256]; |
||||
private static final String[] BG_CODES = new String[256]; |
||||
|
||||
static { |
||||
for (int i = 0; i < FG_CODES.length; i++) { |
||||
FG_CODES[i] = "38;5;" + i; |
||||
} |
||||
for (int i = 0; i < BG_CODES.length; i++) { |
||||
BG_CODES[i] = "48;5;" + i; |
||||
} |
||||
} |
||||
|
||||
public static Chalk256 chalk() { |
||||
return new Chalk256(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- fg codes
|
||||
|
||||
public Chalk256 standard(final int index) { |
||||
startSequence(FG_CODES[index(index, 0, 8)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bright(final int index) { |
||||
startSequence(FG_CODES[index(index, 8, 16)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 rgb(final int index) { |
||||
startSequence(FG_CODES[index(index, 16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Colors with red-green-blue value, in the range 0 to 6. |
||||
*/ |
||||
public Chalk256 rgb(final int r, final int b, final int g) { |
||||
startSequence(FG_CODES[index(36*r + 6*g + b,16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 grayscale(final int index) { |
||||
startSequence(FG_CODES[index(index, 232, 256)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
// ---------------------------------------------------------------- bg codes
|
||||
|
||||
public Chalk256 bgStandard(final int index) { |
||||
startSequence(BG_CODES[index(index, 0, 8)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bgBright(final int index) { |
||||
startSequence(BG_CODES[index(index, 8, 16)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bgRgb(final int index) { |
||||
startSequence(BG_CODES[index(index, 16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
/** |
||||
* Colors with red-green-blue value, in the range 0 to 6. |
||||
*/ |
||||
public Chalk256 bgRgb(final int r, final int b, final int g) { |
||||
startSequence(BG_CODES[index(36*r + 6*g + b,16, 232)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
public Chalk256 bgGrayscale(final int index) { |
||||
startSequence(BG_CODES[index(index, 232, 256)]); |
||||
endSequence(RESET); |
||||
return _this(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- bgcolors
|
||||
|
||||
private int index(int index, final int from, final int to) { |
||||
index += from; |
||||
if ((index < from) || (index >= to)) { |
||||
throw new IllegalArgumentException("Color index not in range: [0, " + (to - from) + "]"); |
||||
} |
||||
return index; |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Little tool for coloring the console output. |
||||
*/ |
||||
package com.fr.third.jodd.chalk; |
@ -1,233 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.function.Consumer; |
||||
|
||||
public class Cli implements Consumer<String[]> { |
||||
|
||||
private final List<Option> options = new ArrayList<>(); |
||||
private final List<Param> params = new ArrayList<>(); |
||||
|
||||
public Option option() { |
||||
final Option option = new Option(); |
||||
options.add(option); |
||||
return option; |
||||
} |
||||
|
||||
public Param param() { |
||||
final Param param = new Param(); |
||||
params.add(param); |
||||
return param; |
||||
} |
||||
|
||||
private boolean consumeOptionWithLongName(final String input, final String valueToConsume) { |
||||
for (final Option option : options) { |
||||
if (input.equals(option.longName)) { |
||||
if (option.hasArg && valueToConsume == null) { |
||||
throw new CliException("Option value not provided for: " + input); |
||||
} |
||||
option.consumer.accept(option.hasArg ? valueToConsume : input); |
||||
return option.hasArg; |
||||
} |
||||
|
||||
if (option.longName != null && input.startsWith(option.longName + "=")) { |
||||
option.consumer.accept(input.substring(option.longName.length() + 1)); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
throw new CliException("Unknown option: " + input); |
||||
} |
||||
|
||||
private boolean consumeOptionWithShortName(final String input, final String valueToConsume) { |
||||
for (final Option option : options) { |
||||
if (input.equals(option.shortName)) { |
||||
if (option.hasArg) { |
||||
if (valueToConsume == null) { |
||||
throw new CliException("Option value not provided for: " + input); |
||||
} |
||||
option.consumer.accept(valueToConsume); |
||||
return true; |
||||
} |
||||
else { |
||||
option.consumer.accept(input); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
if (option.shortName != null && input.startsWith(option.shortName + "=")) { |
||||
option.consumer.accept(input.substring(option.shortName.length() + 1)); |
||||
return false; |
||||
} |
||||
} |
||||
throw new CliException("Unknown option: " + input); |
||||
} |
||||
|
||||
private void consumeOptionWithShortNameAndNoArguments(final String shortName) { |
||||
for (final Option option : options) { |
||||
if (shortName.equals(option.shortName) && !option.hasArg) { |
||||
option.consumer.accept(shortName); |
||||
return; |
||||
} |
||||
} |
||||
throw new CliException("Unknown option: " + shortName); |
||||
} |
||||
|
||||
@Override |
||||
public void accept(final String... args) { |
||||
assertConfigurationIsValid(); |
||||
|
||||
boolean dontParseOptionsAnyMore = false; |
||||
int i; |
||||
int paramsIndex = 0; |
||||
|
||||
for (i = 0; i < args.length; i++) { |
||||
final String arg = args[i]; |
||||
if (arg.isEmpty()) { |
||||
continue; |
||||
} |
||||
final String value = (i + 1 < args.length) ? args[i + 1] : null; |
||||
|
||||
if (arg.equals("--")) { |
||||
dontParseOptionsAnyMore = true; |
||||
continue; |
||||
} |
||||
|
||||
if (!dontParseOptionsAnyMore) { |
||||
// long names
|
||||
if (arg.startsWith("--")) { |
||||
final String argLongName = arg.substring(2); |
||||
|
||||
consumeOptionWithLongName(argLongName, value); |
||||
|
||||
args[i] = null; |
||||
continue; |
||||
} |
||||
|
||||
// short names
|
||||
if (arg.startsWith("-")) { |
||||
final String argShortName = arg.substring(1); |
||||
|
||||
if (argShortName.length() > 1 && argShortName.charAt(1) != '=') { |
||||
// compressed options
|
||||
final char[] allShortNames = argShortName.toCharArray(); |
||||
for (final char c : allShortNames) { |
||||
final String argName = String.valueOf(c); |
||||
consumeOptionWithShortNameAndNoArguments(argName); |
||||
} |
||||
args[i] = null; |
||||
continue; |
||||
} |
||||
|
||||
final boolean valueConsumed = consumeOptionWithShortName(argShortName, value); |
||||
|
||||
// mark argument as consumed
|
||||
args[i] = null; |
||||
if (valueConsumed) { |
||||
// mark value as consumed, too
|
||||
i++; |
||||
args[i] = null; |
||||
} |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
// params
|
||||
|
||||
if (paramsIndex == params.size()) { |
||||
// we are done here
|
||||
break; |
||||
} |
||||
final Param param = params.get(paramsIndex++); |
||||
|
||||
final List<String> paramArguments = new ArrayList<>(); |
||||
|
||||
int from = 0; |
||||
final int to = param.required + param.optional; |
||||
|
||||
for (; from < to; from++, i++) { |
||||
final String paramValue = (i < args.length) ? args[i] : null; |
||||
if (paramValue == null) { |
||||
break; |
||||
} |
||||
paramArguments.add(paramValue); |
||||
} |
||||
i--; |
||||
|
||||
if (paramArguments.size() < param.required) { |
||||
throw new CliException("Parameter required: " + param.label); |
||||
} |
||||
|
||||
if (paramArguments.isEmpty()) { |
||||
// parameter not found
|
||||
continue; |
||||
} |
||||
|
||||
param.consumer.accept(paramArguments.toArray(new String[0])); |
||||
} |
||||
|
||||
// must check if remaining parameters are not satisfied
|
||||
while (paramsIndex < params.size()) { |
||||
final Param param = params.get(paramsIndex++); |
||||
if (param.required > 0) { |
||||
throw new CliException("Parameter required: " + param.label); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void assertConfigurationIsValid() { |
||||
for (final Option option : options) { |
||||
if (option.consumer == null) { |
||||
throw new CliException("Option has no registered consumer: " + option); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Prints the usage line. |
||||
*/ |
||||
public void printUsage(final String commandName) { |
||||
final StringBuilder usage = new StringBuilder(commandName); |
||||
|
||||
for (final Option option : options) { |
||||
if (option.shortName != null) { |
||||
usage.append(" [-").append(option.shortName).append("]"); |
||||
} else if (option.longName != null) { |
||||
usage.append(" [--").append(option.longName).append("]"); |
||||
} |
||||
} |
||||
|
||||
for (final Param param : params) { |
||||
usage.append(" ").append(param.label); |
||||
} |
||||
|
||||
System.out.println(usage); |
||||
} |
||||
|
||||
} |
@ -1,37 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import com.fr.third.jodd.exception.UncheckedException; |
||||
|
||||
/** |
||||
* CLI exception. |
||||
*/ |
||||
public class CliException extends UncheckedException { |
||||
public CliException(final String message) { |
||||
super(message); |
||||
} |
||||
} |
@ -1,96 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import java.util.function.Consumer; |
||||
|
||||
public class Option { |
||||
|
||||
String label; |
||||
String shortName; |
||||
String longName; |
||||
String description; |
||||
boolean hasArg; |
||||
String argLabel; |
||||
Consumer<String> consumer; |
||||
|
||||
public Option shortName(final String shortName) { |
||||
this.shortName = shortName; |
||||
return this; |
||||
} |
||||
|
||||
public Option longName(final String longName) { |
||||
this.longName = longName; |
||||
return this; |
||||
} |
||||
|
||||
public Option names(final String shortName, final String longName) { |
||||
this.shortName = shortName; |
||||
this.longName = longName; |
||||
return this; |
||||
} |
||||
|
||||
public Option description(final String description) { |
||||
this.description = description; |
||||
return this; |
||||
} |
||||
|
||||
public Option hasArg() { |
||||
this.hasArg = true; |
||||
return this; |
||||
} |
||||
|
||||
public Option hasArg(final String argLabel) { |
||||
this.hasArg = true; |
||||
this.argLabel = argLabel; |
||||
return this; |
||||
} |
||||
|
||||
public Option label(final String label) { |
||||
this.label = label; |
||||
return this; |
||||
} |
||||
|
||||
public Option with(final Consumer<String> consumer) { |
||||
this.consumer = consumer; |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
String out = ""; |
||||
if (shortName != null) { |
||||
out += "-" + shortName; |
||||
} |
||||
if (longName != null) { |
||||
if (!out.isEmpty()) { |
||||
out += " | "; |
||||
} |
||||
out += "--" + longName; |
||||
} |
||||
return out; |
||||
} |
||||
} |
@ -1,84 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.cli; |
||||
|
||||
import java.util.function.Consumer; |
||||
|
||||
public class Param { |
||||
String label; |
||||
int required = 0; |
||||
int optional = 1; |
||||
String description; |
||||
Consumer<String[]> consumer; |
||||
|
||||
public Param required(final int required) { |
||||
this.required = required; |
||||
return this; |
||||
} |
||||
|
||||
public Param optional(final int optional) { |
||||
this.optional = optional; |
||||
return this; |
||||
} |
||||
|
||||
public Param required() { |
||||
this.required = 1; |
||||
this.optional = 0; |
||||
return this; |
||||
} |
||||
|
||||
public Param optional() { |
||||
this.required = 0; |
||||
this.optional = 1; |
||||
return this; |
||||
} |
||||
|
||||
public Param all() { |
||||
this.optional = 1_000_000; // magic number indicating *ALL* parameters
|
||||
return this; |
||||
} |
||||
|
||||
public Param range(final int required, final int max) { |
||||
this.required = required; |
||||
this.optional = max - required; |
||||
return this; |
||||
} |
||||
|
||||
public Param label(final String label) { |
||||
this.label = label; |
||||
return this; |
||||
} |
||||
|
||||
public Param description(final String description) { |
||||
this.description = description; |
||||
return this; |
||||
} |
||||
|
||||
public Param with(final Consumer<String[]> consumer) { |
||||
this.consumer = consumer; |
||||
return this; |
||||
} |
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Small parser for command line arguments. |
||||
*/ |
||||
package com.fr.third.jodd.cli; |
@ -1,65 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.core; |
||||
|
||||
import com.fr.third.jodd.util.StringPool; |
||||
|
||||
import java.security.Security; |
||||
|
||||
/** |
||||
* Jodd library-wide properties. |
||||
*/ |
||||
public class JoddCore { |
||||
|
||||
static { |
||||
// Starting from Java8 u151, the `Unlimited Strength Jurisdiction Policy Files`
|
||||
// are included with Java, but has to be enabled.
|
||||
// They are enabled on Java9 by default.
|
||||
Security.setProperty("crypto.policy", "unlimited"); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- settings
|
||||
|
||||
/** |
||||
* Default prefix for temporary files. |
||||
*/ |
||||
public static String tempFilePrefix = "jodd-"; |
||||
|
||||
/** |
||||
* The encoding used across the Jodd classes, "UTF-8" by default. |
||||
*/ |
||||
public static String encoding = StringPool.UTF_8; |
||||
|
||||
/** |
||||
* Buffer size for various I/O operations. |
||||
*/ |
||||
public static int ioBufferSize = 16384; |
||||
/** |
||||
* Flag that controls the {@code Unsafe} usage (if system detects it). Enabled by default. |
||||
*/ |
||||
public static boolean unsafeUsageEnabled = true; |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Jodd Core module. |
||||
*/ |
||||
package com.fr.third.jodd.core; |
@ -1,303 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import com.fr.third.jodd.util.HashCode; |
||||
import static com.fr.third.jodd.util.HashCode.hash; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* Generic date time stamp just stores and holds date and time information. |
||||
* This class does not contain any date/time logic, neither guarantees |
||||
* that date is valid. |
||||
* |
||||
* @see JDateTime |
||||
* @see JulianDateStamp |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class DateTimeStamp implements Comparable, Serializable, Cloneable { |
||||
|
||||
/** |
||||
* Default empty constructor. |
||||
*/ |
||||
public DateTimeStamp() { |
||||
} |
||||
|
||||
/** |
||||
* Constructor that sets date and time. |
||||
*/ |
||||
public DateTimeStamp(int year, int month, int day, int hour, int minute, int second, int millisecond) { |
||||
this.year = year; |
||||
this.month = month; |
||||
this.day = day; |
||||
this.hour = hour; |
||||
this.minute = minute; |
||||
this.second = second; |
||||
this.millisecond = millisecond; |
||||
} |
||||
|
||||
/** |
||||
* Constructor that sets just date. Time is set to zeros. |
||||
*/ |
||||
public DateTimeStamp(int year, int month, int day) { |
||||
this(year, month, day, 0, 0, 0, 0); |
||||
} |
||||
|
||||
/** |
||||
* Year. |
||||
*/ |
||||
public int year; |
||||
|
||||
/** |
||||
* Month, range: [1 - 12] |
||||
*/ |
||||
public int month = 1; |
||||
|
||||
/** |
||||
* Day, range: [1 - 31] |
||||
*/ |
||||
public int day = 1; |
||||
|
||||
/** |
||||
* Hour, range: [0 - 23] |
||||
*/ |
||||
public int hour; |
||||
|
||||
/** |
||||
* Minute, range [0 - 59] |
||||
*/ |
||||
public int minute; |
||||
|
||||
/** |
||||
* Second, range: [0 - 59] |
||||
*/ |
||||
public int second; |
||||
|
||||
/** |
||||
* Millisecond, range: [0 - 1000] |
||||
*/ |
||||
public int millisecond; |
||||
|
||||
|
||||
// ---------------------------------------------------------------- get/set
|
||||
|
||||
public int getYear() { |
||||
return year; |
||||
} |
||||
|
||||
public void setYear(int year) { |
||||
this.year = year; |
||||
} |
||||
|
||||
public int getMonth() { |
||||
return month; |
||||
} |
||||
|
||||
public void setMonth(int month) { |
||||
this.month = month; |
||||
} |
||||
|
||||
public int getDay() { |
||||
return day; |
||||
} |
||||
|
||||
public void setDay(int day) { |
||||
this.day = day; |
||||
} |
||||
|
||||
public int getHour() { |
||||
return hour; |
||||
} |
||||
|
||||
public void setHour(int hour) { |
||||
this.hour = hour; |
||||
} |
||||
|
||||
public int getMinute() { |
||||
return minute; |
||||
} |
||||
|
||||
public void setMinute(int minute) { |
||||
this.minute = minute; |
||||
} |
||||
|
||||
public int getSecond() { |
||||
return second; |
||||
} |
||||
|
||||
public void setSecond(int second) { |
||||
this.second = second; |
||||
} |
||||
|
||||
public int getMillisecond() { |
||||
return millisecond; |
||||
} |
||||
|
||||
public void setMillisecond(int millisecond) { |
||||
this.millisecond = millisecond; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- compare
|
||||
|
||||
/** |
||||
* Compares this object with the specified object for order. Returns a |
||||
* negative integer, zero, or a positive integer as this object is less |
||||
* than, equal to, or greater than the specified object. |
||||
* |
||||
* @param o the Object to be compared. |
||||
* @return a negative integer, zero, or a positive integer as this object |
||||
* is less than, equal to, or greater than the specified object. |
||||
* |
||||
* @throws ClassCastException if the specified object's type prevents it |
||||
* from being compared to this Object. |
||||
*/ |
||||
public int compareTo(Object o) { |
||||
DateTimeStamp dts = (DateTimeStamp) o; |
||||
|
||||
int date1 = year * 10000 + month * 100 + day; |
||||
int date2 = dts.year * 10000 + dts.month * 100 + dts.day; |
||||
|
||||
if (date1 < date2) { |
||||
return -1; |
||||
} |
||||
if (date1 > date2) { |
||||
return 1; |
||||
} |
||||
|
||||
date1 = (hour * 10000000) + (minute * 100000) + (second * 1000) + millisecond; |
||||
date2 = (dts.hour * 10000000) + (dts.minute * 100000) + (dts.second * 1000) + dts.millisecond; |
||||
|
||||
if (date1 < date2) { |
||||
return -1; |
||||
} |
||||
if (date1 > date2) { |
||||
return 1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
/** |
||||
* Compares just date component of two date time stamps. |
||||
*/ |
||||
public int compareDateTo(Object o) { |
||||
DateTimeStamp dts = (DateTimeStamp) o; |
||||
|
||||
int date1 = year * 10000 + month * 100 + day; |
||||
int date2 = dts.year * 10000 + dts.month * 100 + dts.day; |
||||
|
||||
if (date1 < date2) { |
||||
return -1; |
||||
} |
||||
if (date1 > date2) { |
||||
return 1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- toString
|
||||
|
||||
/** |
||||
* Simple to string conversion. |
||||
* |
||||
* @return date/time string in 'y-m-d h:m:m.s' format |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new StringBuilder(25).append(year).append('-').append(month) |
||||
.append('-').append(day).append(' ').append(hour).append(':') |
||||
.append(minute).append(':').append(second).append('.') |
||||
.append(millisecond).toString(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- equals & hashCode
|
||||
|
||||
@Override |
||||
public boolean equals(Object object) { |
||||
if (this == object) { |
||||
return true; |
||||
} |
||||
if (this.getClass() != object.getClass()) { |
||||
return false; |
||||
} |
||||
DateTimeStamp stamp = (DateTimeStamp) object; |
||||
return (stamp.year == this.year) && |
||||
(stamp.month == this.month) && |
||||
(stamp.day == this.day) && |
||||
(stamp.hour == this.hour) && |
||||
(stamp.minute == this.minute) && |
||||
(stamp.second == this.second) && |
||||
(stamp.millisecond == this.millisecond); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int result = HashCode.SEED; |
||||
result = hash(result, year); |
||||
result = hash(result, month); |
||||
result = hash(result, day); |
||||
result = hash(result, hour); |
||||
result = hash(result, minute); |
||||
result = hash(result, second); |
||||
result = hash(result, millisecond); |
||||
return result; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- clone
|
||||
|
||||
|
||||
@Override |
||||
protected DateTimeStamp clone() { |
||||
DateTimeStamp dts = new DateTimeStamp(); |
||||
dts.year = this.year; |
||||
dts.month = this.month; |
||||
dts.day = this.day; |
||||
dts.hour = this.hour; |
||||
dts.minute = this.minute; |
||||
dts.second = this.second; |
||||
dts.millisecond = this.millisecond; |
||||
return dts; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- equals
|
||||
|
||||
public boolean isEqualDate(DateTimeStamp date) { |
||||
return date.day == this.day |
||||
&& date.month == this.month |
||||
&& date.year == this.year; |
||||
} |
||||
|
||||
public boolean isEqualTime(DateTimeStamp time) { |
||||
return time.hour == this.hour |
||||
&& time.minute == this.minute |
||||
&& time.second == this.second |
||||
&& time.millisecond == this.millisecond; |
||||
} |
||||
|
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,88 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import com.fr.third.jodd.datetime.format.Iso8601JdtFormatter; |
||||
import com.fr.third.jodd.datetime.format.JdtFormatter; |
||||
|
||||
import java.util.TimeZone; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* Defaults for {@link JDateTime}. |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
@SuppressWarnings({"RedundantFieldInitialization"}) |
||||
public class JDateTimeDefault { |
||||
|
||||
/** |
||||
* Default value for month fix. |
||||
*/ |
||||
public static boolean monthFix = true; |
||||
|
||||
/** |
||||
* Default time zone. Set it to <code>null</code> |
||||
* for system default timezone. |
||||
*/ |
||||
public static TimeZone timeZone = null; // system default
|
||||
|
||||
/** |
||||
* Default locale for date names. Set it to <code>null</code> |
||||
* for system default locale. |
||||
*/ |
||||
public static Locale locale = null; // system default
|
||||
|
||||
/** |
||||
* Default format template. |
||||
*/ |
||||
public static String format = JDateTime.DEFAULT_FORMAT; |
||||
|
||||
/** |
||||
* Default formatter. |
||||
*/ |
||||
public static JdtFormatter formatter = new Iso8601JdtFormatter(); |
||||
|
||||
/** |
||||
* Default definition of first day of week. |
||||
*/ |
||||
public static int firstDayOfWeek = JDateTime.MONDAY; |
||||
|
||||
/** |
||||
* Default number of days first week of year must have. |
||||
*/ |
||||
public static int mustHaveDayOfFirstWeek = 4; |
||||
|
||||
/** |
||||
* Default minimal number of days firs week of year must have. |
||||
*/ |
||||
public static int minDaysInFirstWeek = 4; |
||||
|
||||
/** |
||||
* Default value for tracking DST. |
||||
*/ |
||||
public static boolean trackDST = false; |
||||
} |
@ -1,302 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import java.util.List; |
||||
import java.util.ArrayList; |
||||
|
||||
/** |
||||
* Nice thread-aware stopwatch that supports time spans, cumulative times and laps. |
||||
* Useful for all kind of profiling, time measurements etc. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class JStopWatch { |
||||
|
||||
/** |
||||
* Optional stopwatch name. |
||||
*/ |
||||
protected String name; |
||||
/** |
||||
* Last start time. |
||||
*/ |
||||
protected long startTime; |
||||
/** |
||||
* Last stop time. |
||||
*/ |
||||
protected long stopTime; |
||||
/** |
||||
* Last elapsed time. |
||||
*/ |
||||
protected long spanTime; |
||||
/** |
||||
* Cumulative elapsed time. |
||||
*/ |
||||
protected long totalTime; |
||||
/** |
||||
* Running flag. |
||||
*/ |
||||
protected boolean running; |
||||
|
||||
// ---------------------------------------------------------------- ctors
|
||||
|
||||
/** |
||||
* Starts the stopwatch. |
||||
*/ |
||||
public JStopWatch() { |
||||
this("#jStopWatch"); |
||||
} |
||||
|
||||
/** |
||||
* Starts the named stopwatch. |
||||
*/ |
||||
public JStopWatch(String name) { |
||||
this.name = name; |
||||
start(); |
||||
} |
||||
|
||||
/** |
||||
* Returns stopwatch name. |
||||
*/ |
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if stopwatch is running. |
||||
*/ |
||||
public boolean isRunning() { |
||||
return running; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- basic
|
||||
|
||||
/** |
||||
* Starts the stopwatch. {@link #stop()} must be called prior to restart. |
||||
* Returns starting time in milliseconds. |
||||
*/ |
||||
public long start() { |
||||
if (!running) { |
||||
startTime = System.currentTimeMillis(); |
||||
running = true; |
||||
} |
||||
return startTime; |
||||
} |
||||
|
||||
/** |
||||
* Restarts the stopwatch. |
||||
*/ |
||||
public long restart() { |
||||
startTime = System.currentTimeMillis(); |
||||
running = true; |
||||
return startTime; |
||||
} |
||||
|
||||
/** |
||||
* Stops the stopwatch if running. Returns span time. |
||||
* If laps are used, marks the last lap. |
||||
*/ |
||||
public long stop() { |
||||
if (running) { |
||||
stopTime = System.currentTimeMillis(); |
||||
if (laps != null) { |
||||
lap(stopTime); |
||||
} |
||||
spanTime = stopTime - startTime; |
||||
totalTime += stopTime - startTime; |
||||
running = false; |
||||
} |
||||
return spanTime; |
||||
} |
||||
|
||||
/** |
||||
* Returns total elapsed time from the {@link #start()} in ms. |
||||
*/ |
||||
public long elapsed() { |
||||
return System.currentTimeMillis() - startTime; |
||||
} |
||||
|
||||
/** |
||||
* Stops the stopwatch and returns total cumulative time in ms. |
||||
*/ |
||||
public long total() { |
||||
stop(); |
||||
return totalTime; |
||||
} |
||||
|
||||
/** |
||||
* Stops the stopwatch and returns total time span for last |
||||
* start-stop sequence. |
||||
*/ |
||||
public long span() { |
||||
stop(); |
||||
return spanTime; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- laps
|
||||
|
||||
/** |
||||
* List of all laps. Contains long arrays in following format: |
||||
* <ul> |
||||
* <li>lap time - current lap time,</li> |
||||
* <li>lap span time - elapsed time from start,</li> |
||||
* <li>lap millis - lap milliseconds. |
||||
* </ul> |
||||
*/ |
||||
protected List<long[]> laps; |
||||
|
||||
/** |
||||
* Marks a lap and returns its length. May be called only while stop watch is running. |
||||
*/ |
||||
public long lap() { |
||||
return lap(System.currentTimeMillis()); |
||||
} |
||||
|
||||
protected long lap(long lap) { |
||||
if (!running) { |
||||
return 0; |
||||
} |
||||
long lapSpanTime = lap - startTime; |
||||
long lapTime; |
||||
if (laps == null) { |
||||
lapTime = lapSpanTime; |
||||
laps = new ArrayList<long[]>(); |
||||
} else { |
||||
long[] previous = laps.get(laps.size() - 1); |
||||
lapTime = lap - previous[2]; |
||||
} |
||||
laps.add(new long[] {lapTime, lapSpanTime, lap}); |
||||
return lapTime; |
||||
} |
||||
|
||||
/** |
||||
* Returns the total number of laps up to this moment. |
||||
*/ |
||||
public int totalLaps() { |
||||
if (laps == null) { |
||||
return 0; |
||||
} |
||||
return laps.size(); |
||||
} |
||||
|
||||
/** |
||||
* Returns lap times for 1-based lap index. |
||||
* Returns <code>null</code> if laps are not used or if index is invalid. |
||||
*/ |
||||
public long[] getLapTimes(int index) { |
||||
if (laps == null) { |
||||
return null; |
||||
} |
||||
if ((index <= 0) || (index > laps.size())) { |
||||
return null; |
||||
} |
||||
return laps.get(index - 1); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- output
|
||||
|
||||
/** |
||||
* Returns total elapsed time as formatted string from the last start. |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
long elapsed = elapsed(); |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("JStopWatch ").append(name).append(running ? " is running." : "").append('\n'); |
||||
if (running) { |
||||
sb.append("elapsed: ").append(formatTimeSpan(elapsed)); |
||||
} else { |
||||
if (spanTime != totalTime) { |
||||
sb.append("span: ").append(formatTimeSpan(spanTime)).append('\n'); |
||||
} |
||||
sb.append("\ntotal: ").append(formatTimeSpan(totalTime)); |
||||
} |
||||
if (laps != null) { |
||||
if (!laps.isEmpty()) { |
||||
sb.append('\n'); |
||||
sb.append("\n\t\t\tlap\t\telapsed\n"); |
||||
} |
||||
for (int i = 0; i < laps.size(); i++) { |
||||
long[] longs = laps.get(i); |
||||
sb.append(" lap #").append(i + 1).append(':').append('\t'); |
||||
sb.append(formatTimeSpan(longs[0])).append('\t'); |
||||
sb.append(formatTimeSpan(longs[1])).append('\n'); |
||||
} |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Formats time spans. |
||||
*/ |
||||
public static String formatTimeSpan(long millis) { |
||||
long seconds = 0; |
||||
long minutes = 0; |
||||
long hours = 0; |
||||
|
||||
if (millis > 1000) { |
||||
seconds = millis / 1000; |
||||
millis %= 1000; |
||||
} |
||||
if (seconds > 60) { |
||||
minutes = seconds / 60; |
||||
seconds %= 60; |
||||
} |
||||
if (minutes > 60) { |
||||
hours = minutes / 60; |
||||
minutes %= 60; |
||||
} |
||||
|
||||
StringBuilder result = new StringBuilder(20); |
||||
boolean out = false; |
||||
if (hours > 0) { |
||||
result.append(hours).append(':'); |
||||
out = true; |
||||
} |
||||
if (out || (minutes > 0)) { |
||||
if (minutes < 10) { |
||||
result.append('0'); |
||||
} |
||||
result.append(minutes).append(':'); |
||||
} |
||||
|
||||
if (seconds < 10) { |
||||
result.append('0'); |
||||
} |
||||
result.append(seconds).append('.'); |
||||
|
||||
if (millis < 10) { |
||||
result.append('0'); |
||||
} |
||||
if (millis < 100) { |
||||
result.append('0'); |
||||
} |
||||
result.append(millis); |
||||
return result.toString(); |
||||
} |
||||
} |
@ -1,337 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import com.fr.third.jodd.util.HashCode; |
||||
import static com.fr.third.jodd.util.HashCode.hash; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* Julian Date stamp, for high precision calculations. Julian date is a real |
||||
* number and it basically consist of two parts: integer and fraction. Integer |
||||
* part carries date information, fraction carries time information. |
||||
* |
||||
* <p> |
||||
* The Julian day or Julian day number (JDN) is the (integer) number of days that |
||||
* have elapsed since Monday, January 1, 4713 BC in the proleptic Julian calendar 1. |
||||
* That day is counted as Julian day zero. Thus the multiples of 7 are Mondays. |
||||
* Negative values can also be used. |
||||
* |
||||
* <p> |
||||
* The Julian Date (JD) is the number of days (with decimal fraction of the day) that |
||||
* have elapsed since 12 noon Greenwich Mean Time (UT or TT) of that day. |
||||
* Rounding to the nearest integer gives the Julian day number. |
||||
* <p> |
||||
* For calculations that will have time precision of 1e-3 seconds, both |
||||
* fraction and integer part must have enough digits in it. The problem is |
||||
* that integer part is big and, on the other hand fractional is small, and |
||||
* since final julian date is a sum of this two values, some fraction |
||||
* numerals may be lost. Therefore, for higher precision both |
||||
* fractional and integer part of julian date real number has to be |
||||
* preserved. |
||||
* <p> |
||||
* This class stores the unmodified fraction part, but not all digits |
||||
* are significant! For 1e-3 seconds precision, only 8 digits after |
||||
* the decimal point are significant. |
||||
* |
||||
* @see TimeUtil |
||||
* @see JDateTime |
||||
* @see DateTimeStamp |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class JulianDateStamp implements Serializable, Cloneable { |
||||
|
||||
/** |
||||
* Integer part of the Julian Date (JD). |
||||
*/ |
||||
protected int integer; |
||||
|
||||
/** |
||||
* Returns integer part of the Julian Date (JD). |
||||
*/ |
||||
public int getInteger() { |
||||
return integer; |
||||
} |
||||
|
||||
/** |
||||
* Fraction part of the Julian Date (JD). |
||||
* Should be always in [0.0, 1.0) range. |
||||
*/ |
||||
protected double fraction; |
||||
|
||||
/** |
||||
* Returns the fraction part of Julian Date (JD). |
||||
* Returned value is always in [0.0, 1.0) range. |
||||
*/ |
||||
public double getFraction() { |
||||
return fraction; |
||||
} |
||||
|
||||
/** |
||||
* Calculates and returns significant fraction only as an int. |
||||
*/ |
||||
public int getSignificantFraction() { |
||||
return (int) (fraction * 100000000); |
||||
} |
||||
|
||||
/** |
||||
* Returns JDN. Note that JDN is not equal to {@link #integer}. It is calculated by |
||||
* rounding to the nearest integer. |
||||
*/ |
||||
public int getJulianDayNumber() { |
||||
if (fraction >= 0.5) { |
||||
return integer + 1; |
||||
} |
||||
return integer; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- ctors
|
||||
|
||||
/** |
||||
* Default empty constructor. |
||||
*/ |
||||
public JulianDateStamp() { |
||||
} |
||||
|
||||
/** |
||||
* Creates JD from a <code>double</code>. |
||||
*/ |
||||
public JulianDateStamp(double jd) { |
||||
set(jd); |
||||
} |
||||
|
||||
/** |
||||
* Creates JD from both integer and fractional part using normalization. |
||||
* Normalization occurs when fractional part is out of range. |
||||
* |
||||
* @see #set(int, double) |
||||
* |
||||
* @param i integer part |
||||
* @param f fractional part should be in range [0.0, 1.0) |
||||
*/ |
||||
public JulianDateStamp(int i, double f) { |
||||
set(i, f); |
||||
} |
||||
|
||||
/** |
||||
* Creates JD from <code>BigDecimal</code>. |
||||
*/ |
||||
public JulianDateStamp(BigDecimal bd) { |
||||
double d = bd.doubleValue(); |
||||
integer = (int) d; |
||||
bd = bd.subtract(new BigDecimal(integer)); |
||||
fraction = bd.doubleValue(); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- conversion
|
||||
|
||||
|
||||
/** |
||||
* Returns <code>double</code> value of JD. |
||||
* <b>CAUTION</b>: double values may not be suit for precision math due to |
||||
* loss of precision. |
||||
*/ |
||||
public double doubleValue() { |
||||
return (double)integer + fraction; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>BigDecimal</code> value of JD. |
||||
*/ |
||||
@SuppressWarnings({"UnpredictableBigDecimalConstructorCall"}) |
||||
public BigDecimal toBigDecimal() { |
||||
BigDecimal bd = new BigDecimal(integer); |
||||
return bd.add(new BigDecimal(fraction)); |
||||
} |
||||
|
||||
/** |
||||
* Returns string representation of JD. |
||||
* |
||||
* @return julian integer as string |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
String s = Double.toString(fraction); |
||||
int i = s.indexOf('.'); |
||||
s = s.substring(i); |
||||
return integer + s; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- math
|
||||
|
||||
/** |
||||
* Adds a JD to current instance. |
||||
*/ |
||||
public JulianDateStamp add(JulianDateStamp jds) { |
||||
int i = this.integer + jds.integer; |
||||
double f = this.fraction + jds.fraction; |
||||
set(i, f); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Adds a double to current instance. |
||||
*/ |
||||
public JulianDateStamp add(double delta) { |
||||
set(this.integer, this.fraction + delta); |
||||
return this; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Subtracts a JD from current instance. |
||||
*/ |
||||
public JulianDateStamp sub(JulianDateStamp jds) { |
||||
int i = this.integer - jds.integer; |
||||
double f = this.fraction -jds.fraction; |
||||
set(i, f); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Subtracts a double from current instance. |
||||
*/ |
||||
public JulianDateStamp sub(double delta) { |
||||
set(this.integer, this.fraction - delta); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Sets integer and fractional part with normalization. |
||||
* Normalization means that if double is out of range, |
||||
* values will be correctly fixed. |
||||
*/ |
||||
public void set(int i, double f) { |
||||
integer = i; |
||||
int fi = (int) f; |
||||
f -= fi; |
||||
integer += fi; |
||||
if (f < 0) { |
||||
f += 1; |
||||
integer--; |
||||
} |
||||
this.fraction = f; |
||||
} |
||||
|
||||
public void set(double jd) { |
||||
integer = (int)jd; |
||||
fraction = jd - (double)integer; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- between
|
||||
|
||||
/** |
||||
* Calculates the number of days between two dates. Returned value is always positive. |
||||
*/ |
||||
public int daysBetween(JulianDateStamp otherDate) { |
||||
int difference = daysSpan(otherDate); |
||||
return difference >= 0 ? difference : -difference; |
||||
} |
||||
|
||||
/** |
||||
* Returns span between two days. Returned value may be positive (when this date |
||||
* is after the provided one) or negative (when comparing to future date). |
||||
*/ |
||||
public int daysSpan(JulianDateStamp otherDate) { |
||||
int now = getJulianDayNumber(); |
||||
int then = otherDate.getJulianDayNumber(); |
||||
return now - then; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- equals & hashCode
|
||||
|
||||
@Override |
||||
public boolean equals(Object object) { |
||||
if (this == object) { |
||||
return true; |
||||
} |
||||
if (this.getClass() != object.getClass()) { |
||||
return false; |
||||
} |
||||
JulianDateStamp stamp = (JulianDateStamp) object; |
||||
return (stamp.integer == this.integer) && |
||||
(Double.compare(stamp.fraction, this.fraction) == 0); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int result = HashCode.SEED; |
||||
result = hash(result, integer); |
||||
result = hash(result, fraction); |
||||
return result; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- clone
|
||||
|
||||
@Override |
||||
protected JulianDateStamp clone() { |
||||
return new JulianDateStamp(this.integer, this.fraction); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- conversion
|
||||
|
||||
/** |
||||
* Returns Reduced Julian Date (RJD), used by astronomers. |
||||
* RJD = JD − 2400000 |
||||
*/ |
||||
public JulianDateStamp getReducedJulianDate() { |
||||
return new JulianDateStamp(integer - 2400000, fraction); |
||||
} |
||||
|
||||
public void setReducedJulianDate(double rjd) { |
||||
set(rjd + 2400000); |
||||
} |
||||
|
||||
/** |
||||
* Returns Modified Julian Date (MJD), where date starts from midnight rather than noon. |
||||
* RJD = JD − 2400000.5 |
||||
*/ |
||||
public JulianDateStamp getModifiedJulianDate() { |
||||
return new JulianDateStamp(integer - 2400000, fraction - 0.5); |
||||
} |
||||
|
||||
public void setModifiedJulianDate(double mjd) { |
||||
set(mjd + 2400000.5); |
||||
} |
||||
|
||||
/** |
||||
* Returns Truncated Julian Day (TJD), introduced by NASA for the space program. |
||||
* TJD began at midnight at the beginning of May 24, 1968 (Friday). |
||||
*/ |
||||
public JulianDateStamp getTruncatedJulianDate() { |
||||
return new JulianDateStamp(integer - 2440000, fraction - 0.5); |
||||
} |
||||
|
||||
public void setTruncatedJulianDate(double tjd) { |
||||
set(tjd + 2440000.5); |
||||
} |
||||
} |
@ -1,118 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
/** |
||||
* Holds a time period. With julian dates and {@link JDateTime} it is quite |
||||
* easy to calculate period in days - just by subtracting two julian day numbers. |
||||
* However, calculating hours, minutes and seconds would require more calculation |
||||
* and this class provides simple and faster period calculation. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class Period { |
||||
|
||||
protected final long days; |
||||
protected final int hours; |
||||
protected final int minutes; |
||||
protected final int seconds; |
||||
protected final int milliseconds; |
||||
|
||||
public Period(JDateTime jdt1, JDateTime jdt2) { |
||||
if (jdt2.isBefore(jdt1)) { |
||||
JDateTime temp = jdt1; |
||||
jdt1 = jdt2; |
||||
jdt2 = temp; |
||||
} |
||||
long julian2 = jdt2.getJulianDayNumber(); |
||||
long julian1 = jdt1.getJulianDayNumber(); |
||||
|
||||
long days = julian2 - julian1; |
||||
int milliseconds = jdt2.getMillisecond() - jdt1.getMillisecond(); |
||||
int seconds = jdt2.getSecond() - jdt1.getSecond(); |
||||
int minutes = jdt2.getMinute() - jdt1.getMinute(); |
||||
int hours = jdt2.getHour() - jdt1.getHour(); |
||||
|
||||
if (milliseconds < 0) { |
||||
seconds--; |
||||
milliseconds += 1000; |
||||
} |
||||
if (seconds < 0) { |
||||
minutes--; |
||||
seconds += 60; |
||||
} |
||||
if (minutes < 0) { |
||||
hours--; |
||||
minutes += 60; |
||||
} |
||||
if (hours < 0) { |
||||
days--; |
||||
hours += 24; |
||||
} |
||||
|
||||
this.days = days; |
||||
this.hours = hours; |
||||
this.minutes = minutes; |
||||
this.seconds = seconds; |
||||
this.milliseconds = milliseconds; |
||||
} |
||||
|
||||
/** |
||||
* Returns number of days in period. |
||||
*/ |
||||
public long getDays() { |
||||
return days; |
||||
} |
||||
|
||||
/** |
||||
* Returns hours in period. |
||||
*/ |
||||
public int getHours() { |
||||
return hours; |
||||
} |
||||
|
||||
/** |
||||
* Returns minutes in period. |
||||
*/ |
||||
public int getMinutes() { |
||||
return minutes; |
||||
} |
||||
|
||||
/** |
||||
* Returns seconds in period. |
||||
*/ |
||||
public int getSeconds() { |
||||
return seconds; |
||||
} |
||||
|
||||
/** |
||||
* Returns milliseconds in period. |
||||
*/ |
||||
public int getMilliseconds() { |
||||
return milliseconds; |
||||
} |
||||
} |
@ -1,398 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* Date time calculations and utilities. <code>TimeUtil</code> is used by |
||||
* {@link JDateTime} and it contains few utilities that may be used |
||||
* elsewhere, although {@link JDateTime} is recommended for all time |
||||
* manipulation. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class TimeUtil { |
||||
|
||||
public static final int SECONDS_IN_DAY = 60 * 60 * 24; |
||||
|
||||
public static final long MILLIS_IN_DAY = 1000L * SECONDS_IN_DAY; |
||||
|
||||
// ---------------------------------------------------------------- misc calc
|
||||
|
||||
/** |
||||
* Calculates day of year from given time stamp. |
||||
* It may not work for some dates in 1582. |
||||
* |
||||
* @return day of year in range: [1-366] |
||||
*/ |
||||
public static int dayOfYear(int year, int month, int day) { |
||||
int day_of_year; |
||||
if (isLeapYear(year)) { |
||||
day_of_year = ((275 * month) / 9) - ((month + 9) / 12) + day - 30; |
||||
} else { |
||||
day_of_year = ((275 * month) / 9) - (((month + 9) / 12) << 1) + day - 30; |
||||
} |
||||
return day_of_year; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Check if the given year is leap year. |
||||
* |
||||
* @return <code>true</code> if the year is a leap year |
||||
*/ |
||||
public static boolean isLeapYear(int y) { |
||||
boolean result = false; |
||||
|
||||
if (((y % 4) == 0) && // must be divisible by 4...
|
||||
((y < 1582) || // and either before reform year...
|
||||
((y % 100) != 0) || // or not a century...
|
||||
((y % 400) == 0))) { // or a multiple of 400...
|
||||
result = true; // for leap year.
|
||||
} |
||||
return result; |
||||
} |
||||
|
||||
static final int[] MONTH_LENGTH = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
||||
|
||||
/** |
||||
* Returns the length of the specified month in days. Month is 1 for January |
||||
* and 12 for December. |
||||
* |
||||
* @return length of the specified month in days |
||||
*/ |
||||
public static int getMonthLength(int year, int month) { |
||||
return getMonthLength(year, month, isLeapYear(year)); |
||||
} |
||||
|
||||
static int getMonthLength(int year, int month, boolean leap) { |
||||
if ((month < 1) || (month > 12)) { |
||||
throw new IllegalArgumentException("Invalid month: " + month); |
||||
} |
||||
if (month == 2) { |
||||
return leap ? 29 : 28; |
||||
} |
||||
if ((year == 1582) && (month == 10)) { |
||||
return 21; |
||||
} |
||||
return MONTH_LENGTH[month]; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- valid
|
||||
|
||||
/** |
||||
* Checks if date is valid. |
||||
* |
||||
* @return <code>true</code> if date is valid, otherwise <code>false</code> |
||||
*/ |
||||
public static boolean isValidDate(int year, int month, int day) { |
||||
if ((month < 1) || (month > 12)) { |
||||
return false; |
||||
} |
||||
int ml = getMonthLength(year, month); |
||||
//noinspection RedundantIfStatement
|
||||
if ((day < 1) || (day > ml)) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Checks if time is valid. |
||||
* |
||||
* @param hour hour to check |
||||
* @param minute minute to check |
||||
* @param second second to check |
||||
* |
||||
* @return <code>true</code> if time is valid, otherwise <code>false</code> |
||||
*/ |
||||
public static boolean isValidTime(int hour, int minute, int second, int millisecond) { |
||||
if ((hour < 0) || (hour >= 24)) { |
||||
return false; |
||||
} |
||||
if ((minute < 0) || (minute >= 60)) { |
||||
return false; |
||||
} |
||||
if ((second < 0) || (second >= 60)) { |
||||
return false; |
||||
} |
||||
//noinspection RedundantIfStatement
|
||||
if ((millisecond < 0) || (millisecond >= 1000)) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Checks if date and time are valid. |
||||
* |
||||
* @param year year to check |
||||
* @param month month to check |
||||
* @param day day to check |
||||
* @param hour hour to check |
||||
* @param minute minute to check |
||||
* @param second second to check |
||||
* |
||||
* @return <code>true</code> if date and time are valid, otherwise <code>false</code> |
||||
*/ |
||||
public static boolean isValidDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond) { |
||||
return (isValidDate(year, month, day) && isValidTime(hour, minute, second, millisecond)); |
||||
} |
||||
|
||||
/** |
||||
* Checks if date and time are valid. |
||||
* |
||||
* @param dts date/time stamp |
||||
* |
||||
* @return <code>true</code> if date and time are valid, otherwise <code>false</code> |
||||
*/ |
||||
public static boolean isValidDateTime(DateTimeStamp dts) { |
||||
return (isValidDate(dts.year, dts.month, dts.day) && isValidTime(dts.hour, dts.minute, dts.second, dts.millisecond)); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- julian date
|
||||
|
||||
/** |
||||
* Calculates Astronomical Julian Date from given time stamp. |
||||
* |
||||
* @return Julian Date stamp |
||||
*/ |
||||
public static JulianDateStamp toJulianDate(DateTimeStamp time) { |
||||
return toJulianDate(time.year, time.month, time.day, time.hour, time.minute, time.second, time.millisecond); |
||||
} |
||||
|
||||
/** |
||||
* Calculates Astronomical Julian Date from given time.<p> |
||||
* |
||||
* Astronomical Julian Dates are counting from noon of the January 1st, -4712 |
||||
* (julian date 0 is -4712/01/01 12:00:00). Zero year exist. Julian Date |
||||
* is always GMT, there are no timezones. |
||||
* <p> |
||||
* |
||||
* Algorithm based on Numerical Recipesin C, 2nd ed., Cambridge University |
||||
* Press 1992, modified and enhanced by Igor Spasic. |
||||
* |
||||
* @param year year |
||||
* @param month month |
||||
* @param day day |
||||
* @param hour hour |
||||
* @param minute minute |
||||
* @param second second |
||||
* |
||||
* @return julian time stamp |
||||
*/ |
||||
public static JulianDateStamp toJulianDate(int year, int month, int day, int hour, int minute, int second, int millisecond) { |
||||
|
||||
// month range fix
|
||||
if ((month > 12) || (month < -12)) { |
||||
month--; |
||||
int delta = month / 12; |
||||
year += delta; |
||||
month -= delta * 12; |
||||
month++; |
||||
} |
||||
if (month < 0) { |
||||
year--; |
||||
month += 12; |
||||
} |
||||
|
||||
// decimal day fraction
|
||||
double frac = (hour / 24.0) + (minute / 1440.0) + (second / 86400.0) + (millisecond / 86400000.0); |
||||
if (frac < 0) { // negative time fix
|
||||
int delta = ((int)(-frac)) + 1; |
||||
frac += delta; |
||||
day -= delta; |
||||
} |
||||
//double gyr = year + (0.01 * month) + (0.0001 * day) + (0.0001 * frac) + 1.0e-9;
|
||||
double gyr = year + (0.01 * month) + (0.0001 * (day + frac)) + 1.0e-9; |
||||
|
||||
// conversion factors
|
||||
int iy0; |
||||
int im0; |
||||
if (month <= 2) { |
||||
iy0 = year - 1; |
||||
im0 = month + 12; |
||||
} else { |
||||
iy0 = year; |
||||
im0 = month; |
||||
} |
||||
int ia = iy0 / 100; |
||||
int ib = 2 - ia + (ia >> 2); |
||||
|
||||
// calculate julian date
|
||||
int jd; |
||||
if (year <= 0) { |
||||
jd = (int)((365.25 * iy0) - 0.75) + (int)(30.6001 * (im0 + 1)) + day + 1720994; |
||||
} else { |
||||
jd = (int)(365.25 * iy0) + (int)(30.6001 * (im0 + 1)) + day + 1720994; |
||||
} |
||||
if (gyr >= 1582.1015) { // on or after 15 October 1582
|
||||
jd += ib; |
||||
} |
||||
//return jd + frac + 0.5;
|
||||
|
||||
return new JulianDateStamp(jd, frac + 0.5); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Calculates time stamp from Astronomical Julian Date. |
||||
* |
||||
* @param JD julian date |
||||
* |
||||
* @return time stamp |
||||
*/ |
||||
public static DateTimeStamp fromJulianDate(double JD) { |
||||
return fromJulianDate(new JulianDateStamp(JD)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Calculates time stamp from Astronomical Julian Date. |
||||
* Algorithm based on Numerical Recipesin C, 2nd ed., Cambridge University |
||||
* Press 1992. |
||||
* |
||||
* @param jds julian date stamp |
||||
* |
||||
* @return time stamp |
||||
*/ |
||||
public static DateTimeStamp fromJulianDate(JulianDateStamp jds) { |
||||
DateTimeStamp time = new DateTimeStamp(); |
||||
int year, month, day; |
||||
double frac; |
||||
int jd, ka, kb, kc, kd, ke, ialp; |
||||
|
||||
//double JD = jds.doubleValue();//jdate;
|
||||
//jd = (int)(JD + 0.5); // integer julian date
|
||||
//frac = JD + 0.5 - (double)jd + 1.0e-10; // day fraction
|
||||
|
||||
ka = (int)(jds.fraction + 0.5); |
||||
jd = jds.integer + ka; |
||||
frac = jds.fraction + 0.5 - ka + 1.0e-10; |
||||
|
||||
ka = jd; |
||||
if (jd >= 2299161) { |
||||
ialp = (int)(((double)jd - 1867216.25) / (36524.25)); |
||||
ka = jd + 1 + ialp - (ialp >> 2); |
||||
} |
||||
kb = ka + 1524; |
||||
kc = (int)(((double)kb - 122.1) / 365.25); |
||||
kd = (int)((double)kc * 365.25); |
||||
ke = (int)((double)(kb - kd) / 30.6001); |
||||
day = kb - kd - ((int)((double)ke * 30.6001)); |
||||
if (ke > 13) { |
||||
month = ke - 13; |
||||
} else { |
||||
month = ke - 1; |
||||
} |
||||
if ((month == 2) && (day > 28)){ |
||||
day = 29; |
||||
} |
||||
if ((month == 2) && (day == 29) && (ke == 3)) { |
||||
year = kc - 4716; |
||||
} else if (month > 2) { |
||||
year = kc - 4716; |
||||
} else { |
||||
year = kc - 4715; |
||||
} |
||||
time.year = year; |
||||
time.month = month; |
||||
time.day = day; |
||||
|
||||
// hour with minute and second included as fraction
|
||||
double d_hour = frac * 24.0; |
||||
time.hour = (int) d_hour; // integer hour
|
||||
|
||||
// minute with second included as a fraction
|
||||
double d_minute = (d_hour - (double)time.hour) * 60.0; |
||||
time.minute = (int) d_minute; // integer minute
|
||||
|
||||
double d_second = (d_minute - (double)time.minute) * 60.0; |
||||
time.second = (int) d_second; // integer seconds
|
||||
|
||||
double d_millis = (d_second - (double)time.second) * 1000.0; |
||||
|
||||
// fix calculation errors
|
||||
time.millisecond = (int) (((d_millis * 10) + 0.5) / 10); |
||||
|
||||
return time; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- gc
|
||||
|
||||
/** |
||||
* Returns Calendar month from provided JDateTime month. |
||||
*/ |
||||
public static int toCalendarMonth(int month) { |
||||
return month - 1; |
||||
} |
||||
|
||||
/** |
||||
* Returns Calendar day-of-week from provided JDateTime. |
||||
*/ |
||||
public static int toCalendarDayOfWeek(int dayOfWeek) { |
||||
return (dayOfWeek % 7) + 1; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- format
|
||||
|
||||
public static final SimpleDateFormat HTTP_DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); |
||||
|
||||
/** |
||||
* Formats time to HTTP date/time format. Note that number of milliseconds |
||||
* is lost. |
||||
*/ |
||||
public static String formatHttpDate(long millis) { |
||||
Date date = new Date(millis); |
||||
return HTTP_DATE_FORMAT.format(date); |
||||
} |
||||
|
||||
/** |
||||
* Parses the HTTP date/time format. Returns <code>-1</code> if given string |
||||
* is invalid. |
||||
*/ |
||||
public static long parseHttpTime(String time) { |
||||
if (time == null) { |
||||
return -1; |
||||
} |
||||
|
||||
try { |
||||
return TimeUtil.HTTP_DATE_FORMAT.parse(time).getTime(); |
||||
} |
||||
catch (ParseException e) { |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,75 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime; |
||||
|
||||
import java.util.TimeZone; |
||||
|
||||
/** |
||||
* Misc timezone utilities. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class TimeZoneUtil { |
||||
|
||||
/** |
||||
* Returns raw offset difference in milliseconds. |
||||
*/ |
||||
public static int getRawOffsetDifference(TimeZone from, TimeZone to) { |
||||
int offsetBefore = from.getRawOffset(); |
||||
int offsetAfter = to.getRawOffset(); |
||||
return offsetAfter - offsetBefore; |
||||
} |
||||
|
||||
/** |
||||
* Returns offset difference in milliseconds for given time. |
||||
*/ |
||||
public static int getOffsetDifference(long now, TimeZone from, TimeZone to) { |
||||
int offsetBefore = from.getOffset(now); |
||||
int offsetAfter = to.getOffset(now); |
||||
return offsetAfter - offsetBefore; |
||||
} |
||||
|
||||
/** |
||||
* Get offset difference in milliseconds for given jdatetime. |
||||
*/ |
||||
public static int getOffset(JDateTime jdt, TimeZone tz) { |
||||
return tz.getOffset( |
||||
jdt.getEra(), |
||||
jdt.getYear(), |
||||
jdt.getMonth() - 1, |
||||
jdt.getDay(), |
||||
TimeUtil.toCalendarDayOfWeek(jdt.getDayOfWeek()), |
||||
jdt.getMillisOfDay() |
||||
); |
||||
} |
||||
|
||||
public static int getOffsetDifference(JDateTime jdt, TimeZone from, TimeZone to) { |
||||
int offsetBefore = getOffset(jdt, from); |
||||
int offsetAfter = getOffset(jdt, to); |
||||
return offsetAfter - offsetBefore; |
||||
} |
||||
} |
@ -1,330 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime.format; |
||||
|
||||
import com.fr.third.jodd.datetime.DateTimeStamp; |
||||
import com.fr.third.jodd.datetime.JDateTime; |
||||
import com.fr.third.jodd.util.CharUtil; |
||||
|
||||
/** |
||||
* Abstract formatter for easier {@link JdtFormatter} implementations. |
||||
* <p> |
||||
* For setting date and time, default formatter parses input String against |
||||
* specified format. It extracts parts of input string upon patterns |
||||
* and then each part is converted to a number for a date/time information. |
||||
* It doesn't ignore any non-number character. If conversion fails, |
||||
* <code>null</code> is returned. |
||||
* |
||||
* <p> |
||||
* Getting date time is also user friendly. Specified format may not only |
||||
* contains patterns but also any text. To remove errors in decoding when |
||||
* text may be recognize as one of patterns, format text may be quoted |
||||
* with the special escape sign. Double quote in the text will be decoded |
||||
* as a single quote, of course. |
||||
* <p> |
||||
* |
||||
* It is not necessary to have parsers for all patterns. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public abstract class AbstractFormatter implements JdtFormatter { |
||||
|
||||
/** |
||||
* Available patterns list. Used by {@link #findPattern(char[], int)} |
||||
* when parsing date time format. Each formatter will have its own set of |
||||
* patterns, in strictly defined order. |
||||
*/ |
||||
protected char[][] patterns; |
||||
|
||||
/** |
||||
* Escape character. |
||||
*/ |
||||
protected char escapeChar = '\''; |
||||
|
||||
|
||||
/** |
||||
* Converts String array of patterns to char arrays. |
||||
*/ |
||||
protected void preparePatterns(String[] spat) { |
||||
patterns = new char[spat.length][]; |
||||
for (int i = 0; i < spat.length; i++) { |
||||
patterns[i] = spat[i].toCharArray(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Finds the longest pattern in provided format starting from specified position. |
||||
* All available patterns are stored in {@link #patterns}. |
||||
* |
||||
* @param format date time format to examine |
||||
* @param i starting index |
||||
* |
||||
* @return 0-based index of founded pattern, or <code>-1</code> if pattern not found |
||||
*/ |
||||
protected int findPattern(char[] format, int i) { |
||||
int frmtc_len = format.length; |
||||
boolean match; |
||||
int n, lastn = -1; |
||||
int maxLen = 0; |
||||
for (n = 0; n < patterns.length; n++) { |
||||
char[] curr = patterns[n]; // current pattern from the pattern list
|
||||
if (i > frmtc_len - curr.length) { |
||||
continue; |
||||
} |
||||
match = true; |
||||
int delta = 0; |
||||
while (delta < curr.length) { // match given pattern
|
||||
if (curr[delta] != format[i + delta]) { |
||||
match = false; // no match, go to next
|
||||
break; |
||||
} |
||||
delta++; |
||||
} |
||||
if (match) { // match
|
||||
if (patterns[n].length > maxLen) { // find longest match
|
||||
lastn = n; |
||||
maxLen = patterns[n].length; |
||||
} |
||||
} |
||||
} |
||||
return lastn; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- convert
|
||||
|
||||
/** |
||||
* Creates a date-time string for founded pattern. Founded patterns |
||||
* is identified by its {@link #patterns} index. |
||||
* |
||||
* @param patternIndex index of founded pattern |
||||
* @param jdt date time information |
||||
*/ |
||||
protected abstract String convertPattern(int patternIndex, JDateTime jdt); |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
* @see JdtFormatter#convert(JDateTime, String) |
||||
*/ |
||||
public String convert(JDateTime jdt, String format) { |
||||
char[] fmtc = format.toCharArray(); |
||||
int fmtc_len = fmtc.length; |
||||
StringBuilder result = new StringBuilder(fmtc_len); |
||||
|
||||
int i = 0; |
||||
while (i < fmtc_len) { |
||||
if (fmtc[i] == escapeChar) { // quote founded
|
||||
int end = i + 1; |
||||
while (end < fmtc_len) { |
||||
if (fmtc[end] == escapeChar) { // second quote founded
|
||||
if (end + 1 < fmtc_len) { |
||||
end++; |
||||
if (fmtc[end] == escapeChar) { // skip double quotes
|
||||
result.append(escapeChar); // and continue
|
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
} else { |
||||
result.append(fmtc[end]); |
||||
} |
||||
end++; |
||||
} |
||||
i = end; |
||||
continue; // end of quoted string, continue the main loop
|
||||
} |
||||
|
||||
int n = findPattern(fmtc, i); |
||||
if (n != -1) { // pattern founded
|
||||
result.append(convertPattern(n, jdt)); |
||||
i += patterns[n].length; |
||||
} else { |
||||
result.append(fmtc[i]); |
||||
i++; |
||||
} |
||||
} |
||||
return result.toString(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- parse
|
||||
|
||||
/** |
||||
* Parses value for matched pattern. Founded patterns |
||||
* is identified by its {@link #patterns} index. |
||||
* Note that value may represent both integer and decimals. |
||||
* May throw {@link NumberFormatException}. |
||||
* |
||||
* @param patternIndex index of founded pattern |
||||
* @param value value to parse, no spaces or tabs |
||||
* @param destination destination to modify |
||||
*/ |
||||
protected abstract void parseValue(int patternIndex, String value, DateTimeStamp destination); |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
* @see JdtFormatter#parse(String, String) |
||||
*/ |
||||
public DateTimeStamp parse(String value, String format) { |
||||
char[] valueChars = value.toCharArray(); |
||||
char[] formatChars = format.toCharArray(); |
||||
|
||||
int i = 0, j = 0; |
||||
int valueLen = valueChars.length; |
||||
int formatLen = formatChars.length; |
||||
|
||||
// detect if separators are used
|
||||
boolean useSeparators = true; |
||||
|
||||
if (valueLen == formatLen) { |
||||
useSeparators = false; |
||||
|
||||
for (char valueChar : valueChars) { |
||||
if (!CharUtil.isDigit(valueChar)) { |
||||
useSeparators = true; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
DateTimeStamp time = new DateTimeStamp(); |
||||
StringBuilder sb = new StringBuilder(); |
||||
while (true) { |
||||
int n = findPattern(formatChars, i); |
||||
if (n != -1) { // pattern founded
|
||||
int patternLen = patterns[n].length; |
||||
i += patternLen; |
||||
sb.setLength(0); |
||||
if (!useSeparators) { |
||||
for (int k = 0; k < patternLen; k++) { |
||||
sb.append(valueChars[j++]); |
||||
} |
||||
} else { |
||||
char next = 0xFFFF; |
||||
if (i < formatLen) { |
||||
next = formatChars[i]; // next = delimiter
|
||||
} |
||||
while ((j < valueLen) && (valueChars[j] != next)) { |
||||
char scj = valueChars[j]; |
||||
if ((scj != ' ') && (scj != '\t')) { // ignore surrounding whitespaces
|
||||
sb.append(valueChars[j]); |
||||
} |
||||
j++; |
||||
} |
||||
} |
||||
|
||||
parseValue(n, sb.toString(), time); |
||||
} else { |
||||
if (!useSeparators) { |
||||
throw new IllegalArgumentException("Invalid value: " + value); |
||||
} |
||||
if (formatChars[i] == valueChars[j]) { |
||||
j++; |
||||
} |
||||
i++; |
||||
} |
||||
if ((i == formatLen) || (j == valueLen)) { |
||||
break; |
||||
} |
||||
} |
||||
return time; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- util
|
||||
|
||||
/** |
||||
* Prints values 00 - 99. |
||||
*/ |
||||
protected String print2(int value) { |
||||
if (value < 0) { |
||||
throw new IllegalArgumentException("Value must be positive: " + value); |
||||
} |
||||
if (value < 10) { |
||||
return '0' + Integer.toString(value); |
||||
} |
||||
if (value < 100) { |
||||
return Integer.toString(value); |
||||
} |
||||
throw new IllegalArgumentException("Value too big: " + value); |
||||
} |
||||
|
||||
/** |
||||
* Prints values 00 - 999. |
||||
*/ |
||||
protected String print3(int value) { |
||||
if (value < 0) { |
||||
throw new IllegalArgumentException("Value must be positive: " + value); |
||||
} |
||||
if (value < 10) { |
||||
return "00" + Integer.toString(value); |
||||
} |
||||
if (value < 100) { |
||||
return '0' + Integer.toString(value); |
||||
} |
||||
if (value < 1000) { |
||||
return Integer.toString(value); |
||||
} |
||||
throw new IllegalArgumentException("Value too big: " + value); |
||||
} |
||||
|
||||
/** |
||||
* Prints 4 digits and optional minus sign. |
||||
*/ |
||||
protected String printPad4(int value) { |
||||
char[] result = new char[4]; |
||||
int count = 0; |
||||
|
||||
if (value < 0) { |
||||
result[count++] = '-'; |
||||
value = -value; |
||||
} |
||||
|
||||
String str = Integer.toString(value); |
||||
|
||||
if (value < 10) { |
||||
result[count++] = '0'; |
||||
result[count++] = '0'; |
||||
result[count++] = '0'; |
||||
result[count++] = str.charAt(0); |
||||
} else if (value < 100) { |
||||
result[count++] = '0'; |
||||
result[count++] = '0'; |
||||
result[count++] = str.charAt(0); |
||||
result[count++] = str.charAt(1); |
||||
} else if (value < 1000) { |
||||
result[count++] = '0'; |
||||
result[count++] = str.charAt(0); |
||||
result[count++] = str.charAt(1); |
||||
result[count++] = str.charAt(2); |
||||
} else { |
||||
if (count > 0) { |
||||
return '-' + str; |
||||
} |
||||
return str; |
||||
} |
||||
return new String(result, 0, count); |
||||
} |
||||
} |
@ -1,170 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime.format; |
||||
|
||||
import com.fr.third.jodd.datetime.DateTimeStamp; |
||||
import com.fr.third.jodd.datetime.JDateTime; |
||||
import com.fr.third.jodd.datetime.DateTimeStamp; |
||||
import com.fr.third.jodd.datetime.JDateTime; |
||||
import com.fr.third.jodd.util.LocaleUtil; |
||||
import com.fr.third.jodd.util.DateFormatSymbolsEx; |
||||
|
||||
import java.util.TimeZone; |
||||
|
||||
/** |
||||
* Default {@link JdtFormatter} uses <b>ISO 8601</b> specification, enhanced by some |
||||
* custom patterns. For more information see: |
||||
* <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO 8601 on Wikipedia</a> |
||||
* |
||||
* <p> |
||||
* Patterns list: |
||||
* |
||||
* <ul> |
||||
* <li>YYYY + year</li> |
||||
* <li>MM + month</li> |
||||
* <li>DD + day of month</li> |
||||
* <li>D - day of week</li> |
||||
* <li>MML - month name (add-on)</li> |
||||
* <li>MMS - month abbreviation (add-on)</li> |
||||
* <li>DL - day of week name (add-on)</li> |
||||
* <li>DS - day of week abbreviation (add-on)</li> |
||||
* <li>hh + hour</li> |
||||
* <li>mm + minute</li> |
||||
* <li>ss + seconds (no milliseconds)</li> |
||||
* <li>mss + milliseconds (add-on)</li> |
||||
* <li>DDD - day of year</li> |
||||
* <li>WW - week of year</li> |
||||
* <li>WWW - week of year with 'W' prefix</li> |
||||
* <li>W - week of month (add-on)</li> |
||||
* <li>E - era</li> |
||||
* <li>TLZ - time zone long</li> |
||||
* <li>TLS - time zone short</li> |
||||
* </ul> |
||||
* |
||||
* <p> |
||||
* Patterns noted with + sign are used both for conversion and parsing. |
||||
* All patterns are used for conversion. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class Iso8601JdtFormatter extends AbstractFormatter { |
||||
|
||||
public Iso8601JdtFormatter() { |
||||
preparePatterns( |
||||
new String[] { |
||||
"YYYY", // 0 + year
|
||||
"MM", // 1 + month
|
||||
"DD", // 2 + day of month
|
||||
"D", // 3 - day of week
|
||||
"MML", // 4 - month long name
|
||||
"MMS", // 5 - month short name
|
||||
"DL", // 6 - day of week long name
|
||||
"DS", // 7 - day of week short name
|
||||
"hh", // 8 + hour
|
||||
"mm", // 9 + minute
|
||||
"ss", // 10 + seconds
|
||||
"mss", // 11 + milliseconds
|
||||
"DDD", // 12 - day of year
|
||||
"WW", // 13 - week of year
|
||||
"WWW", // 14 - week of year with 'W' prefix
|
||||
"W", // 15 - week of month
|
||||
"E", // 16 - era
|
||||
"TZL", // 17 - timezone long name
|
||||
"TZS", // 18 - timezone short name
|
||||
} |
||||
); |
||||
} |
||||
|
||||
@Override |
||||
protected String convertPattern(int patternIndex, JDateTime jdt) { |
||||
DateFormatSymbolsEx dfs = LocaleUtil.getDateFormatSymbols(jdt.getLocale()); |
||||
switch (patternIndex) { |
||||
case 0: |
||||
return printPad4(jdt.getYear()); |
||||
case 1: |
||||
return print2(jdt.getMonth()); |
||||
case 2: |
||||
return print2(jdt.getDay()); |
||||
case 3: |
||||
return Integer.toString(jdt.getDayOfWeek()); |
||||
case 4: |
||||
return dfs.getMonth(jdt.getMonth() - 1); |
||||
case 5: |
||||
return dfs.getShortMonth(jdt.getMonth() - 1); |
||||
case 6: |
||||
return dfs.getWeekday((jdt.getDayOfWeek() % 7) + 1); |
||||
case 7: |
||||
return dfs.getShortWeekday((jdt.getDayOfWeek() % 7) + 1); |
||||
case 8: |
||||
return print2(jdt.getHour()); |
||||
case 9: |
||||
return print2(jdt.getMinute()); |
||||
case 10: |
||||
return print2(jdt.getSecond()); |
||||
case 11: |
||||
return print3(jdt.getMillisecond()); |
||||
case 12: |
||||
return print3(jdt.getDayOfYear()); |
||||
case 13: |
||||
return print2(jdt.getWeekOfYear()); |
||||
case 14: |
||||
return 'W' + print2(jdt.getWeekOfYear()); |
||||
case 15: |
||||
return Integer.toString(jdt.getWeekOfMonth()); |
||||
case 16: |
||||
return jdt.getEra() == 1 ? dfs.getAdEra() : dfs.getBcEra(); |
||||
case 17: |
||||
return jdt.getTimeZone().getDisplayName( |
||||
jdt.isInDaylightTime(), |
||||
TimeZone.LONG, |
||||
jdt.getLocale()); |
||||
case 18: |
||||
return jdt.getTimeZone().getDisplayName( |
||||
jdt.isInDaylightTime(), |
||||
TimeZone.SHORT, |
||||
jdt.getLocale()); |
||||
default: |
||||
return new String(patterns[patternIndex]); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void parseValue(int patternIndex, String value, DateTimeStamp destination) { |
||||
int v = Integer.parseInt(value); |
||||
switch (patternIndex) { |
||||
case 0: destination.year = v; break; |
||||
case 1: destination.month = v; break; |
||||
case 2: destination.day = v; break; |
||||
case 8: destination.hour = v; break; |
||||
case 9: destination.minute = v; break; |
||||
case 10: destination.second = v; break; |
||||
case 11: destination.millisecond = v; break; |
||||
default: |
||||
throw new IllegalArgumentException("Invalid template: " + new String(patterns[patternIndex])); |
||||
} |
||||
} |
||||
} |
@ -1,75 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime.format; |
||||
|
||||
import com.fr.third.jodd.datetime.DateTimeStamp; |
||||
import com.fr.third.jodd.datetime.JDateTime; |
||||
|
||||
/** |
||||
* Immutable format-formatter pair. |
||||
* |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public class JdtFormat { |
||||
|
||||
protected final String format; |
||||
protected final JdtFormatter formatter; |
||||
|
||||
public JdtFormat(JdtFormatter formatter, String format) { |
||||
this.format = format; |
||||
this.formatter = formatter; |
||||
} |
||||
|
||||
/** |
||||
* Returns format. |
||||
*/ |
||||
public String getFormat() { |
||||
return format; |
||||
} |
||||
|
||||
/** |
||||
* Returns formatter. |
||||
*/ |
||||
public JdtFormatter getFormatter() { |
||||
return formatter; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Delegates for {@link JdtFormatter#convert(JDateTime, String)}. |
||||
*/ |
||||
public String convert(JDateTime jdt) { |
||||
return formatter.convert(jdt, format); |
||||
} |
||||
|
||||
/** |
||||
* Delegates for {@link JdtFormatter#parse(String, String)}. |
||||
*/ |
||||
public DateTimeStamp parse(String value) { |
||||
return formatter.parse(value, format); |
||||
} |
||||
} |
@ -1,62 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.datetime.format; |
||||
|
||||
import com.fr.third.jodd.datetime.DateTimeStamp; |
||||
import com.fr.third.jodd.datetime.JDateTime; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* Date time formatter performs conversion both from and to string representation of time. |
||||
* |
||||
* @see AbstractFormatter |
||||
* @deprecated jodd目前版本为5.1.6, 此版本已移除此类, 兼容问题暂不删除此类 |
||||
*/ |
||||
@Deprecated |
||||
public interface JdtFormatter extends Serializable { |
||||
|
||||
/** |
||||
* Converts date time to a string using specified format. |
||||
* |
||||
* @param jdt JDateTime to read from |
||||
* @param format format |
||||
* |
||||
* @return formatted string with date time information |
||||
*/ |
||||
String convert(JDateTime jdt, String format); |
||||
|
||||
/** |
||||
* Parses string given in specified format and extracts time information. |
||||
* It returns a new instance of <code>DateTimeStamp</code> or <code>null</code> if error occurs. |
||||
* |
||||
* @param value string containing date time values |
||||
* @param format format |
||||
* |
||||
* @return DateTimeStamp instance with populated data |
||||
*/ |
||||
DateTimeStamp parse(String value, String format); |
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* JDateTime formatters for converting date/time informations to/from strings. |
||||
*/ |
||||
package com.fr.third.jodd.datetime.format; |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Finally, easy manipulation of date and time! |
||||
*/ |
||||
package com.fr.third.jodd.datetime; |
@ -1,301 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.exception; |
||||
|
||||
import com.fr.third.jodd.io.StreamUtil; |
||||
import com.fr.third.jodd.util.StringUtil; |
||||
|
||||
import java.io.PrintWriter; |
||||
import java.io.StringWriter; |
||||
import java.lang.reflect.InvocationTargetException; |
||||
import java.lang.reflect.UndeclaredThrowableException; |
||||
import java.sql.SQLException; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* Few exception utilities. |
||||
*/ |
||||
public class ExceptionUtil { |
||||
|
||||
/** |
||||
* Returns current stack trace in form of array of stack trace elements. |
||||
* First stack trace element is removed. |
||||
* Since an exception is thrown internally, this method is slow. |
||||
*/ |
||||
@SuppressWarnings({"ThrowCaughtLocally"}) |
||||
public static StackTraceElement[] getCurrentStackTrace() { |
||||
StackTraceElement[] ste = new Exception().getStackTrace(); |
||||
if (ste.length > 1) { |
||||
StackTraceElement[] result = new StackTraceElement[ste.length - 1]; |
||||
System.arraycopy(ste, 1, result, 0, ste.length - 1); |
||||
return result; |
||||
} else { |
||||
return ste; |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- exception stack trace
|
||||
|
||||
/** |
||||
* Returns stack trace filtered by class names. |
||||
*/ |
||||
public static StackTraceElement[] getStackTrace(final Throwable t, final String[] allow, final String[] deny) { |
||||
StackTraceElement[] st = t.getStackTrace(); |
||||
ArrayList<StackTraceElement> result = new ArrayList<>(st.length); |
||||
|
||||
elementLoop: |
||||
for (StackTraceElement element : st) { |
||||
String className = element.getClassName(); |
||||
if (allow != null) { |
||||
boolean validElemenet = false; |
||||
for (String filter : allow) { |
||||
if (className.contains(filter)) { |
||||
validElemenet = true; |
||||
break; |
||||
} |
||||
} |
||||
if (!validElemenet) { |
||||
continue; |
||||
} |
||||
} |
||||
if (deny != null) { |
||||
for (String filter : deny) { |
||||
if (className.contains(filter)) { |
||||
continue elementLoop; |
||||
} |
||||
} |
||||
} |
||||
result.add(element); |
||||
} |
||||
st = new StackTraceElement[result.size()]; |
||||
return result.toArray(st); |
||||
} |
||||
|
||||
/** |
||||
* Returns stack trace chain filtered by class names. |
||||
*/ |
||||
public static StackTraceElement[][] getStackTraceChain(Throwable t, final String[] allow, final String[] deny) { |
||||
ArrayList<StackTraceElement[]> result = new ArrayList<>(); |
||||
while (t != null) { |
||||
StackTraceElement[] stack = getStackTrace(t, allow, deny); |
||||
result.add(stack); |
||||
t = t.getCause(); |
||||
} |
||||
StackTraceElement[][] allStacks = new StackTraceElement[result.size()][]; |
||||
for (int i = 0; i < allStacks.length; i++) { |
||||
allStacks[i] = result.get(i); |
||||
} |
||||
return allStacks; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns exception chain starting from top up to root cause. |
||||
*/ |
||||
public static Throwable[] getExceptionChain(Throwable throwable) { |
||||
ArrayList<Throwable> list = new ArrayList<>(); |
||||
list.add(throwable); |
||||
while ((throwable = throwable.getCause()) != null) { |
||||
list.add(throwable); |
||||
} |
||||
Throwable[] result = new Throwable[list.size()]; |
||||
return list.toArray(result); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- exception to string
|
||||
|
||||
|
||||
/** |
||||
* Prints stack trace into a String. |
||||
*/ |
||||
public static String exceptionStackTraceToString(final Throwable t) { |
||||
StringWriter sw = new StringWriter(); |
||||
PrintWriter pw = new PrintWriter(sw, true); |
||||
|
||||
t.printStackTrace(pw); |
||||
|
||||
StreamUtil.close(pw); |
||||
StreamUtil.close(sw); |
||||
|
||||
return sw.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Prints full exception stack trace, from top to root cause, into a String. |
||||
*/ |
||||
public static String exceptionChainToString(Throwable t) { |
||||
StringWriter sw = new StringWriter(); |
||||
PrintWriter pw = new PrintWriter(sw, true); |
||||
while (t != null) { |
||||
t.printStackTrace(pw); |
||||
t = t.getCause(); |
||||
} |
||||
|
||||
StreamUtil.close(pw); |
||||
StreamUtil.close(sw); |
||||
|
||||
return sw.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Build a message for the given base message and its cause. |
||||
*/ |
||||
public static String buildMessage(final String message, Throwable cause) { |
||||
if (cause != null) { |
||||
cause = getRootCause(cause); |
||||
StringBuilder buf = new StringBuilder(); |
||||
if (message != null) { |
||||
buf.append(message).append("; "); |
||||
} |
||||
buf.append("<--- ").append(cause); |
||||
return buf.toString(); |
||||
} else { |
||||
return message; |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- root cause
|
||||
|
||||
/** |
||||
* Introspects the <code>Throwable</code> to obtain the root cause. |
||||
* <p> |
||||
* This method walks through the exception chain to the last element, |
||||
* "root" of the tree, and returns that exception. If no root cause found |
||||
* returns provided throwable. |
||||
*/ |
||||
public static Throwable getRootCause(final Throwable throwable) { |
||||
Throwable cause = throwable.getCause(); |
||||
if (cause == null) { |
||||
return throwable; |
||||
} |
||||
|
||||
Throwable t = throwable; |
||||
|
||||
// defend against (malicious?) circularity
|
||||
for (int i = 0; i < 1000; i++) { |
||||
cause = t.getCause(); |
||||
if (cause == null) { |
||||
return t; |
||||
} |
||||
t = cause; |
||||
} |
||||
|
||||
return throwable; |
||||
} |
||||
|
||||
/** |
||||
* Finds throwing cause in exception stack. Returns throwable object if cause class is matched. |
||||
* Otherwise, returns <code>null</code>. |
||||
*/ |
||||
@SuppressWarnings({"unchecked"}) |
||||
public static <T extends Throwable> T findCause(Throwable throwable, final Class<T> cause) { |
||||
while (throwable != null) { |
||||
if (throwable.getClass().equals(cause)) { |
||||
return (T) throwable; |
||||
} |
||||
throwable = throwable.getCause(); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- sql
|
||||
|
||||
/** |
||||
* Rolls up SQL exceptions by taking each proceeding exception |
||||
* and making it a child of the previous using the <code>setNextException</code> |
||||
* method of SQLException. |
||||
*/ |
||||
public static SQLException rollupSqlExceptions(final Collection<SQLException> exceptions) { |
||||
SQLException parent = null; |
||||
for (SQLException exception : exceptions) { |
||||
if (parent != null) { |
||||
exception.setNextException(parent); |
||||
} |
||||
parent = exception; |
||||
} |
||||
return parent; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- misc
|
||||
|
||||
/** |
||||
* Throws checked exceptions in un-checked manner. |
||||
*/ |
||||
public static void throwRuntimeException(final Throwable throwable) { |
||||
throw wrapToRuntimeException(throwable); |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>non-null</code> message for a throwable. |
||||
*/ |
||||
public static String message(final Throwable throwable) { |
||||
String message = throwable.getMessage(); |
||||
|
||||
if (StringUtil.isBlank(message)) { |
||||
message = throwable.toString(); |
||||
} |
||||
|
||||
return message; |
||||
} |
||||
|
||||
/** |
||||
* Wraps exception to {@code RuntimeException}. |
||||
*/ |
||||
public static RuntimeException wrapToRuntimeException(final Throwable throwable) { |
||||
if (throwable instanceof RuntimeException) { |
||||
return (RuntimeException) throwable; |
||||
} |
||||
return new RuntimeException(throwable); |
||||
} |
||||
public static Exception wrapToException(final Throwable throwable) { |
||||
if (throwable instanceof Exception) { |
||||
return (Exception) throwable; |
||||
} |
||||
return new RuntimeException(throwable); |
||||
} |
||||
|
||||
/** |
||||
* Unwraps invocation and undeclared exceptions to real cause. |
||||
*/ |
||||
public static Throwable unwrapThrowable(final Throwable wrappedThrowable) { |
||||
Throwable unwrapped = wrappedThrowable; |
||||
while (true) { |
||||
if (unwrapped instanceof InvocationTargetException) { |
||||
unwrapped = ((InvocationTargetException) unwrapped).getTargetException(); |
||||
} |
||||
else if (unwrapped instanceof UndeclaredThrowableException) { |
||||
unwrapped = ((UndeclaredThrowableException) unwrapped).getUndeclaredThrowable(); |
||||
} |
||||
else { |
||||
return unwrapped; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,212 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.exception; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.PrintStream; |
||||
import java.io.PrintWriter; |
||||
import java.io.UncheckedIOException; |
||||
import java.util.concurrent.Callable; |
||||
|
||||
/** |
||||
* Unchecked exception and also a wrapper for checked exceptions. |
||||
*/ |
||||
@SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter"}) |
||||
public class UncheckedException extends RuntimeException { |
||||
|
||||
protected final Throwable cause; |
||||
|
||||
/** |
||||
* Divider between causes printouts. |
||||
*/ |
||||
protected static final String CAUSE_DIV = "---[cause]------------------------------------------------------------------------"; |
||||
|
||||
/** |
||||
* If set to <code>true</code> stack trace will be enhanced with cause's stack traces. |
||||
*/ |
||||
protected final boolean showCauseDetails; |
||||
|
||||
// ---------------------------------------------------------------- constructors
|
||||
|
||||
public UncheckedException(final Throwable t) { |
||||
super(t.getMessage()); |
||||
cause = t; |
||||
this.showCauseDetails = true; |
||||
} |
||||
|
||||
public UncheckedException(final Throwable t, final boolean showCauseDetails) { |
||||
super(t.getMessage()); |
||||
cause = t; |
||||
this.showCauseDetails = showCauseDetails; |
||||
} |
||||
|
||||
public UncheckedException() { |
||||
super(); |
||||
cause = null; |
||||
this.showCauseDetails = false; |
||||
} |
||||
|
||||
public UncheckedException(final String message) { |
||||
super(message); |
||||
cause = null; |
||||
this.showCauseDetails = false; |
||||
} |
||||
|
||||
public UncheckedException(final String message, final Throwable t) { |
||||
super(message, t); |
||||
cause = t; |
||||
this.showCauseDetails = true; |
||||
} |
||||
|
||||
public UncheckedException(final String message, final Throwable t, final boolean showCauseDetails) { |
||||
super(message, t); |
||||
cause = t; |
||||
this.showCauseDetails = showCauseDetails; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- stack trace
|
||||
|
||||
@Override |
||||
public void printStackTrace() { |
||||
printStackTrace(System.err); |
||||
} |
||||
|
||||
@Override |
||||
public void printStackTrace(final PrintStream ps) { |
||||
synchronized (ps) { |
||||
super.printStackTrace(ps); |
||||
if ((cause != null) && showCauseDetails) { |
||||
Throwable rootCause = ExceptionUtil.getRootCause(cause); |
||||
ps.println(CAUSE_DIV); |
||||
rootCause.printStackTrace(ps); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void printStackTrace(final PrintWriter pw) { |
||||
synchronized (pw) { |
||||
super.printStackTrace(pw); |
||||
if ((cause != null) && showCauseDetails) { |
||||
Throwable rootCause = ExceptionUtil.getRootCause(cause); |
||||
pw.println(CAUSE_DIV); |
||||
rootCause.printStackTrace(pw); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- txt
|
||||
|
||||
/** |
||||
* Returns the detail message, including the message from the nested exception if there is one. |
||||
*/ |
||||
@Override |
||||
public String getMessage() { |
||||
return ExceptionUtil.buildMessage(super.getMessage(), cause); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- wrap
|
||||
|
||||
/** |
||||
* Wraps checked exceptions in a <code>UncheckedException</code>. |
||||
* Unchecked exceptions are not wrapped. |
||||
*/ |
||||
public static <V> V callAndWrapException(final Callable<V> callable) { |
||||
try { |
||||
return callable.call(); |
||||
} |
||||
catch (IOException ioex) { |
||||
throw new UncheckedIOException(ioex); |
||||
} |
||||
catch (RuntimeException rtex) { |
||||
throw rtex; |
||||
} |
||||
catch (Exception t) { |
||||
throw new UncheckedException(t); |
||||
} |
||||
} |
||||
|
||||
@FunctionalInterface |
||||
public interface CallableVoid { |
||||
public void call() throws Exception; |
||||
} |
||||
|
||||
/** |
||||
* Wraps checked exceptions in a <code>UncheckedException</code>. |
||||
* Unchecked exceptions are not wrapped. |
||||
*/ |
||||
public static void runAndWrapException(final CallableVoid callable) { |
||||
try { |
||||
callable.call(); |
||||
} |
||||
catch (IOException ioex) { |
||||
throw new UncheckedIOException(ioex); |
||||
} |
||||
catch (RuntimeException rtex) { |
||||
throw rtex; |
||||
} |
||||
catch (Exception t) { |
||||
throw new UncheckedException(t); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Wraps all exceptions in a <code>UncheckedException</code> |
||||
*/ |
||||
public static RuntimeException wrap(final Throwable t) { |
||||
return new UncheckedException(t); |
||||
} |
||||
|
||||
/** |
||||
* Wraps all exceptions in a <code>UncheckedException</code> |
||||
*/ |
||||
public static RuntimeException wrap(final Throwable t, final String message) { |
||||
return new UncheckedException(message, t); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- cause
|
||||
|
||||
/** |
||||
* Re-throws cause if exists. |
||||
*/ |
||||
public void rethrow() throws Throwable { |
||||
if (cause == null) { |
||||
return; |
||||
} |
||||
throw cause; |
||||
} |
||||
|
||||
/** |
||||
* Returns exception cause. |
||||
*/ |
||||
@Override |
||||
public Throwable getCause() { |
||||
return cause; |
||||
} |
||||
|
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Jodds exceptions. |
||||
*/ |
||||
package com.fr.third.jodd.exception; |
@ -1,52 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.inex; |
||||
|
||||
import com.fr.third.jodd.util.Wildcard; |
||||
|
||||
/** |
||||
* Rule matcher. |
||||
*/ |
||||
@FunctionalInterface |
||||
public interface InExRuleMatcher<T, R> { |
||||
|
||||
/** |
||||
* {@link com.fr.third.jodd.util.Wildcard#match(CharSequence, CharSequence) Wilcard} rule matcher. |
||||
*/ |
||||
InExRuleMatcher<String, String> WILDCARD_RULE_MATCHER = |
||||
(value, rule, include) -> Wildcard.match(value, rule); |
||||
/** |
||||
* {@link com.fr.third.jodd.util.Wildcard#matchPath(String, String) Wilcard path} rule matcher. |
||||
*/ |
||||
InExRuleMatcher<String, String> WILDCARD_PATH_RULE_MATCHER = |
||||
(value, rule, include) -> Wildcard.matchPath(value, rule); |
||||
|
||||
/** |
||||
* Matches the value against the rule. |
||||
*/ |
||||
boolean accept(T value, R rule, boolean include); |
||||
|
||||
} |
@ -1,381 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.inex; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* A single-class rule engine for includes/excludes filtering logic. It can be used when |
||||
* set of objects has to filtered using includes and excludes rules. |
||||
* For example, when filtering files by file name etc. |
||||
* <p> |
||||
* Rule engine works in one of two modes: |
||||
* <ul> |
||||
* <li><i>blacklist</i> - when any input is allowed by default and when you specify |
||||
* explicit excludes. |
||||
* </li> |
||||
* <li><i>whitelist</i> - when any input is disabled by default and when you specify |
||||
* explicit includes. |
||||
* </li> |
||||
* </ul> |
||||
* <p> |
||||
* The logic of this rule engine depends on the current mode. In both cases, |
||||
* always the inverse rules are considered first. For example, for <i>blacklist</i> |
||||
* mode, engine first examine excludes, and then includes. This way you can |
||||
* set any filter combination. |
||||
* <p> |
||||
* All Jodd classes that filters something uses this class to unify the |
||||
* behavior across the Jodd library. |
||||
* <p> |
||||
* About generics: rule engine examine Values (V). Rules are defined as Definitions (D). |
||||
* They are stored internally as R, that is used with Values. |
||||
*/ |
||||
public class InExRules<V, D, R> implements InExRuleMatcher<V, R> { |
||||
|
||||
public InExRules<String, String, String> create() { |
||||
return new InExRules<>(); |
||||
} |
||||
|
||||
protected List<Rule<R>> rules; |
||||
protected final InExRuleMatcher<V, R> inExRuleMatcher; |
||||
protected int includesCount; |
||||
protected int excludesCount; |
||||
protected boolean blacklist = true; |
||||
|
||||
/** |
||||
* Creates default instance. |
||||
*/ |
||||
public InExRules() { |
||||
this.inExRuleMatcher = this; |
||||
} |
||||
|
||||
/** |
||||
* Creates instance that uses provided matcher. |
||||
*/ |
||||
public InExRules(final InExRuleMatcher<V, R> inExRuleMatcher) { |
||||
this.inExRuleMatcher = inExRuleMatcher; |
||||
} |
||||
|
||||
/** |
||||
* Returns total number of all rules. |
||||
*/ |
||||
public int totalRules() { |
||||
if (rules == null) { |
||||
return 0; |
||||
} |
||||
return rules.size(); |
||||
} |
||||
|
||||
/** |
||||
* Returns total number of include rules. |
||||
*/ |
||||
public int totalIncludeRules() { |
||||
return includesCount; |
||||
} |
||||
|
||||
/** |
||||
* Returns total number of exclude rules. |
||||
*/ |
||||
public int totalExcludeRules() { |
||||
return excludesCount; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if rule engine has at least one rule set. |
||||
*/ |
||||
public boolean hasRules() { |
||||
if (rules == null) { |
||||
return false; |
||||
} |
||||
return !rules.isEmpty(); |
||||
} |
||||
|
||||
/** |
||||
* Rule definition. |
||||
*/ |
||||
public static class Rule<R> { |
||||
public final R value; |
||||
public final boolean include; |
||||
|
||||
public Rule(final R value, final boolean include) { |
||||
this.value = value; |
||||
this.include = include; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return (include ? "+" : "-") + value.toString(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(final Object o) { |
||||
if (this == o) { |
||||
return true; |
||||
} |
||||
if (o == null || getClass() != o.getClass()) { |
||||
return false; |
||||
} |
||||
|
||||
Rule rule = (Rule) o; |
||||
|
||||
if (include != rule.include) { |
||||
return false; |
||||
} |
||||
if (!value.equals(rule.value)) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int result = value.hashCode(); |
||||
result = 31 * result + (include ? 1 : 0); |
||||
return result; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns rule's value on given index. |
||||
*/ |
||||
public R getRule(final int index) { |
||||
return rules.get(index).value; |
||||
} |
||||
|
||||
/** |
||||
* Resets all the rules in this rule engine. |
||||
*/ |
||||
public void reset() { |
||||
if (rules != null) { |
||||
rules.clear(); |
||||
} |
||||
includesCount = excludesCount = 0; |
||||
blacklist = true; |
||||
} |
||||
|
||||
/** |
||||
* Enables <i>blacklist</i> mode - everything is <b>included</b> by default, |
||||
* and user sets explicit excludes. |
||||
*/ |
||||
public void blacklist() { |
||||
blacklist = true; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if blacklist mode is set. |
||||
*/ |
||||
public boolean isBlacklist() { |
||||
return blacklist; |
||||
} |
||||
|
||||
/** |
||||
* Enables <i>whitelist</i> mode - everything is <b>excluded</b> by default, |
||||
* and user set explicit includes. |
||||
*/ |
||||
public void whitelist() { |
||||
blacklist = false; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if whitelist mode is set. |
||||
*/ |
||||
public boolean isWhitelist() { |
||||
return !blacklist; |
||||
} |
||||
|
||||
/** |
||||
* Sets blacklist or whitelist mode depending on rules. Smart mode |
||||
* determines the following: |
||||
* <ul> |
||||
* <li>If there are only include rules, then the {@link #whitelist() whitelist} mode is set.</li> |
||||
* <li>If there are only excluded rules, then the {@link #blacklist() blacklist} mode is set.</li> |
||||
* <li>In any other case (both type of rules exist or no rules are set), then mode is not changed.</li> |
||||
* </ul> |
||||
* Should be called <b>after</b> all the rules are set, before matching starts. |
||||
*/ |
||||
public void detectMode() { |
||||
if (excludesCount == 0 && includesCount > 0) { |
||||
whitelist(); |
||||
} |
||||
else if (excludesCount > 0 && includesCount == 0) { |
||||
blacklist(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Adds include rule. |
||||
*/ |
||||
public void include(final D rule) { |
||||
addRule(rule, true); |
||||
} |
||||
|
||||
/** |
||||
* Adds exclude rule. |
||||
*/ |
||||
public void exclude(final D rule) { |
||||
addRule(rule, false); |
||||
} |
||||
|
||||
/** |
||||
* Adds a rule. Duplicates are not allowed and will be ignored. |
||||
*/ |
||||
protected void addRule(final D ruleDefinition, final boolean include) { |
||||
if (rules == null) { |
||||
rules = new ArrayList<>(); |
||||
} |
||||
|
||||
if (include) { |
||||
includesCount++; |
||||
} else { |
||||
excludesCount++; |
||||
} |
||||
|
||||
Rule<R> newRule = new Rule<>(makeRule(ruleDefinition), include); |
||||
|
||||
if (rules.contains(newRule)) { |
||||
return; |
||||
} |
||||
|
||||
rules.add(newRule); |
||||
} |
||||
|
||||
protected R makeRule(final D rule) { |
||||
return (R) rule; |
||||
} |
||||
|
||||
/** |
||||
* Matches value against the set of rules using current white/black list mode. |
||||
*/ |
||||
public boolean match(final V value) { |
||||
return match(value, blacklist); |
||||
} |
||||
/** |
||||
* Matches value against the set of rules using provided white/black list mode. |
||||
*/ |
||||
public boolean match(final V value, final boolean blacklist) { |
||||
if (rules == null) { |
||||
return blacklist; |
||||
} |
||||
|
||||
boolean include = blacklist; |
||||
|
||||
if (include) { |
||||
include = processExcludes(value, true); |
||||
include = processIncludes(value, include); |
||||
} |
||||
else { |
||||
include = processIncludes(value, false); |
||||
include = processExcludes(value, include); |
||||
} |
||||
|
||||
return include; |
||||
} |
||||
|
||||
/** |
||||
* Applies rules on given flag using current black/white list mode. |
||||
* @see #apply(Object, boolean, boolean) |
||||
*/ |
||||
public boolean apply(final V value, final boolean flag) { |
||||
return apply(value, blacklist, flag); |
||||
} |
||||
|
||||
/** |
||||
* Applies rules on given flag. Flag is only changed if at least one rule |
||||
* matched. Otherwise, the same value is returned. This way you can |
||||
* chain several rules and have the rule engine change the flag |
||||
* only when a rule is matched. |
||||
*/ |
||||
public boolean apply(final V value, final boolean blacklist, boolean flag) { |
||||
if (rules == null) { |
||||
return flag; |
||||
} |
||||
|
||||
if (blacklist) { |
||||
flag = processExcludes(value, flag); |
||||
flag = processIncludes(value, flag); |
||||
} |
||||
else { |
||||
flag = processIncludes(value, flag); |
||||
flag = processExcludes(value, flag); |
||||
} |
||||
|
||||
return flag; |
||||
} |
||||
|
||||
/** |
||||
* Process includes rules. |
||||
*/ |
||||
protected boolean processIncludes(final V value, boolean include) { |
||||
if (includesCount > 0) { |
||||
if (!include) { |
||||
for (Rule<R> rule : rules) { |
||||
if (!rule.include) { |
||||
continue; |
||||
} |
||||
|
||||
if (inExRuleMatcher.accept(value, rule.value, true)) { |
||||
include = true; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return include; |
||||
} |
||||
|
||||
/** |
||||
* Process excludes rules. |
||||
*/ |
||||
protected boolean processExcludes(final V value, boolean include) { |
||||
if (excludesCount > 0) { |
||||
if (include) { |
||||
for (Rule<R> rule : rules) { |
||||
if (rule.include) { |
||||
continue; |
||||
} |
||||
|
||||
if (inExRuleMatcher.accept(value, rule.value, false)) { |
||||
include = false; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return include; |
||||
} |
||||
|
||||
/** |
||||
* Matches value against single rule. By default performs <code>equals</code> on value |
||||
* against the rule. |
||||
*/ |
||||
@Override |
||||
public boolean accept(final V value, final R rule, final boolean include) { |
||||
return value.equals(rule); |
||||
} |
||||
|
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Include-Exclude rules engine. |
||||
*/ |
||||
package com.fr.third.jodd.inex; |
@ -1,86 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.cache.TypeCache; |
||||
|
||||
/** |
||||
* Default {@link com.fr.third.jodd.introspector.ClassIntrospector introspector} that caches all class descriptors. |
||||
* It can examine either <b>accessible</b> or <b>supported</b> fields/methods/constructors. |
||||
* <p> |
||||
* It simply caches <b>all</b> class descriptors. |
||||
*/ |
||||
public class CachingIntrospector implements ClassIntrospector { |
||||
|
||||
protected final TypeCache<ClassDescriptor> cache; |
||||
protected final boolean scanAccessible; |
||||
protected final boolean enhancedProperties; |
||||
protected final boolean includeFieldsAsProperties; |
||||
protected final String[] propertyFieldPrefix; |
||||
|
||||
/** |
||||
* Default constructor. |
||||
*/ |
||||
public CachingIntrospector() { |
||||
this(true, true, true, null); |
||||
} |
||||
|
||||
/** |
||||
* Creates new caching {@link ClassIntrospector}. It may scan |
||||
* <b>accessible</b> or <b>supported</b> fields, methods or |
||||
* constructors. |
||||
*/ |
||||
public CachingIntrospector(final boolean scanAccessible, final boolean enhancedProperties, final boolean includeFieldsAsProperties, final String[] propertyFieldPrefix) { |
||||
this.cache = TypeCache.createDefault(); |
||||
this.scanAccessible = scanAccessible; |
||||
this.enhancedProperties = enhancedProperties; |
||||
this.includeFieldsAsProperties = includeFieldsAsProperties; |
||||
this.propertyFieldPrefix = propertyFieldPrefix; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public ClassDescriptor lookup(final Class type) { |
||||
return cache.get(type, (t) -> |
||||
new ClassDescriptor( |
||||
t, |
||||
scanAccessible, |
||||
enhancedProperties, |
||||
includeFieldsAsProperties, |
||||
propertyFieldPrefix)); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
@Override |
||||
public void reset() { |
||||
cache.clear(); |
||||
} |
||||
|
||||
} |
@ -1,378 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.function.Supplier; |
||||
|
||||
/** |
||||
* A descriptor class for all methods/fields/properties/constructors of a class. |
||||
* Static methods/fields are ignored. |
||||
* <p> |
||||
* Descriptors are 'lazy': various internal caches are created on first request. |
||||
* <p> |
||||
* Throughout this class, public members are defined as members |
||||
* defined with "public" keyword and declared in a public type. |
||||
* Public members declared by a non-public class is considered non-public |
||||
* because access to it from outside is prohibited by the java access control |
||||
* anyway. |
||||
* <p> |
||||
* Public members defined in public classes are always preferred even |
||||
* when we allow private/protected members and types to be visible. |
||||
* So if a non-public subtype and a public super type both have a field |
||||
* with the same name, the field in the public super type is always used. |
||||
*/ |
||||
public class ClassDescriptor { |
||||
|
||||
protected final Class type; |
||||
protected final boolean scanAccessible; |
||||
protected final boolean extendedProperties; |
||||
protected final boolean includeFieldsAsProperties; |
||||
protected final String[] propertyFieldPrefix; |
||||
protected final Class[] interfaces; |
||||
protected final Class[] superclasses; |
||||
|
||||
public ClassDescriptor(final Class type, final boolean scanAccessible, final boolean extendedProperties, final boolean includeFieldsAsProperties, final String[] propertyFieldPrefix) { |
||||
this.type = type; |
||||
this.scanAccessible = scanAccessible; |
||||
this.extendedProperties = extendedProperties; |
||||
this.includeFieldsAsProperties = includeFieldsAsProperties; |
||||
this.propertyFieldPrefix = propertyFieldPrefix; |
||||
|
||||
isArray = type.isArray(); |
||||
isMap = ClassUtil.isTypeOf(type, Map.class); |
||||
isList = ClassUtil.isTypeOf(type, List.class); |
||||
isSet = ClassUtil.isTypeOf(type, Set.class); |
||||
isCollection = ClassUtil.isTypeOf(type, Collection.class); |
||||
isSupplier = ClassUtil.isTypeOf(type, Supplier.class); |
||||
|
||||
interfaces = ClassUtil.resolveAllInterfaces(type); |
||||
superclasses = ClassUtil.resolveAllSuperclasses(type); |
||||
|
||||
isSystemClass = type.getName().startsWith("java.") && |
||||
!type.getName().startsWith("java.awt.geom."); |
||||
} |
||||
|
||||
/** |
||||
* Get the class object that this descriptor describes. |
||||
*/ |
||||
public Class getType() { |
||||
return type; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if this class descriptor |
||||
* works with accessible fields/methods/constructors or with |
||||
* all supported. |
||||
*/ |
||||
public boolean isScanAccessible() { |
||||
return scanAccessible; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if properties in this class descriptor |
||||
* are extended and include field description. |
||||
*/ |
||||
public boolean isExtendedProperties() { |
||||
return extendedProperties; |
||||
} |
||||
|
||||
/** |
||||
* Include fields as properties. |
||||
*/ |
||||
public boolean isIncludeFieldsAsProperties() { |
||||
return includeFieldsAsProperties; |
||||
} |
||||
|
||||
/** |
||||
* Returns property field prefixes. May be <code>null</code> |
||||
* if prefixes are not set. If you need to access both prefixed |
||||
* and non-prefixed fields, use empty string as one of the prefixes. |
||||
*/ |
||||
public String[] getPropertyFieldPrefix() { |
||||
return propertyFieldPrefix; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- special
|
||||
|
||||
private final boolean isArray; |
||||
/** |
||||
* Returns <code>true</code> if class is an array. |
||||
*/ |
||||
public boolean isArray() { |
||||
return isArray; |
||||
} |
||||
|
||||
private final boolean isMap; |
||||
/** |
||||
* Returns <code>true</code> if class is a <code>Map</code>. |
||||
*/ |
||||
public boolean isMap() { |
||||
return isMap; |
||||
} |
||||
|
||||
private final boolean isList; |
||||
/** |
||||
* Returns <code>true</code> if class is a <code>List</code>. |
||||
*/ |
||||
public boolean isList() { |
||||
return isList; |
||||
} |
||||
|
||||
private final boolean isSet; |
||||
/** |
||||
* Returns <code>true</code> if type is a <code>Set</code>. |
||||
*/ |
||||
public boolean isSet() { |
||||
return isSet; |
||||
} |
||||
|
||||
private final boolean isCollection; |
||||
/** |
||||
* Returns <code>true</code> if type is a collection. |
||||
*/ |
||||
public boolean isCollection() { |
||||
return isCollection; |
||||
} |
||||
|
||||
private final boolean isSupplier; |
||||
|
||||
/** |
||||
* Returns <code>true</code> if type is a supplier. |
||||
*/ |
||||
public boolean isSupplier() { |
||||
return isSupplier; |
||||
} |
||||
|
||||
private boolean isSystemClass; |
||||
|
||||
/** |
||||
* Returns <code>true</code> is class is a system class and should not |
||||
* expose fields or declared methods. |
||||
*/ |
||||
public boolean isSystemClass() { |
||||
return isSystemClass; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- fields
|
||||
|
||||
private Fields fields; |
||||
|
||||
/** |
||||
* Returns {@link Fields fields collection}. |
||||
* Creates new fields collection on first usage. |
||||
*/ |
||||
protected Fields getFields() { |
||||
if (fields == null) { |
||||
fields = new Fields(this); |
||||
} |
||||
return fields; |
||||
} |
||||
|
||||
/** |
||||
* Returns field descriptor. |
||||
*/ |
||||
public FieldDescriptor getFieldDescriptor(final String name, final boolean declared) { |
||||
final FieldDescriptor fieldDescriptor = getFields().getFieldDescriptor(name); |
||||
|
||||
if (fieldDescriptor != null) { |
||||
if (!fieldDescriptor.matchDeclared(declared)) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
return fieldDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns all field descriptors, including declared ones. |
||||
*/ |
||||
public FieldDescriptor[] getAllFieldDescriptors() { |
||||
return getFields().getAllFieldDescriptors(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- methods
|
||||
|
||||
private Methods methods; |
||||
|
||||
/** |
||||
* Returns methods collection. |
||||
* Creates new collection on first access. |
||||
*/ |
||||
protected Methods getMethods() { |
||||
if (methods == null) { |
||||
methods = new Methods(this); |
||||
} |
||||
return methods; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@link MethodDescriptor method descriptor} identified by name and parameters. |
||||
*/ |
||||
public MethodDescriptor getMethodDescriptor(final String name, final boolean declared) { |
||||
final MethodDescriptor methodDescriptor = getMethods().getMethodDescriptor(name); |
||||
|
||||
if ((methodDescriptor != null) && methodDescriptor.matchDeclared(declared)) { |
||||
return methodDescriptor; |
||||
} |
||||
|
||||
return methodDescriptor; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns {@link MethodDescriptor method descriptor} identified by name and parameters. |
||||
*/ |
||||
public MethodDescriptor getMethodDescriptor(final String name, final Class[] params, final boolean declared) { |
||||
final MethodDescriptor methodDescriptor = getMethods().getMethodDescriptor(name, params); |
||||
|
||||
if ((methodDescriptor != null) && methodDescriptor.matchDeclared(declared)) { |
||||
return methodDescriptor; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns an array of all methods with the same name. |
||||
*/ |
||||
public MethodDescriptor[] getAllMethodDescriptors(final String name) { |
||||
return getMethods().getAllMethodDescriptors(name); |
||||
} |
||||
|
||||
/** |
||||
* Returns an array of all methods. |
||||
*/ |
||||
public MethodDescriptor[] getAllMethodDescriptors() { |
||||
return getMethods().getAllMethodDescriptors(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- properties
|
||||
|
||||
private Properties properties; |
||||
|
||||
/** |
||||
* Returns properties collection. |
||||
* Creates new collection on first access. |
||||
*/ |
||||
protected Properties getProperties() { |
||||
if (properties == null) { |
||||
properties = new Properties(this); |
||||
} |
||||
return properties; |
||||
} |
||||
|
||||
/** |
||||
* Returns property descriptor. Declared flag is matched on both read and write |
||||
* methods. |
||||
*/ |
||||
public PropertyDescriptor getPropertyDescriptor(final String name, final boolean declared) { |
||||
PropertyDescriptor propertyDescriptor = getProperties().getPropertyDescriptor(name); |
||||
|
||||
if ((propertyDescriptor != null) && propertyDescriptor.matchDeclared(declared)) { |
||||
return propertyDescriptor; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns all properties descriptors. |
||||
*/ |
||||
public PropertyDescriptor[] getAllPropertyDescriptors() { |
||||
return getProperties().getAllPropertyDescriptors(); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- ctors
|
||||
|
||||
private Ctors ctors; |
||||
|
||||
/** |
||||
* Returns constructors collection. |
||||
* Creates new collection of first access. |
||||
*/ |
||||
protected Ctors getCtors() { |
||||
if (ctors == null) { |
||||
ctors = new Ctors(this); |
||||
} |
||||
return ctors; |
||||
} |
||||
|
||||
/** |
||||
* Returns the default ctor or <code>null</code> if not found. |
||||
*/ |
||||
public CtorDescriptor getDefaultCtorDescriptor(final boolean declared) { |
||||
CtorDescriptor defaultCtor = getCtors().getDefaultCtor(); |
||||
|
||||
if ((defaultCtor != null) && defaultCtor.matchDeclared(declared)) { |
||||
return defaultCtor; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns the constructor identified by arguments or <code>null</code> if not found. |
||||
*/ |
||||
public CtorDescriptor getCtorDescriptor(final Class[] args, final boolean declared) { |
||||
CtorDescriptor ctorDescriptor = getCtors().getCtorDescriptor(args); |
||||
|
||||
if ((ctorDescriptor != null) && ctorDescriptor.matchDeclared(declared)) { |
||||
return ctorDescriptor; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns an array of all {@link CtorDescriptor constructor descriptors}. |
||||
*/ |
||||
public CtorDescriptor[] getAllCtorDescriptors() { |
||||
return getCtors().getAllCtorDescriptors(); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- interfaces
|
||||
|
||||
/** |
||||
* Returns <b>all</b> interfaces of this class. |
||||
*/ |
||||
public Class[] getAllInterfaces() { |
||||
return interfaces; |
||||
} |
||||
|
||||
/** |
||||
* Returns <b>all</b> superclasses of this class. |
||||
* <code>Object.class</code> is <b>not</b> included in the |
||||
* returned list. |
||||
*/ |
||||
public Class[] getAllSuperclasses() { |
||||
return superclasses; |
||||
} |
||||
} |
@ -1,66 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
|
||||
import java.util.Objects; |
||||
|
||||
/** |
||||
* Default class {@link ClassIntrospector} simply delegates method calls for |
||||
* more convenient usage. |
||||
*/ |
||||
public interface ClassIntrospector { |
||||
|
||||
class Implementation { |
||||
private static ClassIntrospector classIntrospector = new CachingIntrospector(); |
||||
|
||||
/** |
||||
* Sets default implementation. |
||||
*/ |
||||
public static void set(final ClassIntrospector classIntrospector) { |
||||
Objects.requireNonNull(classIntrospector); |
||||
Implementation.classIntrospector = classIntrospector; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns default implementation. |
||||
*/ |
||||
static ClassIntrospector get() { |
||||
return Implementation.classIntrospector; |
||||
} |
||||
|
||||
/** |
||||
* Returns class descriptor for specified type. |
||||
*/ |
||||
ClassDescriptor lookup(Class type); |
||||
|
||||
/** |
||||
* Clears all cached data. |
||||
*/ |
||||
void reset(); |
||||
|
||||
} |
@ -1,79 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Constructor; |
||||
|
||||
/** |
||||
* Constructor descriptor. |
||||
*/ |
||||
public class CtorDescriptor extends Descriptor { |
||||
|
||||
protected final Constructor constructor; |
||||
protected final Class[] parameters; |
||||
|
||||
public CtorDescriptor(final ClassDescriptor classDescriptor, final Constructor constructor) { |
||||
super(classDescriptor, ClassUtil.isPublic(constructor)); |
||||
this.constructor = constructor; |
||||
this.parameters = constructor.getParameterTypes(); |
||||
|
||||
ClassUtil.forceAccess(constructor); |
||||
} |
||||
|
||||
/** |
||||
* Returns constructor name. |
||||
*/ |
||||
@Override |
||||
public String getName() { |
||||
return constructor.getName(); |
||||
} |
||||
|
||||
/** |
||||
* Returns constructor. |
||||
*/ |
||||
public Constructor getConstructor() { |
||||
return constructor; |
||||
} |
||||
|
||||
/** |
||||
* Returns constructors parameters. The returned array |
||||
* is not cloned. |
||||
*/ |
||||
public Class[] getParameters() { |
||||
return parameters; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if this is a default constructor |
||||
* (with no parameters). |
||||
*/ |
||||
public boolean isDefault() { |
||||
return parameters.length == 0; |
||||
} |
||||
|
||||
} |
@ -1,113 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import java.lang.reflect.Constructor; |
||||
|
||||
/** |
||||
* Constructors collection. |
||||
*/ |
||||
public class Ctors { |
||||
|
||||
protected final ClassDescriptor classDescriptor; |
||||
protected final CtorDescriptor[] allCtors; |
||||
protected CtorDescriptor defaultCtor; |
||||
|
||||
public Ctors(final ClassDescriptor classDescriptor) { |
||||
this.classDescriptor = classDescriptor; |
||||
this.allCtors = inspectConstructors(); |
||||
} |
||||
|
||||
/** |
||||
* Inspects all declared constructors of a target type. |
||||
*/ |
||||
protected CtorDescriptor[] inspectConstructors() { |
||||
Class type = classDescriptor.getType(); |
||||
Constructor[] ctors = type.getDeclaredConstructors(); |
||||
|
||||
CtorDescriptor[] allCtors = new CtorDescriptor[ctors.length]; |
||||
|
||||
for (int i = 0; i < ctors.length; i++) { |
||||
Constructor ctor = ctors[i]; |
||||
|
||||
CtorDescriptor ctorDescriptor = createCtorDescriptor(ctor); |
||||
allCtors[i] = ctorDescriptor; |
||||
|
||||
if (ctorDescriptor.isDefault()) { |
||||
defaultCtor = ctorDescriptor; |
||||
} |
||||
} |
||||
|
||||
return allCtors; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link CtorDescriptor}. |
||||
*/ |
||||
protected CtorDescriptor createCtorDescriptor(final Constructor ctor) { |
||||
return new CtorDescriptor(classDescriptor, ctor); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns default (no-args) constructor descriptor. |
||||
*/ |
||||
public CtorDescriptor getDefaultCtor() { |
||||
return defaultCtor; |
||||
} |
||||
|
||||
/** |
||||
* Finds constructor description that matches given argument types. |
||||
*/ |
||||
public CtorDescriptor getCtorDescriptor(final Class... args) { |
||||
ctors: |
||||
for (CtorDescriptor ctorDescriptor : allCtors) { |
||||
Class[] arg = ctorDescriptor.getParameters(); |
||||
|
||||
if (arg.length != args.length) { |
||||
continue; |
||||
} |
||||
|
||||
for (int j = 0; j < arg.length; j++) { |
||||
if (arg[j] != args[j]) { |
||||
continue ctors; |
||||
} |
||||
} |
||||
|
||||
return ctorDescriptor; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns all constructor descriptors. |
||||
*/ |
||||
CtorDescriptor[] getAllCtorDescriptors() { |
||||
return allCtors; |
||||
} |
||||
|
||||
} |
@ -1,70 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
/** |
||||
* Common descriptor stuff. |
||||
*/ |
||||
public abstract class Descriptor { |
||||
|
||||
protected final ClassDescriptor classDescriptor; |
||||
protected final boolean isPublic; |
||||
|
||||
protected Descriptor(final ClassDescriptor classDescriptor, final boolean isPublic) { |
||||
this.classDescriptor = classDescriptor; |
||||
this.isPublic = isPublic; |
||||
} |
||||
|
||||
/** |
||||
* Returns belonging class descriptor. |
||||
*/ |
||||
public ClassDescriptor getClassDescriptor() { |
||||
return classDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if descriptor content is public. |
||||
*/ |
||||
public boolean isPublic() { |
||||
return isPublic; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if descriptor content matches required declared flag. |
||||
*/ |
||||
public boolean matchDeclared(final boolean declared) { |
||||
if (!declared) { |
||||
return isPublic; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Returns the name of descriptors target. |
||||
*/ |
||||
public abstract String getName(); |
||||
|
||||
} |
@ -1,134 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Field; |
||||
import java.lang.reflect.Type; |
||||
|
||||
/** |
||||
* Field descriptor. Holds additional field data, |
||||
* that might be specific to implementation class. |
||||
*/ |
||||
public class FieldDescriptor extends Descriptor { |
||||
|
||||
public static final FieldDescriptor[] EMPTY_ARRAY = new FieldDescriptor[0]; |
||||
|
||||
protected final Field field; |
||||
protected final Type type; |
||||
protected final Class rawType; |
||||
protected final Class rawComponentType; |
||||
protected final Class rawKeyComponentType; |
||||
protected final MapperFunction mapperFunction; |
||||
|
||||
/** |
||||
* Creates new field descriptor and resolve all additional field data. |
||||
* Also, forces access to a field. |
||||
*/ |
||||
public FieldDescriptor(final ClassDescriptor classDescriptor, final Field field) { |
||||
super(classDescriptor, ClassUtil.isPublic(field)); |
||||
this.field = field; |
||||
this.type = field.getGenericType(); |
||||
this.rawType = ClassUtil.getRawType(type, classDescriptor.getType()); |
||||
|
||||
final Class[] componentTypes = ClassUtil.getComponentTypes(type, classDescriptor.getType()); |
||||
if (componentTypes != null) { |
||||
this.rawComponentType = componentTypes[componentTypes.length - 1]; |
||||
this.rawKeyComponentType = componentTypes[0]; |
||||
} else { |
||||
this.rawComponentType = null; |
||||
this.rawKeyComponentType = null; |
||||
} |
||||
|
||||
// force access
|
||||
|
||||
ClassUtil.forceAccess(field); |
||||
|
||||
// mapper
|
||||
|
||||
final Mapper mapper = field.getAnnotation(Mapper.class); |
||||
|
||||
if (mapper != null) { |
||||
mapperFunction = MapperFunctionInstances.get().lookup(mapper.value()); |
||||
} else { |
||||
mapperFunction = null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns field name. |
||||
*/ |
||||
@Override |
||||
public String getName() { |
||||
return field.getName(); |
||||
} |
||||
|
||||
/** |
||||
* Returns field. |
||||
*/ |
||||
public Field getField() { |
||||
return field; |
||||
} |
||||
|
||||
/** |
||||
* Returns fields raw type. |
||||
*/ |
||||
public Class getRawType() { |
||||
return rawType; |
||||
} |
||||
|
||||
/** |
||||
* Returns fields raw component type. Returns <code>null</code> |
||||
* if field has no component type. |
||||
*/ |
||||
public Class getRawComponentType() { |
||||
return rawComponentType; |
||||
} |
||||
|
||||
/** |
||||
* Returns fields raw component type. Returns <code>null</code> |
||||
* if field has no component type. |
||||
*/ |
||||
public Class getRawKeyComponentType() { |
||||
return rawKeyComponentType; |
||||
} |
||||
|
||||
/** |
||||
* Resolves raw component type for given index. This value is NOT cached. |
||||
*/ |
||||
public Class[] resolveRawComponentTypes() { |
||||
return ClassUtil.getComponentTypes(type, classDescriptor.getType()); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- toString
|
||||
|
||||
@Override |
||||
public String toString() { |
||||
return classDescriptor.getType().getSimpleName() + '#' + field.getName(); |
||||
} |
||||
|
||||
} |
@ -1,130 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Field; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.Comparator; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Collection of {@link FieldDescriptor field descriptors}. |
||||
*/ |
||||
public class Fields { |
||||
|
||||
protected final ClassDescriptor classDescriptor; |
||||
protected final Map<String, FieldDescriptor> fieldsMap; |
||||
|
||||
// cache
|
||||
private FieldDescriptor[] allFields; |
||||
|
||||
/** |
||||
* Creates new fields collection. |
||||
*/ |
||||
public Fields(final ClassDescriptor classDescriptor) { |
||||
this.classDescriptor = classDescriptor; |
||||
this.fieldsMap = inspectFields(); |
||||
} |
||||
|
||||
/** |
||||
* Inspects fields and returns map of {@link FieldDescriptor field descriptors}. |
||||
*/ |
||||
private Map<String, FieldDescriptor> inspectFields() { |
||||
if (classDescriptor.isSystemClass()) { |
||||
return emptyFields(); |
||||
} |
||||
final boolean scanAccessible = classDescriptor.isScanAccessible(); |
||||
final Class type = classDescriptor.getType(); |
||||
|
||||
final Field[] fields = scanAccessible ? ClassUtil.getAccessibleFields(type) : ClassUtil.getSupportedFields(type); |
||||
|
||||
final HashMap<String, FieldDescriptor> map = new HashMap<>(fields.length); |
||||
|
||||
for (final Field field : fields) { |
||||
final String fieldName = field.getName(); |
||||
|
||||
if (fieldName.equals("serialVersionUID")) { |
||||
continue; |
||||
} |
||||
|
||||
map.put(fieldName, createFieldDescriptor(field)); |
||||
} |
||||
|
||||
return map; |
||||
} |
||||
|
||||
/** |
||||
* Defines empty fields for special cases. |
||||
*/ |
||||
private Map<String, FieldDescriptor> emptyFields() { |
||||
allFields = FieldDescriptor.EMPTY_ARRAY; |
||||
return Collections.emptyMap(); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@code FieldDescriptor}. |
||||
*/ |
||||
protected FieldDescriptor createFieldDescriptor(final Field field) { |
||||
return new FieldDescriptor(classDescriptor, field); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns {@link FieldDescriptor field descriptor} for given field name |
||||
* or <code>null</code> if field does not exist. |
||||
*/ |
||||
public FieldDescriptor getFieldDescriptor(final String name) { |
||||
return fieldsMap.get(name); |
||||
} |
||||
|
||||
/** |
||||
* Returns all fields of this collection. Returns empty array |
||||
* if no fields exist. Initialized lazy. |
||||
*/ |
||||
public FieldDescriptor[] getAllFieldDescriptors() { |
||||
if (allFields == null) { |
||||
FieldDescriptor[] allFields = new FieldDescriptor[fieldsMap.size()]; |
||||
|
||||
int index = 0; |
||||
for (FieldDescriptor fieldDescriptor : fieldsMap.values()) { |
||||
allFields[index] = fieldDescriptor; |
||||
index++; |
||||
} |
||||
|
||||
Arrays.sort(allFields, Comparator.comparing(fd -> fd.getField().getName())); |
||||
|
||||
this.allFields = allFields; |
||||
} |
||||
return allFields; |
||||
} |
||||
|
||||
} |
@ -1,94 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import java.lang.reflect.InvocationTargetException; |
||||
|
||||
/** |
||||
* Unified getter property interface for both methods and fields. |
||||
*/ |
||||
public interface Getter { |
||||
|
||||
static Getter of(final MethodDescriptor methodDescriptor) { |
||||
|
||||
return new Getter() { |
||||
|
||||
@Override |
||||
public Object invokeGetter(final Object target) throws InvocationTargetException, IllegalAccessException { |
||||
return methodDescriptor.method.invoke(target); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawType() { |
||||
return methodDescriptor.getRawReturnType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawComponentType() { |
||||
return methodDescriptor.getRawReturnComponentType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawKeyComponentType() { |
||||
return methodDescriptor.getRawReturnKeyComponentType(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
static Getter of(final FieldDescriptor fieldDescriptor) { |
||||
return new Getter() { |
||||
|
||||
@Override |
||||
public Object invokeGetter(final Object target) throws IllegalAccessException { |
||||
return fieldDescriptor.field.get(target); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawType() { |
||||
return fieldDescriptor.getRawType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawComponentType() { |
||||
return fieldDescriptor.getRawComponentType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getGetterRawKeyComponentType() { |
||||
return fieldDescriptor.getRawKeyComponentType(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
Object invokeGetter(Object target) throws InvocationTargetException, IllegalAccessException; |
||||
|
||||
Class getGetterRawType(); |
||||
|
||||
Class getGetterRawComponentType(); |
||||
|
||||
Class getGetterRawKeyComponentType(); |
||||
|
||||
} |
@ -1,43 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
/** |
||||
* Value or type mapper. |
||||
* @see MapperFunction |
||||
*/ |
||||
@Documented |
||||
@Retention(value = RetentionPolicy.RUNTIME) |
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) |
||||
public @interface Mapper { |
||||
Class<? extends MapperFunction> value(); |
||||
} |
@ -1,37 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import java.util.function.Function; |
||||
|
||||
/** |
||||
* Mapper function allows object to be converted before actually used - usually before injected using |
||||
* {@link com.fr.third.jodd.bean.BeanUtil}. |
||||
*/ |
||||
@FunctionalInterface |
||||
public interface MapperFunction<IN, OUT> extends Function<IN, OUT> { |
||||
|
||||
} |
@ -1,57 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.cache.TypeCache; |
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
/** |
||||
* Simple cache of {@link MapperFunction} instances. |
||||
*/ |
||||
public class MapperFunctionInstances { |
||||
|
||||
private static final MapperFunctionInstances MAPPER_FUNCTION_INSTANCES = new MapperFunctionInstances(); |
||||
|
||||
/** |
||||
* Returns the instance. |
||||
*/ |
||||
public static MapperFunctionInstances get() { |
||||
return MAPPER_FUNCTION_INSTANCES; |
||||
} |
||||
|
||||
protected TypeCache<MapperFunction> typeCache = TypeCache.createDefault(); |
||||
|
||||
public MapperFunction lookup(final Class<? extends MapperFunction> mapperFunctionClass) { |
||||
return typeCache.get(mapperFunctionClass, (c) -> { |
||||
try { |
||||
return ClassUtil.newInstance(mapperFunctionClass); |
||||
} catch (final Exception ex) { |
||||
throw new IllegalArgumentException("Invalid mapper class " + c, ex); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
@ -1,193 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.Type; |
||||
|
||||
/** |
||||
* Method descriptor. Holds additional method data, |
||||
* that might be specific to implementation class. |
||||
*/ |
||||
public class MethodDescriptor extends Descriptor { |
||||
|
||||
private static final MethodParamDescriptor[] NO_PARAMS = new MethodParamDescriptor[0]; |
||||
|
||||
protected final Method method; |
||||
protected final Type returnType; |
||||
protected final Class rawReturnType; |
||||
protected final Class rawReturnComponentType; |
||||
protected final Class rawReturnKeyComponentType; |
||||
protected final MethodParamDescriptor[] parameters; |
||||
protected final MapperFunction mapperFunction; |
||||
|
||||
// protected final Function getterFunction;
|
||||
|
||||
public MethodDescriptor(final ClassDescriptor classDescriptor, final Method method) { |
||||
super(classDescriptor, ClassUtil.isPublic(method)); |
||||
this.method = method; |
||||
this.returnType = method.getGenericReturnType(); |
||||
this.rawReturnType = ClassUtil.getRawType(returnType, classDescriptor.getType()); |
||||
|
||||
final Class[] componentTypes = ClassUtil.getComponentTypes(returnType, classDescriptor.getType()); |
||||
if (componentTypes != null) { |
||||
this.rawReturnComponentType = componentTypes[componentTypes.length - 1]; |
||||
this.rawReturnKeyComponentType = componentTypes[0]; |
||||
} else { |
||||
this.rawReturnComponentType = null; |
||||
this.rawReturnKeyComponentType = null; |
||||
} |
||||
|
||||
// force access
|
||||
|
||||
ClassUtil.forceAccess(method); |
||||
|
||||
// mapper
|
||||
|
||||
final Mapper mapper = method.getAnnotation(Mapper.class); |
||||
|
||||
if (mapper != null) { |
||||
mapperFunction = MapperFunctionInstances.get().lookup(mapper.value()); |
||||
} else { |
||||
mapperFunction = null; |
||||
} |
||||
|
||||
// parameters
|
||||
|
||||
if (method.getParameterCount() == 0) { |
||||
parameters = NO_PARAMS; |
||||
} |
||||
else { |
||||
parameters = new MethodParamDescriptor[method.getParameterCount()]; |
||||
|
||||
Class[] params = method.getParameterTypes(); |
||||
Type[] genericParams = method.getGenericParameterTypes(); |
||||
|
||||
for (int i = 0; i < params.length; i++) { |
||||
final Class parameterType = params[i]; |
||||
final Class rawParameterType = genericParams.length == 0 ? |
||||
parameterType : |
||||
ClassUtil.getRawType(genericParams[i], classDescriptor.getType()); |
||||
final Class rawParameterComponentType = genericParams.length == 0 ? |
||||
null : |
||||
ClassUtil.getComponentType(genericParams[i], classDescriptor.getType(), -1); |
||||
|
||||
parameters[i] = new MethodParamDescriptor(parameterType, rawParameterType, rawParameterComponentType); |
||||
} |
||||
} |
||||
|
||||
// try {
|
||||
// MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
// CallSite callSite = LambdaMetafactory.metafactory(lookup,
|
||||
// "apply",
|
||||
// MethodType.methodType(Function.class),
|
||||
// MethodType.methodType(Object.class, Object.class),
|
||||
// lookup.findVirtual(
|
||||
// classDescriptor.getType(),
|
||||
// method.getName(),
|
||||
// MethodType.methodType(method.getReturnType())),
|
||||
// MethodType.methodType(method.getReturnType(), classDescriptor.type)
|
||||
// );
|
||||
//
|
||||
// this.getterFunction = (Function) callSite.getTarget().invokeExact();
|
||||
// }
|
||||
// catch (Throwable ex) {
|
||||
// throw new IllegalArgumentException(ex);
|
||||
// }
|
||||
} |
||||
|
||||
/** |
||||
* Returns method name. |
||||
*/ |
||||
@Override |
||||
public String getName() { |
||||
return method.getName(); |
||||
} |
||||
|
||||
/** |
||||
* Returns method. |
||||
*/ |
||||
public Method getMethod() { |
||||
return method; |
||||
} |
||||
|
||||
/** |
||||
* Returns raw return type. |
||||
*/ |
||||
public Class getRawReturnType() { |
||||
return rawReturnType; |
||||
} |
||||
|
||||
/** |
||||
* Returns raw component type of return type. |
||||
* May be <code>null</code> if return type does not have |
||||
* components. |
||||
*/ |
||||
public Class getRawReturnComponentType() { |
||||
return rawReturnComponentType; |
||||
} |
||||
|
||||
/** |
||||
* Returns raw component type of return type. |
||||
* May be <code>null</code> if return type does not have |
||||
* components. |
||||
*/ |
||||
public Class getRawReturnKeyComponentType() { |
||||
return rawReturnKeyComponentType; |
||||
} |
||||
|
||||
/** |
||||
* Resolves raw return component types |
||||
* This value is NOT cached. |
||||
*/ |
||||
public Class[] resolveRawReturnComponentTypes() { |
||||
return ClassUtil.getComponentTypes(returnType, classDescriptor.getType()); |
||||
} |
||||
|
||||
/** |
||||
* Returns {@link MethodParamDescriptor method parameteres}. |
||||
*/ |
||||
public MethodParamDescriptor[] getParameters() { |
||||
return parameters; |
||||
} |
||||
|
||||
/** |
||||
* Returns number of parameters. |
||||
*/ |
||||
public int getParameterCount() { |
||||
return parameters.length; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- toString
|
||||
|
||||
@Override |
||||
public String toString() { |
||||
return classDescriptor.getType().getSimpleName() + '#' + method.getName() + "()"; |
||||
} |
||||
|
||||
} |
@ -1,53 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
/** |
||||
* Method parameter descriptor. |
||||
*/ |
||||
public class MethodParamDescriptor { |
||||
protected final Class type; |
||||
protected final Class rawType; |
||||
protected final Class rawComponentType; |
||||
|
||||
public MethodParamDescriptor(final Class parameterType, final Class rawParameterType, final Class rawParameterComponentType) { |
||||
this.type = parameterType; |
||||
this.rawType = rawParameterType; |
||||
this.rawComponentType = rawParameterComponentType; |
||||
} |
||||
|
||||
public Class getType() { |
||||
return type; |
||||
} |
||||
|
||||
public Class getRawType() { |
||||
return rawType; |
||||
} |
||||
|
||||
public Class getRawComponentType() { |
||||
return rawComponentType; |
||||
} |
||||
} |
@ -1,162 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ArraysUtil; |
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.Comparator; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Methods collection. |
||||
*/ |
||||
public class Methods { |
||||
|
||||
protected final ClassDescriptor classDescriptor; |
||||
protected final HashMap<String, MethodDescriptor[]> methodsMap; |
||||
|
||||
// cache
|
||||
private MethodDescriptor[] allMethods; |
||||
|
||||
public Methods(final ClassDescriptor classDescriptor) { |
||||
this.classDescriptor = classDescriptor; |
||||
this.methodsMap = inspectMethods(); |
||||
} |
||||
|
||||
/** |
||||
* Inspects types methods and return map of {@link MethodDescriptor method descriptors}. |
||||
*/ |
||||
protected HashMap<String, MethodDescriptor[]> inspectMethods() { |
||||
boolean scanAccessible = classDescriptor.isScanAccessible(); |
||||
|
||||
if (classDescriptor.isSystemClass()) { |
||||
scanAccessible = false; |
||||
} |
||||
|
||||
final Class type = classDescriptor.getType(); |
||||
|
||||
final Method[] methods = scanAccessible ? ClassUtil.getAccessibleMethods(type) : ClassUtil.getSupportedMethods(type); |
||||
|
||||
final HashMap<String, MethodDescriptor[]> map = new HashMap<>(methods.length); |
||||
|
||||
for (final Method method : methods) { |
||||
final String methodName = method.getName(); |
||||
|
||||
MethodDescriptor[] mds = map.get(methodName); |
||||
|
||||
if (mds == null) { |
||||
mds = new MethodDescriptor[1]; |
||||
} else { |
||||
mds = ArraysUtil.resize(mds, mds.length + 1); |
||||
} |
||||
|
||||
map.put(methodName, mds); |
||||
|
||||
mds[mds.length - 1] = createMethodDescriptor(method); |
||||
} |
||||
|
||||
return map; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@code MethodDescriptor}. |
||||
*/ |
||||
protected MethodDescriptor createMethodDescriptor(final Method method) { |
||||
return new MethodDescriptor(classDescriptor, method); |
||||
} |
||||
|
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns a method that matches given name and parameter types. |
||||
* Returns <code>null</code> if method is not found. |
||||
*/ |
||||
public MethodDescriptor getMethodDescriptor(final String name, final Class[] paramTypes) { |
||||
final MethodDescriptor[] methodDescriptors = methodsMap.get(name); |
||||
if (methodDescriptors == null) { |
||||
return null; |
||||
} |
||||
for (MethodDescriptor methodDescriptor : methodDescriptors) { |
||||
final Method m = methodDescriptor.getMethod(); |
||||
if (ClassUtil.compareParameters(m.getParameterTypes(), paramTypes)) { |
||||
return methodDescriptor; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns method descriptor for given name. If more then one methods with |
||||
* the same name exists, one method will be returned (not determined which one). |
||||
* Returns <code>null</code> if no method exist in this collection by given name. |
||||
* @see #getMethodDescriptor(String, Class[]) |
||||
*/ |
||||
public MethodDescriptor getMethodDescriptor(final String name) { |
||||
final MethodDescriptor[] methodDescriptors = methodsMap.get(name); |
||||
if (methodDescriptors == null) { |
||||
return null; |
||||
} |
||||
if (methodDescriptors.length != 1) { |
||||
throw new IllegalArgumentException("Method name not unique: " + name); |
||||
} |
||||
return methodDescriptors[0]; |
||||
} |
||||
|
||||
/** |
||||
* Returns all methods for given name. Returns <code>null</code> if method not found. |
||||
*/ |
||||
public MethodDescriptor[] getAllMethodDescriptors(final String name) { |
||||
return methodsMap.get(name); |
||||
} |
||||
|
||||
/** |
||||
* Returns all methods. Cached. Lazy. |
||||
*/ |
||||
public MethodDescriptor[] getAllMethodDescriptors() { |
||||
if (allMethods == null) { |
||||
final List<MethodDescriptor> allMethodsList = new ArrayList<>(); |
||||
|
||||
for (MethodDescriptor[] methodDescriptors : methodsMap.values()) { |
||||
Collections.addAll(allMethodsList, methodDescriptors); |
||||
} |
||||
|
||||
final MethodDescriptor[] allMethods = allMethodsList.toArray(new MethodDescriptor[0]); |
||||
|
||||
Arrays.sort(allMethods, Comparator.comparing(md -> md.getMethod().getName())); |
||||
|
||||
this.allMethods = allMethods; |
||||
} |
||||
return allMethods; |
||||
} |
||||
|
||||
} |
@ -1,255 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import com.fr.third.jodd.util.ClassUtil; |
||||
|
||||
import java.lang.reflect.Field; |
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.Modifier; |
||||
import java.util.Arrays; |
||||
import java.util.Comparator; |
||||
import java.util.HashMap; |
||||
|
||||
import static com.fr.third.jodd.util.ClassUtil.METHOD_GET_PREFIX; |
||||
import static com.fr.third.jodd.util.ClassUtil.METHOD_IS_PREFIX; |
||||
|
||||
/** |
||||
* Bean properties collection. Property in Java is defined as a pair of |
||||
* read and write method. In Jodd, property can be extended with field |
||||
* definition. Moreover, properties will include just single fields. |
||||
* This behavior can be controlled via {@link ClassDescriptor}. |
||||
*/ |
||||
public class Properties { |
||||
|
||||
protected final ClassDescriptor classDescriptor; |
||||
protected final HashMap<String, PropertyDescriptor> propertyDescriptors; |
||||
|
||||
// cache
|
||||
private PropertyDescriptor[] allProperties; |
||||
|
||||
public Properties(final ClassDescriptor classDescriptor) { |
||||
this.classDescriptor = classDescriptor; |
||||
this.propertyDescriptors = inspectProperties(); |
||||
} |
||||
|
||||
/** |
||||
* Inspects all properties of target type. |
||||
*/ |
||||
protected HashMap<String, PropertyDescriptor> inspectProperties() { |
||||
boolean scanAccessible = classDescriptor.isScanAccessible(); |
||||
Class type = classDescriptor.getType(); |
||||
|
||||
HashMap<String, PropertyDescriptor> map = new HashMap<>(); |
||||
|
||||
Method[] methods = scanAccessible ? ClassUtil.getAccessibleMethods(type) : ClassUtil.getSupportedMethods(type); |
||||
|
||||
for (int iteration = 0; iteration < 2; iteration++) { |
||||
// first find the getters, and then the setters!
|
||||
for (Method method : methods) { |
||||
if (Modifier.isStatic(method.getModifiers())) { |
||||
continue; // ignore static methods
|
||||
} |
||||
|
||||
boolean add = false; |
||||
boolean issetter = false; |
||||
|
||||
String propertyName; |
||||
|
||||
if (iteration == 0) { |
||||
propertyName = ClassUtil.getBeanPropertyGetterName(method); |
||||
if (propertyName != null) { |
||||
add = true; |
||||
issetter = false; |
||||
} |
||||
} else { |
||||
propertyName = ClassUtil.getBeanPropertySetterName(method); |
||||
if (propertyName != null) { |
||||
add = true; |
||||
issetter = true; |
||||
} |
||||
} |
||||
|
||||
if (add) { |
||||
MethodDescriptor methodDescriptor = classDescriptor.getMethodDescriptor(method.getName(), method.getParameterTypes(), true); |
||||
addProperty(map, propertyName, methodDescriptor, issetter); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (classDescriptor.isIncludeFieldsAsProperties()) { |
||||
FieldDescriptor[] fieldDescriptors = classDescriptor.getAllFieldDescriptors(); |
||||
String[] prefix = classDescriptor.getPropertyFieldPrefix(); |
||||
|
||||
for (FieldDescriptor fieldDescriptor : fieldDescriptors) { |
||||
Field field = fieldDescriptor.getField(); |
||||
|
||||
if (Modifier.isStatic(field.getModifiers())) { |
||||
continue; // ignore static fields
|
||||
} |
||||
|
||||
String name = field.getName(); |
||||
|
||||
if (prefix != null) { |
||||
for (String p : prefix) { |
||||
if (!name.startsWith(p)) { |
||||
continue; |
||||
} |
||||
name = name.substring(p.length()); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (!map.containsKey(name)) { |
||||
// add missing field as a potential property
|
||||
map.put(name, createPropertyDescriptor(name, fieldDescriptor)); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
return map; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Adds a setter and/or getter method to the property. |
||||
* If property is already defined, the new, updated, definition will be created. |
||||
*/ |
||||
protected void addProperty(final HashMap<String, PropertyDescriptor> map, final String name, final MethodDescriptor methodDescriptor, final boolean isSetter) { |
||||
MethodDescriptor setterMethod = isSetter ? methodDescriptor : null; |
||||
MethodDescriptor getterMethod = isSetter ? null : methodDescriptor; |
||||
|
||||
PropertyDescriptor existing = map.get(name); |
||||
|
||||
if (existing == null) { |
||||
// new property, just add it
|
||||
PropertyDescriptor propertyDescriptor = createPropertyDescriptor(name, getterMethod, setterMethod); |
||||
|
||||
map.put(name, propertyDescriptor); |
||||
return; |
||||
} |
||||
|
||||
// property exist
|
||||
|
||||
if (!isSetter) { |
||||
// use existing setter
|
||||
setterMethod = existing.getWriteMethodDescriptor(); |
||||
|
||||
// check existing
|
||||
MethodDescriptor existingMethodDescriptor = existing.getReadMethodDescriptor(); |
||||
if (existingMethodDescriptor != null) { |
||||
// check for special case of double get/is
|
||||
|
||||
// getter with the same name already exist
|
||||
String methodName = methodDescriptor.getMethod().getName(); |
||||
String existingMethodName = existingMethodDescriptor.getMethod().getName(); |
||||
|
||||
if ( |
||||
existingMethodName.startsWith(METHOD_IS_PREFIX) && |
||||
methodName.startsWith(METHOD_GET_PREFIX)) { |
||||
|
||||
// ignore getter when ister exist
|
||||
return; |
||||
} |
||||
} |
||||
} else { |
||||
// setter
|
||||
// use existing getter
|
||||
getterMethod = existing.getReadMethodDescriptor(); |
||||
|
||||
if (getterMethod != null) { |
||||
Class returnType = getterMethod.getMethod().getReturnType(); |
||||
|
||||
if (setterMethod != null) { |
||||
Class parameterType = setterMethod.getMethod().getParameterTypes()[0]; |
||||
|
||||
if (returnType != parameterType) { |
||||
// getter's type is different then setter's
|
||||
return; |
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
||||
|
||||
PropertyDescriptor propertyDescriptor = createPropertyDescriptor(name, getterMethod, setterMethod); |
||||
|
||||
map.put(name, propertyDescriptor); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link PropertyDescriptor}. Note that this method may be called |
||||
* up to three times (depends on use case) for the same property. Each time when |
||||
* a property is updated, a new definition is created with updated information. |
||||
*/ |
||||
protected PropertyDescriptor createPropertyDescriptor(final String name, final MethodDescriptor getterMethod, final MethodDescriptor setterMethod) { |
||||
return new PropertyDescriptor(classDescriptor, name, getterMethod, setterMethod); |
||||
} |
||||
|
||||
/** |
||||
* Creates new field-only {@link PropertyDescriptor}. It will be invoked only once. |
||||
*/ |
||||
protected PropertyDescriptor createPropertyDescriptor(final String name, final FieldDescriptor fieldDescriptor) { |
||||
return new PropertyDescriptor(classDescriptor, name, fieldDescriptor); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- get
|
||||
|
||||
/** |
||||
* Returns {@link PropertyDescriptor property descriptor}. |
||||
*/ |
||||
public PropertyDescriptor getPropertyDescriptor(final String name) { |
||||
return propertyDescriptors.get(name); |
||||
} |
||||
|
||||
/** |
||||
* Returns all property descriptors. |
||||
* Properties are sorted by name. |
||||
*/ |
||||
public PropertyDescriptor[] getAllPropertyDescriptors() { |
||||
if (allProperties == null) { |
||||
PropertyDescriptor[] allProperties = new PropertyDescriptor[propertyDescriptors.size()]; |
||||
|
||||
int index = 0; |
||||
for (PropertyDescriptor propertyDescriptor : propertyDescriptors.values()) { |
||||
allProperties[index] = propertyDescriptor; |
||||
index++; |
||||
} |
||||
|
||||
Arrays.sort(allProperties, new Comparator<PropertyDescriptor>() { |
||||
@Override |
||||
public int compare(final PropertyDescriptor pd1, final PropertyDescriptor pd2) { |
||||
return pd1.getName().compareTo(pd2.getName()); |
||||
} |
||||
}); |
||||
|
||||
this.allProperties = allProperties; |
||||
} |
||||
return allProperties; |
||||
} |
||||
|
||||
} |
@ -1,313 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
/** |
||||
* Property descriptor. It consist of read, write and field descriptor. |
||||
* Only one of those three descriptors may exist. |
||||
*/ |
||||
public class PropertyDescriptor extends Descriptor { |
||||
|
||||
protected final String name; |
||||
protected final MethodDescriptor readMethodDescriptor; |
||||
protected final MethodDescriptor writeMethodDescriptor; |
||||
protected final FieldDescriptor fieldDescriptor; |
||||
|
||||
/** |
||||
* Creates field-only property descriptor. |
||||
*/ |
||||
public PropertyDescriptor(final ClassDescriptor classDescriptor, final String propertyName, final FieldDescriptor fieldDescriptor) { |
||||
super(classDescriptor, false); |
||||
this.name = propertyName; |
||||
this.readMethodDescriptor = null; |
||||
this.writeMethodDescriptor = null; |
||||
this.fieldDescriptor = fieldDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Creates property descriptor. |
||||
*/ |
||||
public PropertyDescriptor(final ClassDescriptor classDescriptor, final String propertyName, final MethodDescriptor readMethod, final MethodDescriptor writeMethod) { |
||||
super(classDescriptor, |
||||
((readMethod == null) || readMethod.isPublic()) & (writeMethod == null || writeMethod.isPublic()) |
||||
); |
||||
this.name = propertyName; |
||||
this.readMethodDescriptor = readMethod; |
||||
this.writeMethodDescriptor = writeMethod; |
||||
|
||||
if (classDescriptor.isExtendedProperties()) { |
||||
String[] prefix = classDescriptor.getPropertyFieldPrefix(); |
||||
|
||||
FieldDescriptor fd = null; |
||||
|
||||
if (prefix != null) { |
||||
for (String p : prefix) { |
||||
fd = findField(p + propertyName); |
||||
|
||||
if (fd != null) { |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
else { |
||||
fd = findField(propertyName); |
||||
} |
||||
|
||||
this.fieldDescriptor = fd; |
||||
} else { |
||||
this.fieldDescriptor = null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Locates property field. Field is being searched also in all |
||||
* superclasses of current class. |
||||
*/ |
||||
protected FieldDescriptor findField(final String fieldName) { |
||||
FieldDescriptor fieldDescriptor = classDescriptor.getFieldDescriptor(fieldName, true); |
||||
|
||||
if (fieldDescriptor != null) { |
||||
return fieldDescriptor; |
||||
} |
||||
|
||||
// field descriptor not found in this class
|
||||
// try to locate it in the superclasses
|
||||
|
||||
Class[] superclasses = classDescriptor.getAllSuperclasses(); |
||||
|
||||
for (Class superclass : superclasses) { |
||||
|
||||
ClassDescriptor classDescriptor = ClassIntrospector.get().lookup(superclass); |
||||
|
||||
fieldDescriptor = classDescriptor.getFieldDescriptor(fieldName, true); |
||||
|
||||
if (fieldDescriptor != null) { |
||||
return fieldDescriptor; |
||||
} |
||||
} |
||||
|
||||
// nothing found
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns property name. |
||||
*/ |
||||
@Override |
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
/** |
||||
* Returns read method of this property. |
||||
* May be <code>null</code> if read method is not defined. |
||||
*/ |
||||
public MethodDescriptor getReadMethodDescriptor() { |
||||
return readMethodDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns write method of this property. |
||||
* May be <code>null</code> for read-only properties. |
||||
*/ |
||||
public MethodDescriptor getWriteMethodDescriptor() { |
||||
return writeMethodDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns the associated field of this property. |
||||
* May be <code>null</code> if properties are not enhanced by field description. |
||||
*/ |
||||
public FieldDescriptor getFieldDescriptor() { |
||||
return fieldDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if this is an extended property with |
||||
* only field definition and without getter and setter. |
||||
*/ |
||||
public boolean isFieldOnly() { |
||||
return (readMethodDescriptor == null) && (writeMethodDescriptor == null); |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if this property has only a getter method. |
||||
*/ |
||||
public boolean isGetterOnly() { |
||||
return (fieldDescriptor == null) && (writeMethodDescriptor == null); |
||||
} |
||||
|
||||
/** |
||||
* Returns <code>true</code> if this property has only a setter method. |
||||
*/ |
||||
public boolean isSetterOnly() { |
||||
return (fieldDescriptor == null) && (readMethodDescriptor == null); |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- type
|
||||
|
||||
protected Class type; |
||||
|
||||
/** |
||||
* Returns property type. Raw types are detected. |
||||
*/ |
||||
public Class getType() { |
||||
if (type == null) { |
||||
if (fieldDescriptor != null) { |
||||
type = fieldDescriptor.getRawType(); |
||||
} |
||||
else if (readMethodDescriptor != null) { |
||||
type = getGetter(true).getGetterRawType(); |
||||
//type = readMethodDescriptor.getGetterRawType();
|
||||
} |
||||
else if (writeMethodDescriptor != null) { |
||||
type = getSetter(true).getSetterRawType(); |
||||
//type = writeMethodDescriptor.getSetterRawType();
|
||||
} |
||||
} |
||||
|
||||
return type; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- getters & setters
|
||||
|
||||
protected Getter[] getters; |
||||
protected Setter[] setters; |
||||
|
||||
/** |
||||
* Returns {@link Getter}. May return <code>null</code> |
||||
* if no matched getter is found. |
||||
*/ |
||||
public Getter getGetter(final boolean declared) { |
||||
if (getters == null) { |
||||
getters = new Getter[] { |
||||
createGetter(false), |
||||
createGetter(true), |
||||
}; |
||||
} |
||||
|
||||
return getters[declared ? 1 : 0]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a {@link Getter}. |
||||
*/ |
||||
protected Getter createGetter(final boolean declared) { |
||||
if (readMethodDescriptor != null) { |
||||
if (readMethodDescriptor.matchDeclared(declared)) { |
||||
return Getter.of(readMethodDescriptor); |
||||
} |
||||
} |
||||
if (fieldDescriptor != null) { |
||||
if (fieldDescriptor.matchDeclared(declared)) { |
||||
return Getter.of(fieldDescriptor); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns {@link Setter}. May return <code>null</code> |
||||
* if no matched setter is found. |
||||
*/ |
||||
public Setter getSetter(final boolean declared) { |
||||
if (setters == null) { |
||||
setters = new Setter[] { |
||||
createSetter(false), |
||||
createSetter(true), |
||||
}; |
||||
} |
||||
|
||||
return setters[declared ? 1 : 0]; |
||||
} |
||||
|
||||
/** |
||||
* Creates a {@link Setter}. |
||||
*/ |
||||
protected Setter createSetter(final boolean declared) { |
||||
if (writeMethodDescriptor != null) { |
||||
if (writeMethodDescriptor.matchDeclared(declared)) { |
||||
return Setter.of(writeMethodDescriptor); |
||||
} |
||||
} |
||||
if (fieldDescriptor != null) { |
||||
if (fieldDescriptor.matchDeclared(declared)) { |
||||
return Setter.of(fieldDescriptor); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- resolvers
|
||||
|
||||
/** |
||||
* Resolves key type for given property descriptor. |
||||
*/ |
||||
public Class resolveKeyType(final boolean declared) { |
||||
Class keyType = null; |
||||
|
||||
Getter getter = getGetter(declared); |
||||
|
||||
if (getter != null) { |
||||
keyType = getter.getGetterRawKeyComponentType(); |
||||
} |
||||
|
||||
if (keyType == null) { |
||||
FieldDescriptor fieldDescriptor = getFieldDescriptor(); |
||||
|
||||
if (fieldDescriptor != null) { |
||||
keyType = fieldDescriptor.getRawKeyComponentType(); |
||||
} |
||||
} |
||||
|
||||
return keyType; |
||||
} |
||||
|
||||
/** |
||||
* Resolves component type for given property descriptor. |
||||
*/ |
||||
public Class resolveComponentType(final boolean declared) { |
||||
Class componentType = null; |
||||
|
||||
Getter getter = getGetter(declared); |
||||
|
||||
if (getter != null) { |
||||
componentType = getter.getGetterRawComponentType(); |
||||
} |
||||
|
||||
if (componentType == null) { |
||||
FieldDescriptor fieldDescriptor = getFieldDescriptor(); |
||||
|
||||
if (fieldDescriptor != null) { |
||||
componentType = fieldDescriptor.getRawComponentType(); |
||||
} |
||||
} |
||||
|
||||
return componentType; |
||||
} |
||||
|
||||
} |
@ -1,90 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.introspector; |
||||
|
||||
import java.lang.reflect.InvocationTargetException; |
||||
|
||||
/** |
||||
* Unified setter property interface for both methods and fields. |
||||
*/ |
||||
public interface Setter { |
||||
|
||||
static Setter of(final MethodDescriptor methodDescriptor) { |
||||
return new Setter() { |
||||
@Override |
||||
public void invokeSetter(final Object target, final Object argument) throws InvocationTargetException, IllegalAccessException { |
||||
methodDescriptor.method.invoke(target, argument); |
||||
} |
||||
|
||||
@Override |
||||
public Class getSetterRawType() { |
||||
return methodDescriptor.getParameters()[0].getRawType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getSetterRawComponentType() { |
||||
return methodDescriptor.getParameters()[0].getRawComponentType(); |
||||
} |
||||
|
||||
@Override |
||||
public MapperFunction getMapperFunction() { |
||||
return methodDescriptor.mapperFunction; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
static Setter of(final FieldDescriptor fieldDescriptor) { |
||||
return new Setter() { |
||||
@Override |
||||
public void invokeSetter(final Object target, final Object argument) throws IllegalAccessException { |
||||
fieldDescriptor.field.set(target, argument); |
||||
} |
||||
|
||||
@Override |
||||
public Class getSetterRawType() { |
||||
return fieldDescriptor.getRawType(); |
||||
} |
||||
|
||||
@Override |
||||
public Class getSetterRawComponentType() { |
||||
return fieldDescriptor.getRawComponentType(); |
||||
} |
||||
|
||||
@Override |
||||
public MapperFunction getMapperFunction() { |
||||
return fieldDescriptor.mapperFunction; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
void invokeSetter(Object target, Object argument) throws IllegalAccessException, InvocationTargetException; |
||||
|
||||
Class getSetterRawType(); |
||||
|
||||
Class getSetterRawComponentType(); |
||||
|
||||
MapperFunction getMapperFunction(); |
||||
} |
@ -1,29 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** |
||||
* Very fast reflection introspector. |
||||
*/ |
||||
package com.fr.third.jodd.introspector; |
@ -1,121 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import java.io.Closeable; |
||||
import java.io.Flushable; |
||||
import java.io.IOException; |
||||
import java.io.Writer; |
||||
import java.nio.CharBuffer; |
||||
|
||||
/** |
||||
* Appendable writer adapter. |
||||
*/ |
||||
public class AppendableWriter extends Writer { |
||||
|
||||
private final Appendable appendable; |
||||
private final boolean flushable; |
||||
private boolean closed; |
||||
|
||||
public AppendableWriter(final Appendable appendable) { |
||||
this.appendable = appendable; |
||||
this.flushable = appendable instanceof Flushable; |
||||
this.closed = false; |
||||
} |
||||
|
||||
@Override |
||||
public void write(final char[] cbuf, final int off, final int len) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(CharBuffer.wrap(cbuf), off, off + len); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final int c) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append((char) c); |
||||
} |
||||
|
||||
@Override |
||||
public Writer append(final char c) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(c); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public Writer append(final CharSequence csq, final int start, final int end) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(csq, start, end); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public Writer append(final CharSequence csq) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(csq); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public void write(final String str, final int off, final int len) throws IOException { |
||||
checkNotClosed(); |
||||
appendable.append(str, off, off + len); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final String str) throws IOException { |
||||
appendable.append(str); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final char[] cbuf) throws IOException { |
||||
appendable.append(CharBuffer.wrap(cbuf)); |
||||
} |
||||
|
||||
@Override |
||||
public void flush() throws IOException { |
||||
checkNotClosed(); |
||||
if (flushable) { |
||||
((Flushable) appendable).flush(); |
||||
} |
||||
} |
||||
|
||||
private void checkNotClosed() throws IOException { |
||||
if (closed) { |
||||
throw new IOException("Cannot write to closed writer " + this); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
if (!closed) { |
||||
flush(); |
||||
if (appendable instanceof Closeable) { |
||||
((Closeable) appendable).close(); |
||||
} |
||||
closed = true; |
||||
} |
||||
} |
||||
} |
@ -1,60 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import java.io.Reader; |
||||
import java.nio.CharBuffer; |
||||
|
||||
/** |
||||
* Reader that wraps a <code>CharBuffer</code>. |
||||
*/ |
||||
public class CharBufferReader extends Reader { |
||||
|
||||
private final CharBuffer charBuffer; |
||||
|
||||
public CharBufferReader(final CharBuffer charBuffer) { |
||||
// duplicate so to allow to move independently,
|
||||
// but share the same underlying data.
|
||||
this.charBuffer = charBuffer.duplicate(); |
||||
} |
||||
|
||||
@Override |
||||
public int read(final char[] chars, final int offset, final int length) { |
||||
int read = Math.min(charBuffer.remaining(), length); |
||||
charBuffer.get(chars, offset, read); |
||||
return read; |
||||
} |
||||
|
||||
@Override |
||||
public int read() { |
||||
return charBuffer.position() < charBuffer.limit() ? charBuffer.get() : -1; |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
} |
||||
|
||||
} |
@ -1,146 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import com.fr.third.jodd.util.StringUtil; |
||||
import com.fr.third.jodd.buffer.FastByteBuffer; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* This class implements an {@link OutputStream} in which the data is |
||||
* written into a byte array. The buffer automatically grows as data |
||||
* is written to it. |
||||
* <p> |
||||
* The data can be retrieved using {@link #toByteArray()} and {@link #toString}. |
||||
* <p> |
||||
* Closing a {@link FastByteArrayOutputStream} has no effect. The methods in |
||||
* this class can be called after the stream has been closed without |
||||
* generating an {@link IOException}. |
||||
* <p> |
||||
* This is an alternative implementation of the {@code java.io.FastByteArrayOutputStream} |
||||
* class. The original implementation only allocates 32 bytes at the beginning. |
||||
* As this class is designed for heavy duty it starts at 1024 bytes. In contrast |
||||
* to the original it doesn't reallocate the whole memory block but allocates |
||||
* additional buffers. This way no buffers need to be garbage collected and |
||||
* the contents don't have to be copied to the new buffer. This class is |
||||
* designed to behave exactly like the original. The only exception is the |
||||
* deprecated {@code java.io.FastByteArrayOutputStream#toString(int)} method that has been ignored. |
||||
*/ |
||||
public class FastByteArrayOutputStream extends OutputStream { |
||||
|
||||
private final FastByteBuffer buffer; |
||||
|
||||
/** |
||||
* Creates a new byte array {@link OutputStream}. The buffer capacity is |
||||
* initially 1024 bytes, though its size increases if necessary. |
||||
*/ |
||||
public FastByteArrayOutputStream() { |
||||
this(1024); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new byte array output stream, with a buffer capacity of |
||||
* the specified size, in bytes. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastByteArrayOutputStream(final int size) { |
||||
buffer = new FastByteBuffer(size); |
||||
} |
||||
|
||||
/** |
||||
* @see OutputStream#write(byte[], int, int) |
||||
*/ |
||||
@Override |
||||
public void write(final byte[] b, final int off, final int len) { |
||||
buffer.append(b, off, len); |
||||
} |
||||
|
||||
/** |
||||
* Writes single byte. |
||||
*/ |
||||
@Override |
||||
public void write(final int b) { |
||||
buffer.append((byte) b); |
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#size() |
||||
*/ |
||||
public int size() { |
||||
return buffer.size(); |
||||
} |
||||
|
||||
/** |
||||
* Closing a {@link FastByteArrayOutputStream} has no effect. The methods in |
||||
* this class can be called after the stream has been closed without |
||||
* generating an {@link IOException}. |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
//nop
|
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#reset() |
||||
*/ |
||||
public void reset() { |
||||
buffer.clear(); |
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#writeTo(OutputStream) |
||||
*/ |
||||
public void writeTo(final OutputStream out) throws IOException { |
||||
out.write(buffer.toArray()); |
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#toByteArray() |
||||
*/ |
||||
public byte[] toByteArray() { |
||||
return buffer.toArray(); |
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#toString() |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new String(toByteArray()); |
||||
} |
||||
|
||||
/** |
||||
* @see ByteArrayOutputStream#toString(String) |
||||
*/ |
||||
public String toString(final String enc) { |
||||
return StringUtil.newString(toByteArray(), enc); |
||||
} |
||||
} |
@ -1,134 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import com.fr.third.jodd.buffer.FastCharBuffer; |
||||
|
||||
import java.io.CharArrayWriter; |
||||
import java.io.IOException; |
||||
import java.io.Writer; |
||||
|
||||
/** |
||||
* Similar to {@link FastByteArrayOutputStream} but for {@link Writer}. |
||||
*/ |
||||
public class FastCharArrayWriter extends Writer { |
||||
|
||||
private final FastCharBuffer buffer; |
||||
|
||||
/** |
||||
* Creates a new writer. The buffer capacity is |
||||
* initially 1024 bytes, though its size increases if necessary. |
||||
*/ |
||||
public FastCharArrayWriter() { |
||||
this(1024); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new char array {@link Writer}, with a buffer capacity of |
||||
* the specified size, in bytes. |
||||
* |
||||
* @param size the initial size. |
||||
* @throws IllegalArgumentException if size is negative. |
||||
*/ |
||||
public FastCharArrayWriter(final int size) { |
||||
buffer = new FastCharBuffer(size); |
||||
} |
||||
|
||||
/** |
||||
* @see Writer#write(char[], int, int) |
||||
*/ |
||||
@Override |
||||
public void write(final char[] b, final int off, final int len) { |
||||
buffer.append(b, off, len); |
||||
} |
||||
|
||||
/** |
||||
* Writes single byte. |
||||
*/ |
||||
@Override |
||||
public void write(final int b) { |
||||
buffer.append((char) b); |
||||
} |
||||
|
||||
@Override |
||||
public void write(final String s, final int off, final int len) { |
||||
write(s.toCharArray(), off, len); |
||||
} |
||||
|
||||
/** |
||||
* @see CharArrayWriter#size() |
||||
*/ |
||||
public int size() { |
||||
return buffer.size(); |
||||
} |
||||
|
||||
/** |
||||
* Closing a {@link FastCharArrayWriter} has no effect. The methods in |
||||
* this class can be called after the stream has been closed without |
||||
* generating an {@link IOException}. |
||||
*/ |
||||
@Override |
||||
public void close() { |
||||
//nop
|
||||
} |
||||
|
||||
/** |
||||
* Flushing a {@link FastCharArrayWriter} has no effects. |
||||
*/ |
||||
@Override |
||||
public void flush() { |
||||
//nop
|
||||
} |
||||
|
||||
/** |
||||
* @see CharArrayWriter#reset() |
||||
*/ |
||||
public void reset() { |
||||
buffer.clear(); |
||||
} |
||||
|
||||
/** |
||||
* @see CharArrayWriter#writeTo(Writer) |
||||
*/ |
||||
public void writeTo(final Writer out) throws IOException { |
||||
out.write(buffer.toArray()); |
||||
} |
||||
|
||||
/** |
||||
* @see CharArrayWriter#toCharArray() |
||||
*/ |
||||
public char[] toCharArray() { |
||||
return buffer.toArray(); |
||||
} |
||||
|
||||
/** |
||||
* @see CharArrayWriter#toString() |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new String(toCharArray()); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,194 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import com.fr.third.jodd.util.StringUtil; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.Inet4Address; |
||||
import java.net.InetAddress; |
||||
import java.net.URL; |
||||
import java.net.UnknownHostException; |
||||
import java.nio.channels.Channels; |
||||
import java.nio.channels.FileChannel; |
||||
import java.nio.channels.ReadableByteChannel; |
||||
import java.nio.file.StandardOpenOption; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
|
||||
/** |
||||
* Network utilities. |
||||
*/ |
||||
public class NetUtil { |
||||
|
||||
public static final String LOCAL_HOST = "localhost"; |
||||
public static final String LOCAL_IP = "127.0.0.1"; |
||||
public static final String DEFAULT_MASK = "255.255.255.0"; |
||||
public static final int INT_VALUE_127_0_0_1 = 0x7f000001; |
||||
|
||||
/** |
||||
* Resolves IP address from a hostname. |
||||
*/ |
||||
public static String resolveIpAddress(final String hostname) { |
||||
try { |
||||
InetAddress netAddress; |
||||
|
||||
if (hostname == null || hostname.equalsIgnoreCase(LOCAL_HOST)) { |
||||
netAddress = InetAddress.getLocalHost(); |
||||
} else { |
||||
netAddress = Inet4Address.getByName(hostname); |
||||
} |
||||
return netAddress.getHostAddress(); |
||||
} catch (UnknownHostException ignore) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns IP address as integer. |
||||
*/ |
||||
public static int getIpAsInt(final String ipAddress) { |
||||
int ipIntValue = 0; |
||||
String[] tokens = StringUtil.splitc(ipAddress, '.'); |
||||
for (String token : tokens) { |
||||
if (ipIntValue > 0) { |
||||
ipIntValue <<= 8; |
||||
} |
||||
ipIntValue += Integer.parseInt(token); |
||||
} |
||||
return ipIntValue; |
||||
} |
||||
|
||||
public static int getMaskAsInt(String mask) { |
||||
if (!validateIPv4(mask)) { |
||||
mask = DEFAULT_MASK; |
||||
} |
||||
return getIpAsInt(mask); |
||||
} |
||||
|
||||
public static boolean isSocketAccessAllowed(final int localIp, final int socketIp, final int mask) { |
||||
boolean _retVal = false; |
||||
|
||||
if (socketIp == INT_VALUE_127_0_0_1 || (localIp & mask) == (socketIp & mask)) { |
||||
_retVal = true; |
||||
} |
||||
return _retVal; |
||||
} |
||||
|
||||
private static final Pattern ip4RegExp = Pattern.compile("^((?:1?[1-9]?\\d|2(?:[0-4]\\d|5[0-5]))\\.){4}$"); |
||||
|
||||
/** |
||||
* Checks given string against IP address v4 format. |
||||
* |
||||
* @param input an ip address - may be null |
||||
* @return <tt>true</tt> if param has a valid ip v4 format <tt>false</tt> otherwise |
||||
* @see <a href="https://en.wikipedia.org/wiki/IP_address#IPv4_addresses">ip address v4</a> |
||||
*/ |
||||
public static boolean validateIPv4(final String input) { |
||||
Matcher m = ip4RegExp.matcher(input + '.'); |
||||
return m.matches(); |
||||
} |
||||
|
||||
/** |
||||
* Resolves host name from IP address bytes. |
||||
*/ |
||||
public static String resolveHostName(final byte[] ip) { |
||||
try { |
||||
InetAddress address = InetAddress.getByAddress(ip); |
||||
return address.getHostName(); |
||||
} catch (UnknownHostException ignore) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
// ---------------------------------------------------------------- download
|
||||
|
||||
/** |
||||
* Downloads resource as byte array. |
||||
*/ |
||||
public static byte[] downloadBytes(final String url) throws IOException { |
||||
try (InputStream inputStream = new URL(url).openStream()) { |
||||
return StreamUtil.readBytes(inputStream); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Downloads resource as String. |
||||
*/ |
||||
public static String downloadString(final String url, final String encoding) throws IOException { |
||||
try (InputStream inputStream = new URL(url).openStream()) { |
||||
return new String(StreamUtil.readChars(inputStream, encoding)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Downloads resource as String. |
||||
*/ |
||||
public static String downloadString(final String url) throws IOException { |
||||
try (InputStream inputStream = new URL(url).openStream()) { |
||||
return new String(StreamUtil.readChars(inputStream)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Downloads resource to a file, potentially very efficiently. |
||||
*/ |
||||
public static void downloadFile(final String url, final File file) throws IOException { |
||||
try ( |
||||
InputStream inputStream = new URL(url).openStream(); |
||||
ReadableByteChannel rbc = Channels.newChannel(inputStream); |
||||
FileChannel fileChannel = FileChannel.open( |
||||
file.toPath(), |
||||
StandardOpenOption.CREATE, |
||||
StandardOpenOption.TRUNCATE_EXISTING, |
||||
StandardOpenOption.WRITE) |
||||
) { |
||||
fileChannel.transferFrom(rbc, 0, Long.MAX_VALUE); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get remote file size. Returns -1 if the content length is unknown |
||||
* |
||||
* @param url remote file url |
||||
* @return file size |
||||
* @throws IOException JDK-IOException |
||||
*/ |
||||
public static long getRemoteFileSize(String url) throws IOException { |
||||
HttpURLConnection connection = null; |
||||
try { |
||||
connection = (HttpURLConnection) new URL(url).openConnection(); |
||||
return connection.getContentLengthLong(); |
||||
} finally { |
||||
if (connection != null) { |
||||
connection.disconnect(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,92 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import com.fr.third.jodd.util.StringUtil; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.io.StringWriter; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.nio.file.FileVisitResult; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Path; |
||||
import java.nio.file.SimpleFileVisitor; |
||||
import java.nio.file.attribute.BasicFileAttributes; |
||||
|
||||
public class PathUtil { |
||||
|
||||
/** |
||||
* Resolves subpath in safer way. For some reason, if child starts with |
||||
* a separator it gets resolved as a full path, ignoring the base. |
||||
* This method acts different. |
||||
*/ |
||||
public static Path resolve(final Path base, String child) { |
||||
if (StringUtil.startsWithChar(child, File.separatorChar)) { |
||||
child = child.substring(1); |
||||
} |
||||
return base.resolve(child); |
||||
} |
||||
|
||||
public static Path resolve(Path path, final String... childs) { |
||||
for (String child : childs) { |
||||
path = resolve(path, child); |
||||
} |
||||
return path; |
||||
} |
||||
|
||||
/** |
||||
* Reads path content. |
||||
*/ |
||||
public static String readString(final Path path) throws IOException { |
||||
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { |
||||
StringWriter writer = new StringWriter(); // flush & close not needed for StringWriter-instance
|
||||
StreamUtil.copy(reader, writer); |
||||
return writer.toString(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Deletes a directory recursively. |
||||
*/ |
||||
public static void deleteFileTree(final Path directory) throws IOException { |
||||
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() { |
||||
@Override |
||||
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { |
||||
Files.delete(file); |
||||
return FileVisitResult.CONTINUE; |
||||
} |
||||
|
||||
@Override |
||||
public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { |
||||
Files.delete(dir); |
||||
return FileVisitResult.CONTINUE; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
@ -1,125 +0,0 @@
|
||||
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.fr.third.jodd.io; |
||||
|
||||
import com.fr.third.jodd.util.StringPool; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.io.OutputStream; |
||||
import java.io.PrintStream; |
||||
|
||||
/** |
||||
* Consumes a stream. |
||||
* For any <code>Process</code>, the input and error streams must read even |
||||
* if the data written to these streams is not used by the application. |
||||
* The generally accepted solution for this problem is a stream gobbler thread |
||||
* that does nothing but consume data from an input stream until stopped. |
||||
*/ |
||||
public class StreamGobbler extends Thread { |
||||
|
||||
protected final InputStream is; |
||||
protected final String prefix; |
||||
protected final OutputStream out; |
||||
protected final Object lock = new Object(); |
||||
protected boolean end = false; |
||||
|
||||
public StreamGobbler(final InputStream is) { |
||||
this(is, null, null); |
||||
} |
||||
|
||||
public StreamGobbler(final InputStream is, final OutputStream output) { |
||||
this(is, output, null); |
||||
} |
||||
|
||||
public StreamGobbler(final InputStream is, final OutputStream output, final String prefix) { |
||||
this.is = is; |
||||
this.prefix = prefix; |
||||
this.out = output; |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
InputStreamReader isr = new InputStreamReader(is); |
||||
BufferedReader br = new BufferedReader(isr); |
||||
|
||||
try { |
||||
String line; |
||||
while ((line = br.readLine()) != null) { |
||||
if (out != null) { |
||||
if (prefix != null) { |
||||
out.write(prefix.getBytes()); |
||||
} |
||||
out.write(line.getBytes()); |
||||
out.write(StringPool.BYTES_NEW_LINE); |
||||
} |
||||
} |
||||
} |
||||
catch (IOException ioe) { |
||||
if (out != null) { |
||||
ioe.printStackTrace(new PrintStream(out)); |
||||
} |
||||
} |
||||
finally { |
||||
if (out != null) { |
||||
try { |
||||
out.flush(); |
||||
} |
||||
catch (IOException ignore) { |
||||
} |
||||
} |
||||
try { |
||||
br.close(); |
||||
} |
||||
catch (IOException ignore) { |
||||
} |
||||
} |
||||
|
||||
synchronized (lock) { |
||||
lock.notifyAll(); |
||||
end = true; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Waits for gobbler to end. |
||||
*/ |
||||
public void waitFor() { |
||||
try { |
||||
synchronized (lock) { |
||||
if (!end) { |
||||
lock.wait(); |
||||
} |
||||
} |
||||
} |
||||
catch (InterruptedException ignore) { |
||||
Thread.currentThread().interrupt(); |
||||
} |
||||
} |
||||
|
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue