001    /**
002     * Copyright (C) 2009-2011 the original author or authors.
003     * See the notice.md file distributed with this work for additional
004     * information regarding copyright ownership.
005     *
006     * Licensed under the Apache License, Version 2.0 (the "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package org.fusesource.restygwt.rebind;
020    
021    import java.util.ArrayList;
022    import java.util.List;
023    
024    import com.google.gwt.core.ext.BadPropertyValueException;
025    import com.google.gwt.core.ext.GeneratorContext;
026    import com.google.gwt.core.ext.TreeLogger;
027    
028    /**
029     * compile-time defaults
030     *
031     * with this class it will be possible to take part of the generation process of restserviceimpl
032     * classes. by default there are no additional resolvers registered, you can add some if wanted.
033     *
034     * @see http://code.google.com/p/google-web-toolkit/wiki/MultiValuedConfigProperties
035     * @author abalke
036     *
037     */
038    public class BindingDefaults {
039        /**
040         * additional AnnotationResolvers, added by {@link #addAnnotationResolver(AnnotationResolver)}
041         */
042        private static final List<AnnotationResolver> annotationResolvers = new ArrayList<AnnotationResolver>();
043    
044        /**
045         * to avoid returning different Sets of AnnotationResolvers by false
046         * usage, the return of the first call to {@link #getAnnotationResolvers()}
047         * is cached here.
048         *
049         * if there will be a call to {@link #addAnnotationResolver(AnnotationResolver)} after
050         * that first call, we will throw a runtime exception to avoid nasty bugs.
051         */
052        private static List<AnnotationResolver> _annotationResolversRequested = null;
053    
054        /**
055         * access all annotationresolvers that are registered
056         *
057         * @return a copy of all AnnotationResolvers
058         */
059        public static List<AnnotationResolver> getAnnotationResolvers(final GeneratorContext context,
060                final TreeLogger logger) {
061    
062            // do this only the first time call
063            if(null == _annotationResolversRequested) {
064                // call additional AnnotationResolvers if there are some configured
065                try {
066                    for (String className : context.getPropertyOracle()
067                            .getConfigurationProperty("org.fusesource.restygwt.annotationresolver").getValues()) {
068                        logger.log(TreeLogger.INFO, "classname to resolve: " + className);
069                        Class<?> clazz = null;
070    
071                        try {
072                            clazz = Class.forName(className);
073                        } catch (ClassNotFoundException e) {
074                            new RuntimeException("could not resolve class " + className + " "
075                                    + e.getMessage());
076                        }
077    
078                        if (null != clazz) {
079                            try {
080                                logger.log(TreeLogger.INFO, "add annotationresolver: " + clazz.getName());
081                                addAnnotationResolver((AnnotationResolver) clazz.newInstance());
082                            } catch (InstantiationException e) {
083                                new RuntimeException("could not instanciate class " + className + " "
084                                        + e.getMessage());
085                            } catch (IllegalAccessException e) {
086                                new RuntimeException("could not access class " + className + " "
087                                        + e.getMessage());
088                            }
089                        } else {
090                            throw new RuntimeException("could not create instance for classname " + className);
091                        }
092                    }
093                } catch (BadPropertyValueException ignored) {
094                    /*
095                     *  ignored since there is no
096                     *
097                     *  <set-configuration-property name="org.fusesource.restygwt.annotationresolver"
098                     *          value="org.fusesource.restygwt.rebind.ModelChangeAnnotationResolver"/>
099                     */
100                    logger.log(TreeLogger.DEBUG, "no additional annotationresolvers found");
101                }
102            }
103    
104            // return a copy
105            List<AnnotationResolver> ret = new ArrayList<AnnotationResolver>();
106    
107            for (AnnotationResolver a : annotationResolvers) {
108                ret.add(a);
109            }
110            return _annotationResolversRequested = ret;
111        }
112    
113        /**
114         * access all annotationresolvers that are registered
115         *
116         * @return
117         */
118        public static void addAnnotationResolver(AnnotationResolver ar) {
119            if (_annotationResolversRequested != null) {
120                throw new RuntimeException("Sorry, you cannot add more AnnotationResolver instances after the first time " +
121                        "`BindingDefaults#getAnnotationResolvers“ has been called. please check your runtime logic.");
122            }
123            annotationResolvers.add(ar);
124        }
125    }