[jboss-svn-commits] JBoss Common SVN: r4684 - jboss-logging/trunk/src/main/java/org/jboss/logging.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Tue Jul 6 22:25:43 EDT 2010


Author: david.lloyd at jboss.com
Date: 2010-07-06 22:25:42 -0400 (Tue, 06 Jul 2010)
New Revision: 4684

Added:
   jboss-logging/trunk/src/main/java/org/jboss/logging/Cause.java
   jboss-logging/trunk/src/main/java/org/jboss/logging/MessageBundleInvocationHandler.java
   jboss-logging/trunk/src/main/java/org/jboss/logging/MessageLoggerInvocationHandler.java
Modified:
   jboss-logging/trunk/src/main/java/org/jboss/logging/Logger.java
   jboss-logging/trunk/src/main/java/org/jboss/logging/Message.java
Log:
First pass at runtime proxy generation

Added: jboss-logging/trunk/src/main/java/org/jboss/logging/Cause.java
===================================================================
--- jboss-logging/trunk/src/main/java/org/jboss/logging/Cause.java	                        (rev 0)
+++ jboss-logging/trunk/src/main/java/org/jboss/logging/Cause.java	2010-07-07 02:25:42 UTC (rev 4684)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logging;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark a parameter as being the "exception cause" parameter rather than a positional format parameter.
+ *
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.PARAMETER)
+public @interface Cause {
+}

Modified: jboss-logging/trunk/src/main/java/org/jboss/logging/Logger.java
===================================================================
--- jboss-logging/trunk/src/main/java/org/jboss/logging/Logger.java	2010-07-06 22:40:38 UTC (rev 4683)
+++ jboss-logging/trunk/src/main/java/org/jboss/logging/Logger.java	2010-07-07 02:25:42 UTC (rev 4684)
@@ -24,6 +24,9 @@
 import java.io.Serializable;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Locale;
 
 /**
@@ -35,6 +38,16 @@
 
     private static final String FQCN = Logger.class.getName();
 
+    private static final boolean GENERATE_PROXIES;
+
+    static {
+        GENERATE_PROXIES = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+            public Boolean run() {
+                return Boolean.valueOf(System.getProperty("jboss.i18n.generate-proxies"));
+            }
+        }).booleanValue();
+    }
+
     /**
      * Levels used by this logging API.
      */
@@ -2305,6 +2318,9 @@
         if (loggerClass == null) try {
             loggerClass = Class.forName(join(type.getName(), "$logger", null, null, null), true, type.getClassLoader()).asSubclass(type);
         } catch (ClassNotFoundException e) {
+            if (GENERATE_PROXIES) {
+                return type.cast(Proxy.newProxyInstance(type.getClassLoader(), new Class<?>[] { type }, new MessageLoggerInvocationHandler(type, category)));
+            }
             throw new IllegalArgumentException("Invalid logger " + type + " (implementation not found)");
         }
         final Constructor<? extends T> constructor;

