Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2014 Attila Szegedi, Daniel Dekany, Jonathan Revusky
   * 
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * 
   * http://www.apache.org/licenses/LICENSE-2.0
   * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package freemarker.ext.beans;
 
 import java.util.List;
 import java.util.Map;
 
For internal use only; don't depend on this, there's no backward compatibility guarantee at all! This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can access things inside this package that users shouldn't.
  
 public class _BeansAPI {
 
     private _BeansAPI() { }
     
     public static String getAsClassicCompatibleString(BeanModel bm) {
         return bm.getAsClassicCompatibleString();
     }
     
     public static Object newInstance(Class pClassObject[] argsBeansWrapper bw)
         return newInstance(getConstructorDescriptor(pClassargs), argsbw);
     }
    
    
Gets the constructor that matches the types of the arguments the best. So this is more than what the Java reflection API provides in that it can handle overloaded constructors. This re-uses the overloaded method selection logic of BeansWrapper.
 
     private static CallableMemberDescriptor getConstructorDescriptor(Class pClassObject[] argsthrows NoSuchMethodException {
         if (args == nullargs = .;
         
         final ArgumentTypes argTypes = new ArgumentTypes(argstrue);
         final List fixedArgMemberDescs = new ArrayList();
         final List varArgsMemberDescs = new ArrayList();
         final Constructor[] constrs = pClass.getConstructors();
         for (int i = 0; i < constrs.lengthi++) {
             Constructor constr = constrs[i];
             ReflectionCallableMemberDescriptor memberDesc = new ReflectionCallableMemberDescriptor(constrconstr.getParameterTypes());
             if (!_MethodUtil.isVarargs(constr)) {
                 fixedArgMemberDescs.add(memberDesc);
             } else {
                 varArgsMemberDescs.add(memberDesc);
             }
         }
         
         MaybeEmptyCallableMemberDescriptor contrDesc = argTypes.getMostSpecific(fixedArgMemberDescsfalse);
         if (contrDesc == .) {
             contrDesc = argTypes.getMostSpecific(varArgsMemberDescstrue);
         }
         
         if (contrDesc instanceof EmptyCallableMemberDescriptor) {
             if (contrDesc == .) {
                 throw new NoSuchMethodException(
                         "There's no public " + pClass.getName()
                         + " constructor with compatible parameter list.");
             } else if (contrDesc == .) {
                 throw new NoSuchMethodException(
                         "There are multiple public " + pClass.getName()
                         + " constructors that match the compatible parameter list with the same preferability.");
             } else {
                 throw new NoSuchMethodException();
             }
         } else {
             return (CallableMemberDescriptorcontrDesc;
         }
     }
     
     private static Object newInstance(CallableMemberDescriptor constrDescObject[] argsBeansWrapper bw)
            TemplateModelException {
        if (args == nullargs = .;
        
        final Object[] packedArgs;
        if (constrDesc.isVarargs()) {
            // We have to put all the varargs arguments into a single array argument.
            final Class[] paramTypes = constrDesc.getParamTypes();
            final int fixedArgCnt = paramTypes.length - 1;
            
            packedArgs = new Object[fixedArgCnt + 1]; 
            for (int i = 0; i < fixedArgCnti++) {
                packedArgs[i] = args[i];
            }
            
            final Class compType = paramTypes[fixedArgCnt].getComponentType();
            final int varArgCnt = args.length - fixedArgCnt;
            final Object varArgsArray = Array.newInstance(compTypevarArgCnt);
            for (int i = 0; i < varArgCnti++) {
                Array.set(varArgsArrayiargs[fixedArgCnt + i]);
            }
            packedArgs[fixedArgCnt] = varArgsArray;
        } else {
            packedArgs = args;
        }
        
        return constrDesc.invokeConstructor(bwpackedArgs);
    }
    
    
Contains the common parts of the singleton management for BeansWrapper and freemarker.template.DefaultObjectWrapper.

Parameters:
beansWrapperSubclassFactory Creates a new read-only object wrapper of the desired BeansWrapper subclass.
            BeansWrapperConfiguration settings,
            Map instanceCache,
            ReferenceQueue instanceCacheRefQue,
            _BeansWrapperSubclassFactory beansWrapperSubclassFactory) {
        // BeansWrapper can't be cached across different Thread Context Class Loaders (TCCL), because the result of
        // a class name (String) to Class mappings depends on it, and the staticModels and enumModels need that.
        // (The ClassIntrospector doesn't have to consider the TCCL, as it only works with Class-es, not class
        // names.)
        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
        
        Reference instanceRef;
        Map/*<PropertyAssignments, WeakReference<BeansWrapper>>*/ tcclScopedCache;
        synchronized (instanceCache) {
            tcclScopedCache = (MapinstanceCache.get(tccl);
            if (tcclScopedCache == null) {
                tcclScopedCache = new HashMap();
                instanceCache.put(tccltcclScopedCache);
                instanceRef = null;
            } else {
                instanceRef = (ReferencetcclScopedCache.get(settings);
            }
        }
        BeansWrapper instance = instanceRef != null ? (BeansWrapperinstanceRef.get() : null;
        if (instance != null) {  // cache hit
            return instance;
        }
        // cache miss
        
        settings = (BeansWrapperConfigurationsettings.clone(true);  // prevent any aliasing issues 
        instance = beansWrapperSubclassFactory.create(settings);
        if (!instance.isWriteProtected()) {
            throw new BugException();
        }
        
        synchronized (instanceCache) {
            instanceRef = (ReferencetcclScopedCache.get(settings);
            BeansWrapper concurrentInstance = instanceRef != null ? (BeansWrapperinstanceRef.get() : null;
            if (concurrentInstance == null) {
                tcclScopedCache.put(settingsnew WeakReference(instanceinstanceCacheRefQue));
            } else {
                instance = concurrentInstance;
            }
        }
        
        removeClearedReferencesFromCache(instanceCacheinstanceCacheRefQue);
        
        return instance;
    }
    
    private static void removeClearedReferencesFromCache(Map instanceCacheReferenceQueue instanceCacheRefQue) {
        Reference clearedRef;
        while ((clearedRef = instanceCacheRefQue.poll()) != null) {
            synchronized (instanceCache) {
                findClearedRef: for (Iterator it1 = instanceCache.values().iterator(); it1.hasNext(); ) {
                    Map tcclScopedCache = (Mapit1.next();
                    for (Iterator it2 = tcclScopedCache.values().iterator(); it2.hasNext(); ) {
                        if (it2.next() == clearedRef) {
                            it2.remove();
                            break findClearedRef;
                        }
                    }
                }
            } // sync
        } // while poll
    }
    
    
For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
    public interface _BeansWrapperSubclassFactory {
        
        
Creates a new read-only BeansWrapper; used for BeansWrapperBuilder and such.
    }
    
New to GrepCode? Check out our FAQ X