diff --git a/core/src/main/java/org/demoiselle/jee/core/annotation/Ignore.java b/core/src/main/java/org/demoiselle/jee/core/annotation/Ignore.java new file mode 100644 index 0000000..4c793da --- /dev/null +++ b/core/src/main/java/org/demoiselle/jee/core/annotation/Ignore.java @@ -0,0 +1,56 @@ +/* + * Demoiselle Framework + * Copyright (C) 2010 SERPRO + * ---------------------------------------------------------------------------- + * This file is part of Demoiselle Framework. + * + * Demoiselle Framework is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License version 3 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this program; if not, see + * or write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301, USA. + * ---------------------------------------------------------------------------- + * Este arquivo é parte do Framework Demoiselle. + * + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação + * do Software Livre (FSF). + * + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português + * para maiores detalhes. + * + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título + * "LICENCA.txt", junto com esse programa. Se não, acesse + * ou escreva para a Fundação do Software Livre (FSF) Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. + */ +package org.demoiselle.jee.core.annotation; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + *

Used in fields of classes annotated with {@link org.demoiselle.configuration.Configuration} + * to indicate that the system should ignore this field when population the new configuration + * instance with values extracted from the source file.

+ * + * @see org.demoiselle.configuration.Configuration + * @author SERPRO + */ +@Target(FIELD) +@Retention(RUNTIME) +public @interface Ignore { +} diff --git a/core/src/main/java/org/demoiselle/jee/core/annotation/Name.java b/core/src/main/java/org/demoiselle/jee/core/annotation/Name.java new file mode 100644 index 0000000..8e93aaa --- /dev/null +++ b/core/src/main/java/org/demoiselle/jee/core/annotation/Name.java @@ -0,0 +1,98 @@ +/* + * Demoiselle Framework + * Copyright (C) 2010 SERPRO + * ---------------------------------------------------------------------------- + * This file is part of Demoiselle Framework. + * + * Demoiselle Framework is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License version 3 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this program; if not, see + * or write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301, USA. + * ---------------------------------------------------------------------------- + * Este arquivo é parte do Framework Demoiselle. + * + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação + * do Software Livre (FSF). + * + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português + * para maiores detalhes. + * + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título + * "LICENCA.txt", junto com esse programa. Se não, acesse + * ou escreva para a Fundação do Software Livre (FSF) Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. + */ +package org.demoiselle.jee.core.annotation; + +import javax.enterprise.inject.spi.InjectionPoint; +import javax.enterprise.util.Nonbinding; +import javax.inject.Named; +import javax.inject.Qualifier; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + *

+ * String based non-binding qualifier. + *

+ * + *

+ * This annotation is used to qualify beans using an user defined String. {@link javax.enterprise.inject.Produces} + * methods can then read this string and use it to customize the bean creation process. + *

+ * + *

+ * The {@link #value()} attribute is non-binding (contrary to {@link Named#value()}, meaning multiple classes + * qualified with this annotation, even with different values, will be considered the same candidate for + * injection points. To avoid ambiguous resolutions and select which candidate to choose usually you'll need a + * producer method to read the string and select the best fitted candidate. + *

+ * + *

+ * The framework classes qualified with this annotation already have such producers and the accepted values for + * this annotation will be detailed in their respective documentations. + *

+ * + * + * @author SERPRO + * + * @see org.demoiselle.util.ResourceBundle + * @see org.demoiselle.internal.producer.ResourceBundleProducer#create(InjectionPoint) + * @see org.demoiselle.internal.producer.LoggerProducer#createNamed(InjectionPoint) + */ +@Qualifier +@Inherited +@Retention(RUNTIME) +@Target({ TYPE, FIELD, METHOD, PARAMETER }) +public @interface Name { + + /** + *

+ * Specifies a name to access a custom configuration that will change how the annotated bean works. + *

+ *

+ * This attribute is nonbinding so you can use the {@link Name} annotation to create {@linkplain javax.enterprise.inject.Produces} + * methods or fields and have only one producer that works with all injection points no matter the value of this attribute. + *

+ * @return Name of custom settings to personalize how the annotated bean works. + */ + @Nonbinding + String value() default ""; + +} diff --git a/core/src/main/java/org/demoiselle/jee/core/annotation/Priority.java b/core/src/main/java/org/demoiselle/jee/core/annotation/Priority.java new file mode 100644 index 0000000..e1d04ac --- /dev/null +++ b/core/src/main/java/org/demoiselle/jee/core/annotation/Priority.java @@ -0,0 +1,96 @@ +/* + * Demoiselle Framework + * Copyright (C) 2010 SERPRO + * ---------------------------------------------------------------------------- + * This file is part of Demoiselle Framework. + * + * Demoiselle Framework is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License version 3 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this program; if not, see + * or write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301, USA. + * ---------------------------------------------------------------------------- + * Este arquivo é parte do Framework Demoiselle. + * + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação + * do Software Livre (FSF). + * + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português + * para maiores detalhes. + * + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título + * "LICENCA.txt", junto com esse programa. Se não, acesse + * ou escreva para a Fundação do Software Livre (FSF) Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. + */ +package org.demoiselle.jee.core.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + *

+ * Used to prioritize some execution flow, as methods annotated with @startup or @shutdown, + * or some interface implementation. + *

+ * + * @author SERPRO + */ +@Target({ TYPE, METHOD }) +@Retention(RUNTIME) +public @interface Priority { + + /** + * Most important priority value. + */ + static int MAX_PRIORITY = Integer.MIN_VALUE; + + /** + * Less important priority value. + */ + static int MIN_PRIORITY = Integer.MAX_VALUE; + + /** + * Less important priority value. + */ + static int L1_PRIORITY = MIN_PRIORITY; + + /** + * Higher priority than L1_PRIORITY + */ + static int L2_PRIORITY = L1_PRIORITY - 100; + + /** + * Higher priority than L2_PRIORITY + */ + static int L3_PRIORITY = L2_PRIORITY - 100; + + /** + * Higher priority than L3_PRIORITY + */ + static int L4_PRIORITY = L3_PRIORITY - 100; + + /** + *

+ * An integer value defines the priority order. The lower the value, the greater priority. + *

+ * + * @return Priority value, lower values have higher priority. + */ + int value(); +} diff --git a/core/src/main/java/org/demoiselle/jee/core/annotation/Strategy.java b/core/src/main/java/org/demoiselle/jee/core/annotation/Strategy.java new file mode 100644 index 0000000..335692f --- /dev/null +++ b/core/src/main/java/org/demoiselle/jee/core/annotation/Strategy.java @@ -0,0 +1,83 @@ +/* + * Demoiselle Framework + * Copyright (C) 2010 SERPRO + * ---------------------------------------------------------------------------- + * This file is part of Demoiselle Framework. + * + * Demoiselle Framework is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License version 3 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this program; if not, see + * or write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301, USA. + * ---------------------------------------------------------------------------- + * Este arquivo é parte do Framework Demoiselle. + * + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação + * do Software Livre (FSF). + * + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português + * para maiores detalhes. + * + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título + * "LICENCA.txt", junto com esse programa. Se não, acesse + * ou escreva para a Fundação do Software Livre (FSF) Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. + */ +package org.demoiselle.jee.core.annotation; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +/** + * + *

+ * This literal marks a bean to be selected at runtime based on a priority system. + * The user qualifies the injection point with this literal and then at runtime + * the CDI engine will circle through all candidate subtypes to be injected + * that are annotated with {@link Priority}. If there is only one subtype with the + * highest priority then this one will be selected to be injected. + *

+ * + *

+ * This allows users to plug in libraries with new candidates and have them be selected + * if their priority values are higher than the default values already present. One example + * is the {@link org.demoiselle.security.Authorizer} type, the framework has a {@link org.demoiselle.internal.implementation.DefaultAuthorizer} + * with {@link Priority#L1_PRIORITY the lowest priority} but the user can add libraries with new + * implementations of {@link org.demoiselle.security.Authorizer} annotated with higher priorities, the code will + * then automatically select these new implementations with no extra configuration. + *

+ * + *

+ * This annotation must be used with supported types. Usually this involves creating {@link javax.enterprise.inject.Produces} CDI + * producer methods that will select the correct strategy. To create your own producer + * methods that support strategy selection, use the utility {@linkplain org.demoiselle.internal.producer.StrategySelector}. + *

+ * + * @author SERPRO + */ +@Qualifier +@Inherited +@Retention(RUNTIME) +@Target({ TYPE, FIELD, METHOD, PARAMETER }) +public @interface Strategy { + +} diff --git a/core/src/main/java/org/demoiselle/jee/core/internal/producer/ResourceBundleProducer.java b/core/src/main/java/org/demoiselle/jee/core/internal/producer/ResourceBundleProducer.java new file mode 100644 index 0000000..8176701 --- /dev/null +++ b/core/src/main/java/org/demoiselle/jee/core/internal/producer/ResourceBundleProducer.java @@ -0,0 +1,72 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.demoiselle.jee.core.internal.producer; + +import java.io.Serializable; +import java.util.Locale; +import org.demoiselle.jee.core.util.ResourceBundle; +import javax.enterprise.context.Dependent; +import javax.enterprise.inject.Default; +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.CDI; +import javax.enterprise.inject.spi.InjectionPoint; +import org.demoiselle.jee.core.annotation.Name; +import org.demoiselle.util.CDIUtils; + +/** + * + * @author 70744416353 + */ +@Dependent +public class ResourceBundleProducer implements Serializable { + + private static final long serialVersionUID = 1L; + + @Default + @Produces + public ResourceBundle createDefault() { + return create((String) null); + } + + /* + * Produces a {@link java.util.ResourceBundle} instance loading the properties file whose name + * is defined by the {@link Name} literal. If no value is specified + * then the default "messages.properties" file is loaded. + */ + @Name + @Produces + public ResourceBundle create(InjectionPoint ip) { + String baseName = null; + if (ip != null && ip.getQualifiers() != null) { + Name nameQualifier = CDIUtils.getQualifier(Name.class, ip); + if (nameQualifier != null) { + baseName = nameQualifier.value(); + if ("".equals(baseName)) { + baseName = null; + } + } + } + + return create(baseName); + } + + public static ResourceBundle create(String baseName) { + ResourceBundle bundle; + + try { + bundle = baseName != null + ? new ResourceBundle(baseName, CDI.current().select(Locale.class).get()) { + } + : new ResourceBundle("messages", CDI.current().select(Locale.class).get()); + } catch (RuntimeException e) { + bundle = baseName != null + ? new ResourceBundle(baseName, Locale.getDefault()) + : new ResourceBundle("messages", Locale.getDefault()); + } + + return bundle; + } +} diff --git a/core/src/main/java/org/demoiselle/jee/core/util/CDIUtils.java b/core/src/main/java/org/demoiselle/jee/core/util/CDIUtils.java new file mode 100644 index 0000000..83737ba --- /dev/null +++ b/core/src/main/java/org/demoiselle/jee/core/util/CDIUtils.java @@ -0,0 +1,121 @@ +package org.demoiselle.util; + +import javax.enterprise.inject.spi.InjectionPoint; +import java.lang.annotation.Annotation; +import java.util.Arrays; +import java.util.Collection; + +/** + * Utility class to peform useful operations on CDI discovered beans. + * + * @author SERPRO + */ +public final class CDIUtils { + + private static final Annotation[] annotationArrayType = new Annotation[0]; + + /** + * Returns true if one annotation of the provided type is present + * on a list of annotations. + * + * @param annotationType Annotation type being looked for. + * @param allAnnotations List of all annotations where to look for. + * @return true if the annotation is present on the list + */ + @SuppressWarnings("WeakerAccess") + public static boolean hasAnnotation(Class annotationType, Annotation... allAnnotations) { + for (Annotation currentAnnotation : allAnnotations) { + if (currentAnnotation.annotationType().isAssignableFrom(annotationType)) { + return true; + } + } + + return false; + } + + /** + * @param annotationType Type of the annotation being checked + * @param allAnnotations List of annotations to check for the specific one + * @see #hasAnnotation(Class, Annotation...) + * @return true if the annotation is present on the list + */ + @SuppressWarnings("WeakerAccess") + public static boolean hasAnnotation(Class annotationType, + Collection allAnnotations) { + return hasAnnotation(annotationType, allAnnotations.toArray(annotationArrayType)); + } + + /** + * Returns true if a base class is annotated with the provided annotation. + * + * @param annotationType Annotation type to look for + * @param baseType Class to check for the informed annotation + * @see #hasAnnotation(Class, Annotation...) + * @return true if the annotation is present on the list + */ + @SuppressWarnings("WeakerAccess") + public static boolean hasAnnotation(Class annotationType, Class baseType) { + return hasAnnotation(annotationType, baseType.getAnnotations()); + } + + /** + * Returns the annotation instance that matches the annotation type provided, + * or null if no annotation of that type is present. + * + * @param annotationType Annotation type being looked for. + * @param allAnnotations List of all annotations where to look for. + * @param Type of the specific annotation returned + * @return The annotation instance found, or null if there is no such annotation present. + */ + @SuppressWarnings({ "WeakerAccess", "unchecked" }) + public static T getAnnotation(Class annotationType, Annotation... allAnnotations) { + for (Annotation currentAnnotation : allAnnotations) { + if (currentAnnotation.annotationType().isAssignableFrom(annotationType)) { + return (T) currentAnnotation; + } + } + + return null; + } + + /** + * @param annotationType Annotation type being looked for. + * @param allAnnotations List of all annotations where to look for. + * @param Type of the specific annotation returned + * @see #getAnnotation(Class, Annotation...) + * @return The annotation instance found, or null if there is no such annotation present. + */ + @SuppressWarnings({ "WeakerAccess" }) + public static T getAnnotation(Class annotationType, + Collection allAnnotations) { + return getAnnotation(annotationType, allAnnotations.toArray(annotationArrayType)); + } + + /** + * Returns true if one qualifier of the provided type is present + * on an injection point. + * + * @param qualifierAnnotationType Annotation type being looked for. + * @param ip Injection point of a bean type. + * @return true if the annotation is present on the list + */ + @SuppressWarnings("WeakerAccess") + public static boolean hasQualifier(Class qualifierAnnotationType, InjectionPoint ip) { + return hasAnnotation(qualifierAnnotationType, ip.getQualifiers()); + } + + /** + * Returns the annotation instance that matches the annotation type provided, + * or null if no annotation of that type is present. + * + * @param qualifierAnnotationType Annotation type being looked for. + * @param ip Injection point of a bean type. + * @param Type of the specific annotation returned + * @return The annotation instance found, or null if there is no such annotation present. + */ + @SuppressWarnings("WeakerAccess") + public static T getQualifier(Class qualifierAnnotationType, InjectionPoint ip) { + return getAnnotation(qualifierAnnotationType, ip.getQualifiers()); + } + +} diff --git a/core/src/main/java/org/demoiselle/jee/core/util/Exceptions.java b/core/src/main/java/org/demoiselle/jee/core/util/Exceptions.java new file mode 100644 index 0000000..5a8d499 --- /dev/null +++ b/core/src/main/java/org/demoiselle/jee/core/util/Exceptions.java @@ -0,0 +1,67 @@ +/* + * Demoiselle Framework + * Copyright (C) 2010 SERPRO + * ---------------------------------------------------------------------------- + * This file is part of Demoiselle Framework. + * + * Demoiselle Framework is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License version 3 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this program; if not, see + * or write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301, USA. + * ---------------------------------------------------------------------------- + * Este arquivo é parte do Framework Demoiselle. + * + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação + * do Software Livre (FSF). + * + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português + * para maiores detalhes. + * + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título + * "LICENCA.txt", junto com esse programa. Se não, acesse + * ou escreva para a Fundação do Software Livre (FSF) Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. + */ +package org.demoiselle.util; + +/** + *Class that offer tow methods that can help with manipulation of throwable exceptions. + * + * @author SERPRO + */ +public final class Exceptions { + + /** + * Constructor without parameters. + */ + private Exceptions() { + } + + /** + * Receives as parameter any kind of Throwable objects, and throws a RuntimeException instead. + * + * @param throwable + * a throwable object. + * + * @throws RuntimeException throws this kind of exception every time that is called. + */ + public static void handleToRuntimeException(final Throwable throwable) throws RuntimeException { + if (throwable instanceof RuntimeException) { + throw (RuntimeException) throwable; + } else { + throw new RuntimeException(throwable); + } + } +} diff --git a/core/src/main/java/org/demoiselle/jee/core/util/Reflections.java b/core/src/main/java/org/demoiselle/jee/core/util/Reflections.java new file mode 100644 index 0000000..3c73793 --- /dev/null +++ b/core/src/main/java/org/demoiselle/jee/core/util/Reflections.java @@ -0,0 +1,367 @@ +/* + * Demoiselle Framework + * Copyright (C) 2010 SERPRO + * ---------------------------------------------------------------------------- + * This file is part of Demoiselle Framework. + * + * Demoiselle Framework is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License version 3 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this program; if not, see + * or write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301, USA. + * ---------------------------------------------------------------------------- + * Este arquivo é parte do Framework Demoiselle. + * + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação + * do Software Livre (FSF). + * + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português + * para maiores detalhes. + * + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título + * "LICENCA.txt", junto com esse programa. Se não, acesse + * ou escreva para a Fundação do Software Livre (FSF) Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. + */ +package org.demoiselle.util; + +import java.io.InputStream; +import java.lang.reflect.*; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Provides some features to do some operations relating to java reflection. + * + * @author SERPRO + */ +public class Reflections { + + protected Reflections() { + // Impede instanciar subclasses desse tipo. + throw new UnsupportedOperationException(); + } + + /** + * Return the parametized type used with a concrete implementation of a class that accepts generics. Ex: If you + * declare + *
+	 * public class SpecializedCollection implements Collection<SpecializedType> {
+	 *   // ...
+	 * }
+	 * 
+ * then the code getGenericTypeArgument(SpecializedCollection.class , 0); will return the type + * SpecializedType. + * + * @param type Base type to check for generic arguments + * @param idx zero based index of the generic argument to get + * @param Type of the generic argument + * @return The class representing the type of the generic argument + */ + @SuppressWarnings("unchecked") + public static Class getGenericTypeArgument(final Type type, final int idx) { + ParameterizedType paramType; + try { + paramType = (ParameterizedType) type; + } catch (ClassCastException cause) { + return getGenericTypeArgument((Class) type, idx); + } + + return (Class) paramType.getActualTypeArguments()[idx]; + } + + /** + * Return the parametized type used with a concrete implementation of a class that accepts generics. Ex: If you + * declare + *
+	 * 
+	 * public class SpecializedCollection implements Collection<SpecializedType> {
+	 *   // ...
+	 * }
+	 * 
+	 * 
+ * then the code getGenericTypeArgument(SpecializedCollection.class , 0); will return the type + * SpecializedType. + * + * @param clazz Base type to check for generic arguments + * @param idx zero based index of the generic argument to get + * @param Type of the generic argument + * @return The class representing the type of the generic argument + */ + @SuppressWarnings("unchecked") + public static Class getGenericTypeArgument(final Class clazz, final int idx) { + final Type type = clazz.getGenericSuperclass(); + + ParameterizedType paramType; + try { + paramType = (ParameterizedType) type; + } catch (ClassCastException cause) { + return getGenericTypeArgument((Class) type, idx); + } + + return (Class) paramType.getActualTypeArguments()[idx]; + } + + /** + *

+ * Return the parametized type passed to field types that accepts Generics. + *

+ * Ex: If you declare + *
+	 * 
+	 * public class MyClass{
+	 *    private Collection<String> myStringCollection;
+	 * }
+	 * 
+	 * 
+ * then the code getGenericTypeArgument( MyClass.class.getDeclaredField("myStringCollection") , 0); + * will return the type String. + * + * @param field Field which type is generified + * @param idx zero based index of the generic argument to get + * @param Type of the generic argument + * @return The class representing the type of the generic argument + */ + @SuppressWarnings("unchecked") + public static Class getGenericTypeArgument(final Field field, final int idx) { + final Type type = field.getGenericType(); + final ParameterizedType paramType = (ParameterizedType) type; + + return (Class) paramType.getActualTypeArguments()[idx]; + } + + /** + *

+ * Return the parametized type passed to members (fields or methods) that accepts Generics. + *

+ * + * @param member Member which type is generified + * @param idx zero based index of the generic argument to get + * @param Type of the generic argument + * @return The class representing the type of the generic argument + * @see #getGenericTypeArgument(Field field, int idx) + */ + public static Class getGenericTypeArgument(final Member member, final int idx) { + Class result = null; + + if (member instanceof Field) { + result = getGenericTypeArgument((Field) member, idx); + } else if (member instanceof Method) { + result = getGenericTypeArgument((Method) member, idx); + } + + return result; + } + + /** + *

+ * Return the parametized type passed to methods that accepts Generics. + *

+ * + * @param method Generified method reference + * @param idx zero based index of the generic argument to get + * @param Type of the generic argument + * @return The class representing the type of the generic argument + * @see #getGenericTypeArgument(Field field, int idx) + */ + @SuppressWarnings("unchecked") + public static Class getGenericTypeArgument(final Method method, final int idx) { + return (Class) method.getGenericParameterTypes()[idx]; + } + + /** + * Returns the value contained in the given field. + * + * @param field field to be extracted the value. + * @param object object that contains the field. + * @param Type of the generic argument + * @return value of the field. + */ + @SuppressWarnings("unchecked") + public static T getFieldValue(Field field, Object object) { + T result = null; + + try { + boolean acessible = field.isAccessible(); + field.setAccessible(true); + result = (T) field.get(object); + field.setAccessible(acessible); + + } catch (Exception e) { + Exceptions.handleToRuntimeException(e); + } + + return result; + } + + /** + * Sets a value in a field. + * + * @param field field to be setted. + * @param object object that contains the field. + * @param value value to be setted in the field. + */ + public static void setFieldValue(Field field, Object object, Object value) { + try { + boolean acessible = field.isAccessible(); + field.setAccessible(true); + field.set(object, value); + field.setAccessible(acessible); + + } catch (Exception e) { + Exceptions.handleToRuntimeException(e); + } + } + + /** + * @param type Base type to look for fields + * @return All non static fields from a certain type. Inherited fields are not returned, so if you need to get + * inherited fields you must iterate over this type's hierarchy. + */ + public static Field[] getNonStaticDeclaredFields(Class type) { + List fields = new ArrayList(); + + if (type != null) { + for (Field field : type.getDeclaredFields()) { + if (!Modifier.isStatic(field.getModifiers()) && !field.getType().equals(type.getDeclaringClass())) { + fields.add(field); + } + } + } + + return fields.toArray(new Field[0]); + } + + /** + * @param type Base type to look for fields + * @return All non static fields from a certain type, including fields declared in superclasses of this type. + */ + public static List getNonStaticFields(Class type) { + List fields = new ArrayList(); + + if (type != null) { + Class currentType = type; + while (currentType != null && !"java.lang.Object".equals(currentType.getCanonicalName())) { + fields.addAll(Arrays.asList(getNonStaticDeclaredFields(currentType))); + currentType = currentType.getSuperclass(); + } + } + + return fields; + } + + /** + * Instantiate an object of the given type. The default constructor with no parameters is used. + * + * @param clazz Base type of object to instantiate + * @param Final type of instantiated object + * @return New instance of provided type + */ + public static T instantiate(Class clazz) { + T object = null; + try { + object = clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + Exceptions.handleToRuntimeException(e); + } + return object; + } + + /** + * Verifies if a given class could be converted to a given type. + * + * @param clazz class to be checked. + * @param type type to be checked. + * @return {@link Boolean} true if the given class can be converted to a given type, and false otherwise. + */ + public static boolean isOfType(Class clazz, Class type) { + return type.isAssignableFrom(clazz) && clazz != type; + } + + /** + * Obtains the {@link ClassLoader} for the given class, from his canonical name. + * + * @param canonicalName canonical name of the the given class. + * @return {@link ClassLoader} ClassLoader for the given class. + */ + public static ClassLoader getClassLoaderForClass(final String canonicalName) { + return Reflections.getClassLoaderForResource(canonicalName.replaceAll("\\.", "/") + ".class"); + } + + /** + * Obtains the {@link ClassLoader} for the given resource. + * + * @param resource String representation of the fully qualified path to the resource on the classpath + * @return {@link ClassLoader} ClassLoader for the given resource. + */ + public static ClassLoader getClassLoaderForResource(final String resource) { + final String stripped = resource.charAt(0) == '/' ? resource.substring(1) : resource; + + URL url = null; + ClassLoader result = Thread.currentThread().getContextClassLoader(); + + if (result != null) { + url = result.getResource(stripped); + } + + if (url == null) { + result = Reflections.class.getClassLoader(); + url = Reflections.class.getClassLoader().getResource(stripped); + } + + if (url == null) { + result = null; + } + + return result; + } + + /** + * Return an URL to access a resource available to the active classloader for the calling thread. + * + * @param resource String representation of the location of the resource on the classpath + * @return The {@link URL} for the resource + */ + public static URL getResourceAsURL(final String resource) { + ClassLoader classLoader = getClassLoaderForResource(resource); + return classLoader != null ? classLoader.getResource(resource) : null; + } + + /** + * Return an InputStream to access a resource available to the active classloader for the calling thread. + * + * @param resource String representation of the location of the resource on the classpath + * @return An {@link InputStream} that reads data from the resource + */ + public static InputStream getResourceAsStream(final String resource) { + ClassLoader classLoader = getClassLoaderForResource(resource); + return classLoader != null ? classLoader.getResourceAsStream(resource) : null; + } + + /** + * Loads a class with the given name using the active classloader for the current thread. + * + * @param className String with fully qualified class name of the desired class + * @param Final type of the loaded class + * @return Class representing the loaded type + * @throws ClassNotFoundException If no class with this name exists + */ + @SuppressWarnings("unchecked") + public static Class forName(final String className) throws ClassNotFoundException { + ClassLoader classLoader = getClassLoaderForClass(className); + return (Class) Class.forName(className, true, classLoader); + } +} diff --git a/core/src/main/java/org/demoiselle/jee/core/util/ResourceBundle.java b/core/src/main/java/org/demoiselle/jee/core/util/ResourceBundle.java new file mode 100644 index 0000000..be81746 --- /dev/null +++ b/core/src/main/java/org/demoiselle/jee/core/util/ResourceBundle.java @@ -0,0 +1,136 @@ +/* + * Demoiselle Framework + * Copyright (C) 2010 SERPRO + * ---------------------------------------------------------------------------- + * This file is part of Demoiselle Framework. + * + * Demoiselle Framework is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License version 3 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this program; if not, see + * or write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301, USA. + * ---------------------------------------------------------------------------- + * Este arquivo é parte do Framework Demoiselle. + * + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação + * do Software Livre (FSF). + * + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português + * para maiores detalhes. + * + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título + * "LICENCA.txt", junto com esse programa. Se não, acesse + * ou escreva para a Fundação do Software Livre (FSF) Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. + */ +package org.demoiselle.jee.core.util; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.Enumeration; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.Set; + +/** + *

The Demoiselle's ResourceBundle extends the abstraction {@link java.util.ResourceBundle}, + * and provide the locale and the base name for the bundle.

+ * + *

To select which resource properties file to load when injecting beans of this class, qualify + * the injection point with {@link org.demoiselle.annotation.Name}, using the resource name (without + * the '.properties' extension) as the value. If the injection point isn't qualified the default + * file messages.properties will be loaded from the root of the classpath.

+ * + * @author SERPRO + */ +public class ResourceBundle extends java.util.ResourceBundle implements Serializable { + + private static final long serialVersionUID = 1L; + + private String baseName; + + private transient java.util.ResourceBundle delegate; + + private final Locale locale; + + private java.util.ResourceBundle getDelegate() { + if (delegate == null) { + try { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + delegate = ResourceBundle.getBundle(baseName, locale, classLoader); + + } catch (MissingResourceException mre) { + delegate = ResourceBundle.getBundle(baseName, locale); + } + } + + return delegate; + } + + /** + * Constructor that set values of baseName and locale. + * + * @param baseName + * the base name to construct the complete bundle name. + * + * @param locale + * locale to define the choosen bundle. + */ + public ResourceBundle(String baseName, Locale locale) { + this.baseName = baseName; + this.locale = locale; + } + + @Override + public boolean containsKey(String key) { + return getDelegate().containsKey(key); + } + + @Override + public Enumeration getKeys() { + return getDelegate().getKeys(); + } + + @Override + public Locale getLocale() { + return getDelegate().getLocale(); + } + + @Override + public Set keySet() { + return getDelegate().keySet(); + } + + public String getString(String key, Object... params) { + return Strings.getString(getString(key), params); + } + + @Override + protected Object handleGetObject(String key) { + Object result; + + try { + Method method = getDelegate().getClass().getMethod("handleGetObject", String.class); + + method.setAccessible(true); + result = method.invoke(delegate, key); + method.setAccessible(false); + + } catch (Exception cause) { + throw new RuntimeException(cause); + } + + return result; + } +} diff --git a/core/src/main/java/org/demoiselle/jee/core/util/Strings.java b/core/src/main/java/org/demoiselle/jee/core/util/Strings.java new file mode 100644 index 0000000..b3e156e --- /dev/null +++ b/core/src/main/java/org/demoiselle/jee/core/util/Strings.java @@ -0,0 +1,301 @@ +/* + * Demoiselle Framework + * Copyright (C) 2010 SERPRO + * ---------------------------------------------------------------------------- + * This file is part of Demoiselle Framework. + * + * Demoiselle Framework is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License version 3 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License version 3 + * along with this program; if not, see + * or write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301, USA. + * ---------------------------------------------------------------------------- + * Este arquivo é parte do Framework Demoiselle. + * + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação + * do Software Livre (FSF). + * + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português + * para maiores detalhes. + * + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título + * "LICENCA.txt", junto com esse programa. Se não, acesse + * ou escreva para a Fundação do Software Livre (FSF) Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. + */ +package org.demoiselle.jee.core.util; + +import org.demoiselle.jee.core.annotation.Ignore; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.demoiselle.util.Reflections; + +/** + * Contain a set of methods that implements a set of functionalities that + * envolves manipulation of strings. + * + * @author SERPRO + */ +public final class Strings { + + private Strings() { + } + + /** + * Returns if some string matches with the format of a ResourceBundle key or + * not. + * + * @param key string to check if matches with key format of ResourceBundle. + * @return boolean true if matches and false otherwise. + */ + public static boolean isResourceBundleKeyFormat(final String key) { + return Pattern.matches("^\\{(.+)\\}$", key == null ? "" : key); + } + + /** + * Removes specific characteres from a given string. + * + * @param string string to be changed, by the removing of some characters. + * @param chars characters to be removed from string. + * @return String returns the given string without the given characters. + */ + public static String removeChars(String string, char... chars) { + String result = string; + + if (result != null) { + for (char ch : chars) { + result = result.replace(String.valueOf(ch), ""); + } + } + return result; + } + + public static String join(String separator, String... strings) { + StringBuffer result = new StringBuffer(); + + if (strings != null) { + for (int i = 0; i < strings.length; i++) { + if (i != 0 && separator != null) { + result.append(separator); + } + + if (strings[i] != null) { + result.append(strings[i]); + } + } + } + + return result.length() > 0 ? result.toString() : null; + } + + /** + * Inserts the character "0" in the begin of a given string. The quantity of + * zeros that will be placed depends on the difference between the length of + * the given string and the value of howMuchZeros. + * + * @param string string to insert zeros characthers. + * @param howMuchZeros its controls how much zeros will be insert. + * @return String Retuns the string, added with appropriate number of zeros. + * For exemplo, if string = "yes" and howMuchZeros = 5, the returned string + * will be "00yes". + */ + public static String insertZeros(String string, int howMuchZeros) { + StringBuffer result = new StringBuffer((string == null ? "" : string).trim()); + int difference = howMuchZeros - result.toString().length(); + + for (int j = 0; j < difference; j++) { + result.insert(0, '0'); + } + + return result.toString(); + } + + /** + * * Replaces the numbers between braces in the given string with the given + * parameters. The process will replace a number between braces for the + * parameter for which its order in the set of parameters matches with the + * number of the given string. For exemple, if is received the following + * string "Treats an {0} exception" and the set of parameters + * {"DemoiselleException"}, the return will be the following string: "Treats + * an DemoiselleException exception". + * + * @param string with the numbers with braces to be replaced with the + * parameters. + * @param params parameters that will replace the number with braces in the + * given string. + * @return String string with numbers replaced with the matching parameter. + */ + public static String getString(final String string, final Object... params) { + String result = null; + + if (string != null) { + result = new String(string); + } + + if (params != null && string != null) { + for (int i = 0; i < params.length; i++) { + if (params[i] != null) { + result = result.replaceAll("\\{" + i + "\\}", Matcher.quoteReplacement(params[i].toString())); + } + } + } + + return result; + } + + /** + * Verifies if a given string is empty or null. + * + * @param string string to be verified. + * @return boolean returns true if the given string is empty or null and + * returns false otherwise. + */ + public static boolean isEmpty(String string) { + return string == null || string.trim().isEmpty(); + } + + /** + * Converts any object to string. + * + * @param object object to be converted. + * @return String the given object converted to string. + */ + public static String toString(Object object) { + StringBuffer result = new StringBuffer(); + Object fieldValue; + + if (object != null) { + result.append(object.getClass().getSimpleName()); + result.append(" ["); + + boolean first = true; + for (Field field : Reflections.getNonStaticDeclaredFields(object.getClass())) { + if (!field.isAnnotationPresent(Ignore.class)) { + if (first) { + first = false; + } else { + result.append(", "); + } + + result.append(field.getName()); + result.append('='); + fieldValue = Reflections.getFieldValue(field, object); + result.append(fieldValue != null && fieldValue.getClass().isArray() + ? Arrays.toString((Object[]) fieldValue) + : fieldValue); + } + } + + result.append(']'); + } + + return result.toString(); + } + + /** + * Replace the camel case string for a lowercase string separated for a + * given symbol. + * + * @param string string that separeted with camel case. + * @param symbol simbol to be the new separator for the given string. + * @return String the given string separated with the given symbol. + */ + public static String camelCaseToSymbolSeparated(String string, String symbol) { + if (symbol == null) { + symbol = ""; + } + + return string == null ? null : string.replaceAll("\\B([A-Z])", symbol + "$1").toLowerCase(); + } + + /** + * Sets the first character of a given string to upper case. + * + * @param string Full string to convert + * @return String the given string with the first character setted to upper + * case. + */ + public static String firstToUpper(String string) { + String result = string; + + if (!Strings.isEmpty(string)) { + result = string.toUpperCase().charAt(0) + (string.length() > 1 ? string.substring(1) : ""); + } + + return result; + } + + /** + * Removes braces from a given string. + * + * @param string Message to remove braces from + * @return String the given string without braces. + */ + public static String removeBraces(String string) { + String result = string; + + if (isResourceBundleKeyFormat(string)) { + result = string.substring(1, string.length() - 1); + } + + return result; + } + + /** + * Inserts braces in a given string. + * + * @param string Original string to insert braces on. + * @return String the given string with braces. + */ + public static String insertBraces(String string) { + String result = string; + + if (!isEmpty(string)) { + result = "{" + string + "}"; + } + + return result; + } + + public static String parse(InputStream inputStream) throws IOException { + StringBuilder result = new StringBuilder(); + + if (inputStream != null) { + BufferedReader reader = null; + + try { + reader = new BufferedReader(new InputStreamReader(inputStream)); + String line; + + while ((line = reader.readLine()) != null) { + result.append(line); + } + + } finally { + if (reader != null) { + reader.close(); + } + } + } + + return result.length() > 0 ? result.toString() : null; + } +} -- libgit2 0.21.2