DefaultEbeanServerFactory.java
001 /*
002  * Copyright 2014-2017 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.ebean;
017 
018 import com.avaje.ebean.EbeanServer;
019 import com.avaje.ebean.config.ServerConfig;
020 import griffon.core.GriffonApplication;
021 import griffon.core.injection.Injector;
022 import griffon.plugins.datasource.DataSourceFactory;
023 import griffon.plugins.datasource.DataSourceStorage;
024 import griffon.plugins.ebean.EbeanBootstrap;
025 import griffon.plugins.ebean.EbeanServerFactory;
026 import griffon.util.GriffonClassUtils;
027 import org.codehaus.griffon.runtime.core.storage.AbstractObjectFactory;
028 
029 import javax.annotation.Nonnull;
030 import javax.inject.Inject;
031 import javax.inject.Named;
032 import javax.sql.DataSource;
033 import java.util.Arrays;
034 import java.util.LinkedHashSet;
035 import java.util.Map;
036 import java.util.Set;
037 
038 import static griffon.util.ConfigUtils.getConfigValue;
039 import static griffon.util.GriffonNameUtils.requireNonBlank;
040 import static java.util.Arrays.asList;
041 import static java.util.Objects.requireNonNull;
042 
043 /**
044  @author Andres Almiray
045  */
046 public class DefaultEbeanServerFactory extends AbstractObjectFactory<EbeanServer> implements EbeanServerFactory {
047     private static final String ERROR_SESSION_FACTORY_NAME_BLANK = "Argument 'ebeanServerName' must not be blank";
048     private final Set<String> ebeanServerNames = new LinkedHashSet<>();
049 
050     private static final String[] CUSTOM_PROPERTIES = {
051         "connect_on_startup",
052         "schema"
053     };
054 
055     @Inject
056     private DataSourceFactory dataSourceFactory;
057 
058     @Inject
059     private DataSourceStorage dataSourceStorage;
060 
061     @Inject
062     private Injector injector;
063 
064     @Inject
065     public DefaultEbeanServerFactory(@Nonnull @Named("ebean"griffon.core.Configuration configuration, @Nonnull GriffonApplication application) {
066         super(configuration, application);
067         ebeanServerNames.add(KEY_DEFAULT);
068 
069         if (configuration.containsKey(getPluralKey())) {
070             Map<String, Object> ebeanFactories = (Map<String, Object>configuration.get(getPluralKey());
071             ebeanServerNames.addAll(ebeanFactories.keySet());
072         }
073     }
074 
075     @Nonnull
076     @Override
077     public Set<String> getEbeanServerNames() {
078         return ebeanServerNames;
079     }
080 
081     @Nonnull
082     @Override
083     public Map<String, Object> getConfigurationFor(@Nonnull String ebeanServerName) {
084         requireNonBlank(ebeanServerName, ERROR_SESSION_FACTORY_NAME_BLANK);
085         return narrowConfig(ebeanServerName);
086     }
087 
088     @Nonnull
089     @Override
090     protected String getSingleKey() {
091         return "ebeanServer";
092     }
093 
094     @Nonnull
095     @Override
096     protected String getPluralKey() {
097         return "ebeanServers";
098     }
099 
100     @Nonnull
101     @Override
102     public EbeanServer create(@Nonnull String name) {
103         Map<String, Object> config = narrowConfig(name);
104         event("EbeanConnectStart", asList(name, config));
105 
106         EbeanServer ebeanserver = createEbeanServer(config, name);
107         for (Object o : injector.getInstances(EbeanBootstrap.class)) {
108             ((EbeanBootstrapo).init(name, ebeanserver);
109         }
110 
111         event("EbeanConnectEnd", asList(name, config, ebeanserver));
112         return ebeanserver;
113     }
114 
115     @Override
116     public void destroy(@Nonnull String name, @Nonnull EbeanServer instance) {
117         requireNonNull(instance, "Argument 'instance' must not be null");
118         Map<String, Object> config = narrowConfig(name);
119         event("EbeanDisconnectStart", asList(name, config, instance));
120 
121         for (Object o : injector.getInstances(EbeanBootstrap.class)) {
122             ((EbeanBootstrapo).destroy(name, instance);
123         }
124 
125         closeDataSource(name);
126 
127         event("EbeanDisconnectEnd", asList(name, config));
128     }
129 
130     @Nonnull
131 
132     protected EbeanServer createEbeanServer(@Nonnull Map<String, Object> config, @Nonnull String ebeanServerName) {
133         String schemaCreate = getConfigValue(config, "schema""create");
134         boolean ddl = "create".equalsIgnoreCase(schemaCreate);
135 
136         ServerConfig serverConfig = new ServerConfig();
137         serverConfig.setName(ebeanServerName);
138         serverConfig.setRegister(true);
139         serverConfig.setDefaultServer(KEY_DEFAULT.equals(ebeanServerName));
140         serverConfig.setDdlGenerate(ddl);
141         serverConfig.setDdlRun(ddl);
142         serverConfig.setDataSource(getDataSource(ebeanServerName));
143 
144         for (Map.Entry<String, Object> e : config.entrySet()) {
145             if (Arrays.binarySearch(CUSTOM_PROPERTIES, e.getKey()) != -1) {
146                 continue;
147             }
148             GriffonClassUtils.setPropertyValue(serverConfig, e.getKey(), e.getValue());
149         }
150 
151         return com.avaje.ebean.EbeanServerFactory.create(serverConfig);
152     }
153 
154     protected void closeDataSource(@Nonnull String dataSourceName) {
155         DataSource dataSource = dataSourceStorage.get(dataSourceName);
156         if (dataSource != null) {
157             dataSourceFactory.destroy(dataSourceName, dataSource);
158             dataSourceStorage.remove(dataSourceName);
159         }
160     }
161 
162     @Nonnull
163     protected DataSource getDataSource(@Nonnull String dataSourceName) {
164         DataSource dataSource = dataSourceStorage.get(dataSourceName);
165         if (dataSource == null) {
166             dataSource = dataSourceFactory.create(dataSourceName);
167             dataSourceStorage.set(dataSourceName, dataSource);
168         }
169         return dataSource;
170     }
171 }