ServiceArtifactHandler.java
001 /*
002  * Copyright 2009-2012 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 
017 package org.codehaus.griffon.runtime.core;
018 
019 import griffon.core.*;
020 import groovy.lang.MetaClass;
021 import groovy.lang.MetaProperty;
022 import org.codehaus.groovy.runtime.InvokerHelper;
023 import org.slf4j.Logger;
024 import org.slf4j.LoggerFactory;
025 
026 import java.util.Collections;
027 import java.util.Map;
028 import java.util.concurrent.ConcurrentHashMap;
029 
030 import static griffon.util.ConfigUtils.getConfigValueAsBoolean;
031 
032 /**
033  * Handler for 'Service' artifacts.
034  *
035  @author Andres Almiray
036  @since 0.9.1
037  */
038 public class ServiceArtifactHandler extends ArtifactHandlerAdapter {
039     private static final Logger LOG = LoggerFactory.getLogger(ServiceArtifactHandler.class);
040     private final ServiceManager serviceManager;
041 
042     private class DefaultServiceManager extends AbstractServiceManager {
043         private final Map<String, GriffonService> serviceInstances = new ConcurrentHashMap<String, GriffonService>();
044 
045         public DefaultServiceManager(GriffonApplication app) {
046             super(app);
047         }
048 
049         public Map<String, GriffonService> getServices() {
050             return Collections.unmodifiableMap(serviceInstances);
051         }
052 
053         public GriffonService findService(String name) {
054             GriffonService serviceInstance = serviceInstances.get(name);
055             if (serviceInstance == null) {
056                 GriffonClass griffonClass = findClassFor(name);
057                 if (griffonClass != null) {
058                     serviceInstance = instantiateService(griffonClass);
059                     serviceInstances.put(name, serviceInstance);
060                 }
061             }
062             return serviceInstance;
063         }
064 
065         private GriffonService instantiateService(GriffonClass griffonClass) {
066             GriffonService serviceInstance = (GriffonServicegriffonClass.newInstance();
067             InvokerHelper.setProperty(serviceInstance, "app", getApp());
068             getApp().addApplicationEventListener(serviceInstance);
069             return serviceInstance;
070         }
071     }
072 
073     public ServiceArtifactHandler(GriffonApplication app) {
074         super(app, GriffonServiceClass.TYPE, GriffonServiceClass.TRAILING);
075         serviceManager = new DefaultServiceManager(app);
076         if (LOG.isDebugEnabled()) {
077             LOG.debug("Registering " + serviceManager + " as ServiceManager.");
078         }
079         InvokerHelper.setProperty(app, "serviceManager", serviceManager);
080     }
081 
082     protected GriffonClass newGriffonClassInstance(Class clazz) {
083         return new DefaultGriffonServiceClass(getApp(), clazz);
084     }
085 
086     public void initialize(ArtifactInfo[] artifacts) {
087         super.initialize(artifacts);
088         if (isBasicInjectionDisabled()) return;
089         if (isEagerInstantiationEnabled()) {
090             if (LOG.isDebugEnabled()) {
091                 LOG.debug("Instantiating service instances eagerly");
092             }
093             for (ArtifactInfo artifactInfo : artifacts) {
094                 GriffonClass griffonClass = getClassFor(artifactInfo.getClazz());
095                 serviceManager.findService(griffonClass.getPropertyName());
096             }
097         }
098         getApp().addApplicationEventListener(this);
099     }
100 
101     /**
102      * Application event listener.<p>
103      * Lazily injects services instances if {@code app.config.griffon.basic_injection.disable}
104      * is not set to true
105      */
106     public void onNewInstance(Class klass, String t, Object instance) {
107         if (isBasicInjectionDisabled()) return;
108         MetaClass metaClass = InvokerHelper.getMetaClass(instance);
109         for (MetaProperty property : metaClass.getProperties()) {
110             String propertyName = property.getName();
111             if (!propertyName.endsWith(getTrailing())) continue;
112             GriffonService serviceInstance = serviceManager.findService(propertyName);
113 
114             if (serviceInstance != null) {
115                 if (LOG.isDebugEnabled()) {
116                     LOG.debug("Injecting service " + serviceInstance + " on " + instance + " using property '" + propertyName + "'");
117                 }
118                 InvokerHelper.setProperty(instance, propertyName, serviceInstance);
119             }
120         }
121     }
122 
123     private boolean isBasicInjectionDisabled() {
124         return getConfigValueAsBoolean(getApp().getConfig()"griffon.basic_injection.disable"false);
125     }
126 
127     private boolean isEagerInstantiationEnabled() {
128         return getConfigValueAsBoolean(getApp().getConfig()"griffon.services.eager.instantiation"false);
129     }
130 }