| 
001 /*002  * Copyright 2008-2015 the original author or authors.
 003  *
 004  * Licensed under the Apache License, Version 2.0 (the "License");
 005  * you may not use this file except in compliance with the License.
 006  * You may obtain a copy of the License at
 007  *
 008  *     http://www.apache.org/licenses/LICENSE-2.0
 009  *
 010  * Unless required by applicable law or agreed to in writing, software
 011  * distributed under the License is distributed on an "AS IS" BASIS,
 012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 013  * See the License for the specific language governing permissions and
 014  * limitations under the License.
 015  */
 016 package org.codehaus.griffon.runtime.groovy.mvc;
 017
 018 import griffon.core.ApplicationClassLoader;
 019 import griffon.core.GriffonApplication;
 020 import griffon.core.artifact.GriffonArtifact;
 021 import griffon.core.mvc.MVCGroup;
 022 import griffon.core.mvc.MVCGroupConfiguration;
 023 import griffon.util.BuilderCustomizer;
 024 import griffon.util.CompositeBuilder;
 025 import groovy.lang.Script;
 026 import groovy.util.FactoryBuilderSupport;
 027 import org.codehaus.griffon.runtime.core.mvc.DefaultMVCGroupManager;
 028 import org.slf4j.Logger;
 029 import org.slf4j.LoggerFactory;
 030
 031 import javax.annotation.Nonnull;
 032 import javax.annotation.Nullable;
 033 import javax.inject.Inject;
 034 import java.util.Collection;
 035 import java.util.Map;
 036
 037 import static griffon.core.GriffonExceptionHandler.sanitize;
 038 import static griffon.util.AnnotationUtils.sortByDependencies;
 039 import static org.codehaus.griffon.runtime.groovy.mvc.GroovyAwareMVCGroup.BUILDER;
 040
 041 /**
 042  * @author Andres Almiray
 043  */
 044 public class GroovyAwareMVCGroupManager extends DefaultMVCGroupManager {
 045     private static final Logger LOG = LoggerFactory.getLogger(DefaultMVCGroupManager.class);
 046     private static final String BUILDER_CUSTOMIZER = "BuilderCustomizer";
 047
 048     @Inject
 049     public GroovyAwareMVCGroupManager(@Nonnull GriffonApplication application, @Nonnull ApplicationClassLoader applicationClassLoader) {
 050         super(application, applicationClassLoader);
 051     }
 052
 053     @Nonnull
 054     @Override
 055     public MVCGroup newMVCGroup(@Nonnull MVCGroupConfiguration configuration, @Nullable String mvcId, @Nonnull Map<String, Object> members, @Nullable MVCGroup parentGroup) {
 056         return new GroovyAwareMVCGroup(this, configuration, mvcId, members, parentGroup);
 057     }
 058
 059     @Nonnull
 060     @Override
 061     @SuppressWarnings("unchecked")
 062     protected Map<String, Object> instantiateMembers(@Nonnull Map<String, ClassHolder> classMap, @Nonnull Map<String, Object> args) {
 063         Map<String, Object> map = super.instantiateMembers(classMap, args);
 064         FactoryBuilderSupport builder = createBuilder(getApplication());
 065         map.put(BUILDER, builder);
 066
 067         for (Object member : map.values()) {
 068             // all scripts get the builder as their binding
 069             if (member instanceof Script) {
 070                 builder.getVariables().putAll(((Script) member).getBinding().getVariables());
 071                 ((Script) member).setBinding(builder);
 072             }
 073         }
 074
 075         return map;
 076     }
 077
 078     @Nonnull
 079     protected FactoryBuilderSupport createBuilder(@Nonnull GriffonApplication application) {
 080         Collection<BuilderCustomizer> customizers = resolveBuilderCustomizers(application);
 081         return new CompositeBuilder(customizers.toArray(new BuilderCustomizer[customizers.size()]));
 082     }
 083
 084     @Override
 085     @SuppressWarnings("ConstantConditions")
 086     protected void adjustMvcArguments(@Nonnull MVCGroup group, @Nonnull Map<String, Object> args) {
 087         super.adjustMvcArguments(group, args);
 088         FactoryBuilderSupport builder = (FactoryBuilderSupport) group.getMember(BUILDER);
 089         args.put(BUILDER, builder);
 090         for (Map.Entry<String, Object> variable : args.entrySet()) {
 091             builder.setVariable(variable.getKey(), variable.getValue());
 092         }
 093     }
 094
 095     @Override
 096     @SuppressWarnings("unchecked")
 097     protected void fillNonArtifactMemberProperties(@Nonnull String type, @Nonnull Object member, @Nonnull Map<String, Object> args) {
 098         if (member instanceof Script) {
 099             ((Script) member).getBinding().getVariables().putAll(args);
 100         }
 101     }
 102
 103     @Override
 104     protected void initializeArtifactMember(@Nonnull MVCGroup group, @Nonnull String type, @Nonnull GriffonArtifact member, @Nonnull Map<String, Object> args) {
 105         if (member instanceof Script) {
 106             ((GroovyAwareMVCGroup) group).buildScriptMember(type);
 107         } else {
 108             super.initializeArtifactMember(group, type, member, args);
 109         }
 110     }
 111
 112     @Override
 113     protected void initializeNonArtifactMember(@Nonnull MVCGroup group, @Nonnull String type, @Nonnull Object member, @Nonnull Map<String, Object> args) {
 114         if (member instanceof Script) {
 115             ((GroovyAwareMVCGroup) group).buildScriptMember(type);
 116         } else {
 117             super.initializeNonArtifactMember(group, type, member, args);
 118         }
 119     }
 120
 121     @Override
 122     protected void destroyMembers(@Nonnull MVCGroup group, boolean fireDestructionEvents) {
 123         super.destroyMembers(group, fireDestructionEvents);
 124
 125         try {
 126             FactoryBuilderSupport builder = (FactoryBuilderSupport) group.getMember(BUILDER);
 127             if (builder != null) {
 128                 builder.dispose();
 129                 builder.getVariables().clear();
 130             }
 131         } catch (Exception e) {
 132             // TODO find out why this call breaks applet mode on shutdown
 133             LOG.error("Application encountered an error while destroying group '" + group.getMvcId() + "'", sanitize(e));
 134         }
 135     }
 136
 137     @Nonnull
 138     protected Collection<BuilderCustomizer> resolveBuilderCustomizers(@Nonnull GriffonApplication application) {
 139         Collection<BuilderCustomizer> customizerInstances = application.getInjector().getInstances(BuilderCustomizer.class);
 140         return sortByDependencies(customizerInstances, BUILDER_CUSTOMIZER, "customizer").values();
 141     }
 142 }
 |