Modified: jboss-logging/trunk/src/main/java/org/jboss/logging/Message.java
===================================================================
--- jboss-logging/trunk/src/main/java/org/jboss/logging/Message.java	2010-07-06 22:40:38 UTC (rev 4683)
+++ jboss-logging/trunk/src/main/java/org/jboss/logging/Message.java	2010-07-07 02:25:42 UTC (rev 4684)
@@ -68,14 +68,6 @@
     Format format() default Format.PRINTF;
 
     /**
-     * The converter to use.  Any specified converter must implement the {@code ParameterConverter} interface
-     * from JBoss Logging or JBoss I18n.
-     *
-     * @return the converter
-     */
-    Class<?> converter() default Object.class;
-
-    /**
      * The possible format types.
      */
     enum Format {

Added: jboss-logging/trunk/src/main/java/org/jboss/logging/MessageBundleInvocationHandler.java
===================================================================
--- jboss-logging/trunk/src/main/java/org/jboss/logging/MessageBundleInvocationHandler.java	                        (rev 0)
+++ jboss-logging/trunk/src/main/java/org/jboss/logging/MessageBundleInvocationHandler.java	2010-07-07 02:25:42 UTC (rev 4684)
@@ -0,0 +1,128 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logging;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+class MessageBundleInvocationHandler implements InvocationHandler {
+
+    private final String projectCode;
+
+    protected MessageBundleInvocationHandler(final String projectCode) {
+        this.projectCode = projectCode;
+    }
+
+    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+        final Message message = method.getAnnotation(Message.class);
+        if (message == null) {
+            // nothing to do...
+            return null;
+        }
+        final Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+        ArrayList<Object> newArgs = new ArrayList<Object>();
+        Throwable cause = extractCause(parameterAnnotations, args, newArgs);
+        String result;
+        switch (message.format()) {
+            case PRINTF: {
+                result = String.format(getFormatString(message), newArgs.toArray());
+                break;
+            }
+            case MESSAGE_FORMAT: {
+                result = MessageFormat.format(getFormatString(message), newArgs.toArray());
+                break;
+            }
+            default: throw new IllegalStateException();
+        }
+        final Class<?> returnType = method.getReturnType();
+        if (Throwable.class.isAssignableFrom(returnType)) {
+            // the return type is an exception
+            if (cause != null) {
+                final Constructor<?> constructor = returnType.getConstructor(String.class, Throwable.class);
+                return constructor.newInstance(result, cause);
+            } else {
+                final Constructor<?> constructor = returnType.getConstructor(String.class);
+                return constructor.newInstance(result);
+            }
+        } else {
+            return result;
+        }
+    }
+
+    protected String getFormatString(final Message message) {
+        String formatString = message.value();
+        if (formatString == null) {
+            return null;
+        }
+        final int id = message.id();
+        if (id > 0) {
+            final String projectCode = this.projectCode;
+            if (projectCode != null) {
+                final StringBuilder b = new StringBuilder(32);
+                b.append(projectCode).append('-');
+                if (id < 10) {
+                    b.append("0000");
+                } else if (id < 100) {
+                    b.append("000");
+                } else if (id < 1000) {
+                    b.append("00");
+                } else if (id < 10000) {
+                    b.append("0");
+                }
+                b.append(id);
+                b.append(": ");
+                b.append(formatString);
+                formatString = b.toString();
+            }
+        }
+        return formatString;
+    }
+
+    protected static Throwable extractCause(final Annotation[][] parameterAnnotations, final Object[] args, final List<Object> newArgs) {
+        Throwable cause = null;
+        for (int i = 0; i < parameterAnnotations.length; i++) {
+            Annotation[] annotations = parameterAnnotations[i];
+            boolean found = false;
+            for (Annotation annotation : annotations) {
+                if (annotation instanceof Cause) {
+                    if (cause == null) {
+                        cause = (Throwable) args[i];
+                    }
+                    found = true;
+                }
+            }
+            if (! found) {
+                newArgs.add(args[i]);
+            }
+        }
+        return cause;
+    }
+}

Added: jboss-logging/trunk/src/main/java/org/jboss/logging/MessageLoggerInvocationHandler.java
===================================================================
--- jboss-logging/trunk/src/main/java/org/jboss/logging/MessageLoggerInvocationHandler.java	                        (rev 0)
+++ jboss-logging/trunk/src/main/java/org/jboss/logging/MessageLoggerInvocationHandler.java	2010-07-07 02:25:42 UTC (rev 4684)
@@ -0,0 +1,93 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logging;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+/**
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+class MessageLoggerInvocationHandler extends MessageBundleInvocationHandler {
+
+    private final Logger logger;
+
+    MessageLoggerInvocationHandler(final Class<?> type, final String category) {
+        this(type.getAnnotation(MessageLogger.class), category);
+    }
+
+    private MessageLoggerInvocationHandler(final MessageLogger messageLogger, final String category) {
+        super(messageLogger.projectCode());
+        logger = Logger.getLogger(category);
+    }
+
+    public Object invoke(final Object proxy, final Method method, Object[] args) throws Throwable {
+        final Message message = method.getAnnotation(Message.class);
+        if (message == null) {
+            // nothing to do...
+            return null;
+        }
+        final Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+        final LogMessage logMessage = method.getAnnotation(LogMessage.class);
+        if (logMessage != null) {
+
+            try {
+                // See if it's a basic logger method
+                if (method.getDeclaringClass().equals(BasicLogger.class)) {
+                    // doesn't cover overrides though!
+                    return method.invoke(logger, args);
+                }
+
+                // it's a log message
+                final Logger.Level level = logMessage.level();
+                if (logger.isEnabled(level)) {
+                    String formatString = getFormatString(message);
+                    if (formatString == null) {
+                        return null;
+                    }
+                    ArrayList<Object> newArgs = new ArrayList<Object>();
+                    Throwable cause = extractCause(parameterAnnotations, args, newArgs);
+                    final Message.Format format = message.format();
+                    switch (format) {
+                        case PRINTF: {
+                            logger.logf(level, cause, formatString, newArgs.toArray());
+                            return null;
+                        }
+                        case MESSAGE_FORMAT: {
+                            logger.logv(level, cause, formatString, newArgs.toArray());
+                            return null;
+                        }
+                        default: {
+                            return null;
+                        }
+                    }
+                }
+            } catch (Throwable ignored) {
+            }
+        } else {
+            return super.invoke(proxy, method, args);
+        }
+        return null;
+    }
+}



More information about the jboss-svn-commits mailing list