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 = (GriffonService) griffonClass.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 }
|