@Override public void setResourceLoader(ResourceLoader resourceLoader) { if (Metadata.getCurrent().isWarDeployed()) { localResourceLoader = resourceLoader; } else { // The "settings" may be null in some of the Grails unit tests. BuildSettings settings = BuildSettingsHolder.getSettings(); String location = null; if (settings != null) { location = settings.getResourcesDir().getPath(); } else if (Environment.getCurrent().isReloadEnabled()) { location = Environment.getCurrent().getReloadLocation(); } if (location != null) { localResourceLoader = new DevelopmentResourceLoader(application, location); } else { localResourceLoader = resourceLoader; } } super.setResourceLoader(localResourceLoader); if (resourceResolver == null) { resourceResolver = new PathMatchingResourcePatternResolver(localResourceLoader); } }
private static ScriptAndArgs processAndReturnArguments(CommandLine commandLine) { ScriptAndArgs info = new ScriptAndArgs(); if (Environment.isSystemSet()) { info.env = Environment.getCurrent().getName(); } else if (commandLine.getEnvironment() != null) { info.env = commandLine.getEnvironment(); } info.inputName = commandLine.getCommandName(); info.name = GrailsNameUtils.getNameFromScript(commandLine.getCommandName()); return info; }
private static List getBindingIncludeList(final Object object) { List includeList = Collections.emptyList(); try { final Class<? extends Object> objectClass = object.getClass(); if (CLASS_TO_BINDING_INCLUDE_LIST.containsKey(objectClass)) { includeList = CLASS_TO_BINDING_INCLUDE_LIST.get(objectClass); } else { final Field whiteListField = objectClass.getDeclaredField(DefaultASTDatabindingHelper.DEFAULT_DATABINDING_WHITELIST); if (whiteListField != null) { if ((whiteListField.getModifiers() & Modifier.STATIC) != 0) { final Object whiteListValue = whiteListField.get(objectClass); if (whiteListValue instanceof List) { includeList = (List) whiteListValue; } } } if (!Environment.getCurrent().isReloadEnabled()) { CLASS_TO_BINDING_INCLUDE_LIST.put(objectClass, includeList); } } } catch (Exception e) { } return includeList; }
public GroovyPageParser( String name, String uri, String filename, String gspSource, String expressionCodecName) throws IOException { Config config = Holders.getConfig(); if (config != null) { setEnableSitemeshPreprocessing( config.getProperty( GroovyPageParser.CONFIG_PROPERTY_GSP_SITEMESH_PREPROCESS, Boolean.class, enableSitemeshPreprocessing)); } GrailsPluginInfo pluginInfo = null; // TODO: figure out a way to restore plugin metadata for GSP // if (filename != null && BuildSettingsHolder.getSettings() != null) { // pluginInfo = // GrailsPluginUtils.getPluginBuildSettings().getPluginInfoForSource(filename); // if (pluginInfo != null) { // pluginAnnotation = "@GrailsPlugin(name='" + pluginInfo.getName() + "', // version='" + // pluginInfo.getVersion() + "')"; // } // } OutputEncodingSettings gspConfig = new OutputEncodingSettings(config); this.expressionCodecDirectiveValue = expressionCodecName; if (expressionCodecDirectiveValue == null) { expressionCodecDirectiveValue = gspConfig.getCodecSettings(pluginInfo, OutputEncodingSettings.EXPRESSION_CODEC_NAME); } staticCodecDirectiveValue = gspConfig.getCodecSettings(pluginInfo, OutputEncodingSettings.STATIC_CODEC_NAME); outCodecDirectiveValue = gspConfig.getCodecSettings(pluginInfo, OutputEncodingSettings.OUT_CODEC_NAME); taglibCodecDirectiveValue = gspConfig.getCodecSettings(pluginInfo, OutputEncodingSettings.TAGLIB_CODEC_NAME); Map<String, String> directives = parseDirectives(gspSource); if (isSitemeshPreprocessingEnabled(directives.get(SITEMESH_PREPROCESS_DIRECTIVE))) { if (LOG.isDebugEnabled()) { LOG.debug( "Preprocessing " + uri + " for sitemesh. Replacing head, title, meta and body elements with sitemesh:capture*."); } // GSP preprocessing for direct sitemesh integration: replace head -> g:captureHead, title -> // g:captureTitle, meta -> g:captureMeta, body -> g:captureBody gspSource = sitemeshPreprocessor.addGspSitemeshCapturing(gspSource); sitemeshPreprocessMode = true; } scan = new GroovyPageScanner(gspSource, uri); pageName = uri; environment = Environment.getCurrent(); makeName(name); makeSourceName(filename); }
private Resource getResourceWithinContext(String uri) { if (resourceLoader == null) throw new IllegalStateException( "TemplateEngine not initialised correctly, no [resourceLoader] specified!"); if (Environment.getCurrent().isReloadEnabled() && Metadata.getCurrent().isWarDeployed()) { return resourceLoader.getResource(uri); } Resource r = servletContextLoader.getResource(uri); if (r.exists()) return r; return resourceLoader.getResource(uri); }
@Override public Resource findResourceForURI(String uri) { Resource resource = uriResolveCache.get(uri); if (resource == null) { resource = super.findResourceForURI(uri); if (resource == null && Environment.isWarDeployed()) { resource = NULL_RESOURCE; } if (resource != null) uriResolveCache.put(uri, resource); } return resource == NULL_RESOURCE ? null : resource; }
public void afterPropertiesSet() throws Exception { resourceLoader = GrailsResourceLoaderHolder.getResourceLoader(); if (resourceLoader != null) { return; } if (Environment.getCurrent().isReloadEnabled()) { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); try { Resource[] resources = resolver.getResources( "file:" + Environment.getCurrent().getReloadLocation() + "/grails-app/**/*.groovy"); resourceLoader = new GrailsResourceLoader(resources); } catch (IOException e) { createDefaultInternal(); } } else { createDefaultInternal(); } GrailsResourceLoaderHolder.setResourceLoader(resourceLoader); }
/** * Get the default Compass connection (ie, Lucene index dir) * * @param grailsApplication the GrailsApplication - may be null * @return {user.home}/.grails/projects/{project-name}/searchable-index/{grails.env} */ public static String getDefaultConnection(GrailsApplication grailsApplication) { String appName = SearchableUtils.getAppName(grailsApplication); return new StringBuilder(System.getProperty("user.home")) .append(File.separator) .append(".grails") .append(File.separator) .append("projects") .append(File.separator) .append(appName) .append(File.separator) .append("searchable-index") .append(File.separator) .append(Environment.getCurrent().getName()) .toString(); }
/** * Returns the absolute path to the provided Grails plugin if it is being used "inline" or {@code * null} if the plugin is <b>not</b> being used "inline". * * @param grailsPlugin The Grails plugin. * @return The absolute path to the "inline" plugin or {@code null} if the plugin is not being * used "inline". */ protected String getInlinePluginPath(GrailsPlugin grailsPlugin) { if (Environment.isWarDeployed()) return null; try { final GrailsPluginInfo pluginInfo = pluginBuildSettings.getPluginInfoForName(grailsPlugin.getFileSystemShortName()); if (pluginInfo != null) { return new File( pluginBuildSettings.getBuildSettings().getResourcesDir(), "plugins/" + pluginInfo.getFullName()) .getCanonicalPath(); } } catch (final IOException e) { LOG.debug( "Unable to retrieve plugin directory for plugin " + grailsPlugin.getFileSystemShortName(), e); } return null; }
@Override public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException { if (Environment.isInitializing()) { return; } if (autowireMode == AUTOWIRE_BY_NAME) { if (DISABLE_AUTOWIRE_BY_NAME_OPTIMIZATIONS || dependencyCheck || existingBean instanceof Aware) { super.autowireBeanProperties(existingBean, autowireMode, dependencyCheck); } else { populateBeanInAutowireByName(existingBean); } } else { super.autowireBeanProperties(existingBean, autowireMode, dependencyCheck); } }
/** Default constructor. */ public ReloadAwareAutowireCapableBeanFactory() { reloadEnabled = GrailsUtil.isDevelopmentEnv() || Environment.getCurrent().isReloadEnabled(); if (reloadEnabled) { // Implementation note: The default Spring InstantiationStrategy caches constructors. // This is no good at development time because if the class reloads then Spring // continues to use the old class. We deal with this here by disabling the caching // for development time only setInstantiationStrategy( new CglibSubclassingInstantiationStrategy() { @Override public Object instantiate( RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. if (beanDefinition.getMethodOverrides().isEmpty()) { Constructor<?> constructorToUse; Class<?> clazz = beanDefinition.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { constructorToUse = clazz.getDeclaredConstructor((Class[]) null); } catch (Exception ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } return BeanUtils.instantiateClass(constructorToUse); } // Must generate CGLIB subclass. return instantiateWithMethodInjection(beanDefinition, beanName, owner); } }); } setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer()); setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver()); ignoreDependencyType(Closure.class); }
@SuppressWarnings("unchecked") private void evaluateOnChangeListener() { if (pluginBean.isReadableProperty(ON_SHUTDOWN)) { onShutdownListener = (Closure) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, ON_SHUTDOWN); } if (pluginBean.isReadableProperty(ON_CONFIG_CHANGE)) { onConfigChangeListener = (Closure) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, ON_CONFIG_CHANGE); } if (pluginBean.isReadableProperty(ON_CHANGE)) { onChangeListener = (Closure) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, ON_CHANGE); } final boolean warDeployed = Metadata.getCurrent().isWarDeployed(); final boolean reloadEnabled = Environment.getCurrent().isReloadEnabled(); if (!((reloadEnabled || !warDeployed) && onChangeListener != null)) { return; } Object referencedResources = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, WATCHED_RESOURCES); try { List resourceList = null; if (referencedResources instanceof String) { if (LOG.isDebugEnabled()) { LOG.debug( "Configuring plugin " + this + " to watch resources with pattern: " + referencedResources); } resourceList = new ArrayList(); resourceList.add(referencedResources.toString()); } else if (referencedResources instanceof List) { resourceList = (List) referencedResources; } if (resourceList != null) { List<String> resourceListTmp = new ArrayList<String>(); PluginBuildSettings pluginBuildSettings = GrailsPluginUtils.getPluginBuildSettings(); if (pluginBuildSettings != null) { final Resource[] pluginDirs = pluginBuildSettings.getPluginDirectories(); final Environment env = Environment.getCurrent(); final String baseLocation = env.getReloadLocation(); for (Object ref : resourceList) { String stringRef = ref.toString(); if (!warDeployed) { for (Resource pluginDir : pluginDirs) { if (pluginDir != null) { String pluginResources = getResourcePatternForBaseLocation( pluginDir.getFile().getCanonicalPath(), stringRef); resourceListTmp.add(pluginResources); } } addBaseLocationPattern(resourceListTmp, baseLocation, stringRef); } else { addBaseLocationPattern(resourceListTmp, baseLocation, stringRef); } } watchedResourcePatternReferences = new String[resourceListTmp.size()]; for (int i = 0; i < watchedResourcePatternReferences.length; i++) { String resRef = resourceListTmp.get(i); watchedResourcePatternReferences[i] = resRef; } watchedResourcePatterns = new WatchPatternParser() .getWatchPatterns(Arrays.asList(watchedResourcePatternReferences)); } } } catch (IllegalArgumentException e) { if (GrailsUtil.isDevelopmentEnv()) { LOG.debug( "Cannot load plug-in resource watch list from [" + ArrayUtils.toString(watchedResourcePatternReferences) + "]. This means that the plugin " + this + ", will not be able to auto-reload changes effectively. Try runnng grails upgrade.: " + e.getMessage()); } } catch (IOException e) { if (GrailsUtil.isDevelopmentEnv()) { LOG.debug( "Cannot load plug-in resource watch list from [" + ArrayUtils.toString(watchedResourcePatternReferences) + "]. This means that the plugin " + this + ", will not be able to auto-reload changes effectively. Try runnng grails upgrade.: " + e.getMessage()); } } }
/** * Default ResourceLocator implementation that doesn't take into account servlet loading. * * @author Graeme Rocher * @since 2.0 */ public class DefaultResourceLocator implements ResourceLocator, ResourceLoaderAware, PluginManagerAware { public static final String WILDCARD = "*"; public static final String FILE_SEPARATOR = File.separator; public static final String CLOSURE_MARKER = "$"; public static final String WEB_APP_DIR = "web-app"; protected static final Resource NULL_RESOURCE = new ByteArrayResource("null".getBytes()); protected PathMatchingResourcePatternResolver patchMatchingResolver; protected List<String> classSearchDirectories = new ArrayList<String>(); protected List<String> resourceSearchDirectories = new ArrayList<String>(); protected Map<String, Resource> classNameToResourceCache = new ConcurrentHashMap<String, Resource>(); protected Map<String, Resource> uriToResourceCache = new ConcurrentHashMap<String, Resource>(); protected ResourceLoader defaultResourceLoader = new FileSystemResourceLoader(); protected GrailsPluginManager pluginManager; protected boolean warDeployed = Environment.isWarDeployed(); public void setSearchLocation(String searchLocation) { ResourceLoader resourceLoader = getDefaultResourceLoader(); patchMatchingResolver = new CachingPathMatchingResourcePatternResolver(resourceLoader); initializeForSearchLocation(searchLocation); } protected ResourceLoader getDefaultResourceLoader() { return defaultResourceLoader; } public void setSearchLocations(Collection<String> searchLocations) { patchMatchingResolver = new CachingPathMatchingResourcePatternResolver(getDefaultResourceLoader()); for (String searchLocation : searchLocations) { initializeForSearchLocation(searchLocation); } } private void initializeForSearchLocation(String searchLocation) { String searchLocationPlusSlash = searchLocation.endsWith("/") ? searchLocation : searchLocation + FILE_SEPARATOR; try { File[] directories = new File(searchLocationPlusSlash + GrailsResourceUtils.GRAILS_APP_DIR) .listFiles( new FileFilter() { public boolean accept(File file) { return file.isDirectory() && !file.isHidden(); } }); if (directories != null) { for (File directory : directories) { classSearchDirectories.add(directory.getCanonicalPath()); } } } catch (IOException e) { // ignore } classSearchDirectories.add(searchLocationPlusSlash + "src/main/java"); classSearchDirectories.add(searchLocationPlusSlash + "src/main/groovy"); resourceSearchDirectories.add(searchLocationPlusSlash); } public Resource findResourceForURI(String uri) { Resource resource = uriToResourceCache.get(uri); if (resource == null) { PluginResourceInfo info = inferPluginNameFromURI(uri); if (warDeployed) { Resource defaultResource = defaultResourceLoader.getResource(uri); if (defaultResource != null && defaultResource.exists()) { resource = defaultResource; } } else { String uriWebAppRelative = WEB_APP_DIR + uri; for (String resourceSearchDirectory : resourceSearchDirectories) { Resource res = resolveExceptionSafe(resourceSearchDirectory + uriWebAppRelative); if (res.exists()) { resource = res; } else if (!warDeployed) { Resource dir = resolveExceptionSafe(resourceSearchDirectory); if (dir.exists() && info != null) { try { String filename = dir.getFilename(); if (filename != null && filename.equals(info.pluginName)) { Resource pluginFile = dir.createRelative(WEB_APP_DIR + info.uri); if (pluginFile.exists()) { resource = pluginFile; } } } catch (IOException e) { // ignore } } } } } if (resource == null && info != null) { resource = findResourceInBinaryPlugins(info); } if (resource == null || !resource.exists()) { Resource tmp = defaultResourceLoader != null ? defaultResourceLoader.getResource(uri) : null; if (tmp != null && tmp.exists()) { resource = tmp; } } if (resource != null) { uriToResourceCache.put(uri, resource); } else if (warDeployed) { uriToResourceCache.put(uri, NULL_RESOURCE); } } return resource == NULL_RESOURCE ? null : resource; } protected Resource findResourceInBinaryPlugins(PluginResourceInfo info) { if (pluginManager != null) { String fullPluginName = info.pluginName; for (GrailsPlugin plugin : pluginManager.getAllPlugins()) { if (plugin.getFileSystemName().equals(fullPluginName) && (plugin instanceof BinaryGrailsPlugin)) { return ((BinaryGrailsPlugin) plugin).getResource(info.uri); } } } return null; } private PluginResourceInfo inferPluginNameFromURI(String uri) { if (uri.startsWith("/plugins/")) { String withoutPluginsPath = uri.substring("/plugins/".length(), uri.length()); int i = withoutPluginsPath.indexOf('/'); if (i > -1) { PluginResourceInfo info = new PluginResourceInfo(); info.pluginName = withoutPluginsPath.substring(0, i); info.uri = withoutPluginsPath.substring(i, withoutPluginsPath.length()); return info; } } return null; } public Resource findResourceForClassName(String className) { if (className.contains(CLOSURE_MARKER)) { className = className.substring(0, className.indexOf(CLOSURE_MARKER)); } Resource resource = classNameToResourceCache.get(className); if (resource == null) { String classNameWithPathSeparator = className.replace(".", FILE_SEPARATOR); for (String pathPattern : getSearchPatternForExtension(classNameWithPathSeparator, ".groovy", ".java")) { resource = resolveExceptionSafe(pathPattern); if (resource != null && resource.exists()) { classNameToResourceCache.put(className, resource); break; } } } return resource != null && resource.exists() ? resource : null; } private List<String> getSearchPatternForExtension( String classNameWithPathSeparator, String... extensions) { List<String> searchPatterns = new ArrayList<String>(); for (String extension : extensions) { String filename = classNameWithPathSeparator + extension; for (String classSearchDirectory : classSearchDirectories) { searchPatterns.add(classSearchDirectory + FILE_SEPARATOR + filename); } } return searchPatterns; } private Resource resolveExceptionSafe(String pathPattern) { try { Resource[] resources = patchMatchingResolver.getResources("file:" + pathPattern); if (resources != null && resources.length > 0) { return resources[0]; } } catch (IOException e) { return null; } return null; } public void setResourceLoader(ResourceLoader resourceLoader) { defaultResourceLoader = resourceLoader; } public void setPluginManager(GrailsPluginManager pluginManager) { this.pluginManager = pluginManager; } class PluginResourceInfo { String pluginName; String uri; } }
@SuppressWarnings("rawtypes") @Override public GrailsClass getArtefactForFeature(Object featureId) { if (artefactInfo == null) { return null; } String uri; String pluginName = null; if (featureId instanceof Map) { Map featureIdMap = (Map) featureId; uri = (String) featureIdMap.get("uri"); pluginName = (String) featureIdMap.get("pluginName"); } else { uri = featureId.toString(); } GrailsClass controllerClass = uriToControllerClassCache.get(uri); if (controllerClass == null) { final ApplicationContext mainContext = grailsApplication.getMainContext(); GrailsPluginManager grailsPluginManager = null; if (mainContext.containsBean(GrailsPluginManager.BEAN_NAME)) { final Object pluginManagerBean = mainContext.getBean(GrailsPluginManager.BEAN_NAME); if (pluginManagerBean instanceof GrailsPluginManager) { grailsPluginManager = (GrailsPluginManager) pluginManagerBean; } } final GrailsClass[] controllerClasses = artefactInfo.getGrailsClasses(); // iterate in reverse in order to pick up application classes first for (int i = (controllerClasses.length - 1); i >= 0; i--) { GrailsClass c = controllerClasses[i]; if (((GrailsControllerClass) c).mapsToURI(uri)) { boolean foundController = false; if (pluginName != null && grailsPluginManager != null) { final GrailsPlugin pluginForClass = grailsPluginManager.getPluginForClass(c.getClazz()); if (pluginForClass != null && pluginName.equals(pluginForClass.getName())) { foundController = true; } } else { foundController = true; } if (foundController) { controllerClass = c; break; } } } if (controllerClass == null) { controllerClass = NO_CONTROLLER; } // don't cache for dev environment if (Environment.getCurrent() != Environment.DEVELOPMENT) { uriToControllerClassCache.put(uri, controllerClass); } } if (controllerClass == NO_CONTROLLER) { controllerClass = null; } return controllerClass; }
public boolean supportsEnvironment(Environment environment) { return supportsValueInIncludeExcludeMap(pluginEnvs, environment.getName()); }
/** * Enhances controller classes with a method missing implementation for tags at compile time. * * @author Graeme Rocher * @since 2.0 */ public class ControllerTagLibraryApi extends CommonWebApi { private static final long serialVersionUID = 1; private transient TagLibraryLookup tagLibraryLookup; private boolean developmentMode = Environment.isDevelopmentMode(); public ControllerTagLibraryApi(GrailsPluginManager pluginManager) { super(pluginManager); } public ControllerTagLibraryApi() { super(null); } @Autowired public void setTagLibraryLookup(TagLibraryLookup lookup) { tagLibraryLookup = lookup; } @Autowired public void setGspTagLibraryLookup(TagLibraryLookup lookup) { tagLibraryLookup = lookup; } /** * Method missing implementation that handles tag invocation by method name * * @param instance The instance * @param methodName The method name * @param argsObject The arguments * @return The result */ public Object methodMissing(Object instance, String methodName, Object argsObject) { Object[] args = argsObject instanceof Object[] ? (Object[]) argsObject : new Object[] {argsObject}; TagLibraryLookup lookup = getTagLibraryLookup(); if (lookup != null) { GroovyObject tagLibrary = lookup.lookupTagLibrary(GroovyPage.DEFAULT_NAMESPACE, methodName); if (tagLibrary != null) { if (!developmentMode) { MetaClass controllerMc = GrailsMetaClassUtils.getMetaClass(instance); WebMetaUtils.registerMethodMissingForTags( controllerMc, lookup, GroovyPage.DEFAULT_NAMESPACE, methodName); } List<MetaMethod> respondsTo = tagLibrary.getMetaClass().respondsTo(tagLibrary, methodName, args); if (respondsTo.size() > 0) { return respondsTo.get(0).invoke(tagLibrary, args); } } } throw new MissingMethodException(methodName, instance.getClass(), args); } /** * Looks up namespaces on missing property * * @param instance The instance * @param propertyName The property name * @return The namespace or a MissingPropertyException */ public Object propertyMissing(Object instance, String propertyName) { TagLibraryLookup lookup = getTagLibraryLookup(); NamespacedTagDispatcher namespacedTagDispatcher = lookup.lookupNamespaceDispatcher(propertyName); if (namespacedTagDispatcher != null) { if (!developmentMode) { WebMetaUtils.registerPropertyMissingForTag( GrailsMetaClassUtils.getMetaClass(instance), propertyName, namespacedTagDispatcher); } return namespacedTagDispatcher; } throw new MissingPropertyException(propertyName, instance.getClass()); } public TagLibraryLookup getTagLibraryLookup() { if (tagLibraryLookup == null) { ApplicationContext applicationContext = getApplicationContext(null); if (applicationContext != null) { try { tagLibraryLookup = applicationContext.getBean(TagLibraryLookup.class); } catch (BeansException e) { return null; } } } return tagLibraryLookup; } public Object withCodec(Object instance, Object codecInfo, Closure body) { return WithCodecHelper.withCodec(getGrailsApplication(null), codecInfo, body); } }
public boolean supportsCurrentScopeAndEnvironment() { BuildScope bs = BuildScope.getCurrent(); Environment e = Environment.getCurrent(); return supportsEnvironment(e) && supportsScope(bs); }
/** * An immutable ConverterConfiguration which chains the lookup calls for ObjectMarshallers for * performance reasons. * * @author Siegfried Puchbauer * @author Graeme Rocher * @since 1.1 */ @SuppressWarnings("rawtypes") public class ChainedConverterConfiguration<C extends Converter> implements ConverterConfiguration<C> { private List<ObjectMarshaller<C>> marshallerList; private ChainedObjectMarshaller<C> root; private final String encoding; private final Converter.CircularReferenceBehaviour circularReferenceBehaviour; private final boolean prettyPrint; private ProxyHandler proxyHandler; private final boolean cacheObjectMarshallerByClass; private Map<Integer, ObjectMarshaller<C>> objectMarshallerForClassCache; private final boolean developmentMode = Environment.isDevelopmentMode(); private final ObjectMarshaller<C> NULL_HOLDER = new ObjectMarshaller<C>() { public boolean supports(Object object) { return false; } public void marshalObject(Object object, C converter) throws ConverterException {} }; public ChainedConverterConfiguration(ConverterConfiguration<C> cfg) { this(cfg, new DefaultProxyHandler()); } public ChainedConverterConfiguration(ConverterConfiguration<C> cfg, ProxyHandler proxyHandler) { marshallerList = cfg.getOrderedObjectMarshallers(); this.proxyHandler = proxyHandler; encoding = cfg.getEncoding(); prettyPrint = cfg.isPrettyPrint(); cacheObjectMarshallerByClass = cfg.isCacheObjectMarshallerByClass(); if (cacheObjectMarshallerByClass) { objectMarshallerForClassCache = new ConcurrentHashMap<Integer, ObjectMarshaller<C>>(); } circularReferenceBehaviour = cfg.getCircularReferenceBehaviour(); List<ObjectMarshaller<C>> oms = new ArrayList<ObjectMarshaller<C>>(marshallerList); Collections.reverse(oms); ChainedObjectMarshaller<C> prev = null; for (ObjectMarshaller<C> om : oms) { prev = new ChainedObjectMarshaller<C>(om, prev); } root = prev; } public ObjectMarshaller<C> getMarshaller(Object o) { ObjectMarshaller<C> marshaller = null; Integer cacheKey = null; if (!developmentMode && cacheObjectMarshallerByClass && o != null) { cacheKey = System.identityHashCode(o.getClass()); marshaller = objectMarshallerForClassCache.get(cacheKey); if (marshaller != NULL_HOLDER && marshaller != null && !marshaller.supports(o)) { marshaller = null; } } if (marshaller == null) { marshaller = root.findMarhallerFor(o); if (cacheKey != null) { objectMarshallerForClassCache.put(cacheKey, marshaller != null ? marshaller : NULL_HOLDER); } } return marshaller != NULL_HOLDER ? marshaller : null; } public String getEncoding() { return encoding; } public Converter.CircularReferenceBehaviour getCircularReferenceBehaviour() { return circularReferenceBehaviour; } public boolean isPrettyPrint() { return prettyPrint; } public List<ObjectMarshaller<C>> getOrderedObjectMarshallers() { return marshallerList; } @SuppressWarnings("hiding") public class ChainedObjectMarshaller<C extends Converter> implements ObjectMarshaller<C> { private ObjectMarshaller<C> om; private ChainedObjectMarshaller<C> next; public ChainedObjectMarshaller(ObjectMarshaller<C> om, ChainedObjectMarshaller<C> next) { this.om = om; this.next = next; } public ObjectMarshaller<C> findMarhallerFor(Object o) { if (supports(o)) { return om; } return next != null ? next.findMarhallerFor(o) : null; } public boolean supports(Object object) { return om.supports(object); } public void marshalObject(Object object, C converter) throws ConverterException { om.marshalObject(object, converter); } } public ProxyHandler getProxyHandler() { return proxyHandler; } public boolean isCacheObjectMarshallerByClass() { return cacheObjectMarshallerByClass; } }