001 /*
002 * Copyright 2004-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 griffon.util;
018
019 import groovy.lang.Closure;
020 import groovy.lang.GroovyObjectSupport;
021 import groovy.lang.MissingMethodException;
022
023 import java.util.HashMap;
024 import java.util.Locale;
025 import java.util.Map;
026
027 /**
028 * An enum that represents the current environment
029 *
030 * @author Graeme Rocher (Grails 1.1)
031 */
032 public enum Environment {
033 /** The development environment */
034 DEVELOPMENT,
035
036 /** The production environment */
037 PRODUCTION,
038
039 /** The test environment */
040 TEST,
041
042 /** A custom environment */
043 CUSTOM;
044
045 /**
046 * Constant used to resolve the environment via System.getProperty(Environment.KEY)
047 */
048 public static final String KEY = "griffon.env";
049
050 /**
051 * Constants that indicates whether this GriffonApplication is running in the default environment
052 */
053 public static final String DEFAULT = "griffon.env.default";
054 private static final String PRODUCTION_ENV_SHORT_NAME = "prod";
055 private static final String DEVELOPMENT_ENVIRONMENT_SHORT_NAME = "dev";
056
057 private static final String TEST_ENVIRONMENT_SHORT_NAME = "test";
058 private static Map<String, String> envNameMappings = new HashMap<String, String>() {{
059 put(DEVELOPMENT_ENVIRONMENT_SHORT_NAME, Environment.DEVELOPMENT.getName());
060 put(PRODUCTION_ENV_SHORT_NAME, Environment.PRODUCTION.getName());
061 put(TEST_ENVIRONMENT_SHORT_NAME, Environment.TEST.getName());
062 }};
063
064 /**
065 * Returns the current environment which is typcally either DEVELOPMENT, PRODUCTION or TEST.
066 * For custom environments CUSTOM type is returned.
067 *
068 * @return The current environment.
069 */
070 public static Environment getCurrent() {
071 String envName = System.getProperty(Environment.KEY);
072 Metadata metadata = Metadata.getCurrent();
073 if (metadata!=null && isBlank(envName)) {
074 envName = metadata.getEnvironment();
075 }
076
077 if (isBlank(envName)) {
078 return DEVELOPMENT;
079 }
080
081 Environment env = getEnvironment(envName);
082 if (env == null) {
083 try {
084 env = Environment.valueOf(envName.toUpperCase());
085 }
086 catch (IllegalArgumentException e) {
087 // ignore
088 }
089 }
090 if (env == null) {
091 env = Environment.CUSTOM;
092 env.setName(envName);
093 }
094 return env;
095 }
096
097 /**
098 * @see #getCurrent()
099 * @return the current environment
100 */
101 public static Environment getCurrentEnvironment() {
102 return getCurrent();
103 }
104
105 /**
106 * @return Return true if the environment has been set as a System property
107 */
108 public static boolean isSystemSet() {
109 return System.getProperty(KEY) != null;
110 }
111
112 /**
113 * Returns the environment for the given short name
114 * @param shortName The short name
115 * @return The Environment or null if not known
116 */
117 public static Environment getEnvironment(String shortName) {
118 final String envName = envNameMappings.get(shortName);
119 if (envName != null) {
120 return Environment.valueOf(envName.toUpperCase());
121 }
122 return null;
123 }
124
125 /**
126 * Takes an environment specific DSL block like:
127 *
128 * <code>
129 * environments {
130 * development {}
131 * production {}
132 * }
133 * </code>
134 *
135 * And returns the closure that relates to the current environment
136 *
137 * @param closure The top level closure
138 * @return The environment specific block or null if non exists
139 */
140 public static Closure getEnvironmentSpecificBlock(Closure closure) {
141 final Environment env = getCurrent();
142 return getEnvironmentSpecificBlock(env, closure);
143 }
144
145 /**
146 * Takes an environment specific DSL block like:
147 *
148 * <code>
149 * environments {
150 * development {}
151 * production {}
152 * }
153 * </code>
154 *
155 * And returns the closure that relates to the specified
156 *
157 * @param env The environment to use
158 * @param closure The top level closure
159 * @return The environment specific block or null if non exists
160 */
161 public static Closure getEnvironmentSpecificBlock(Environment env, Closure closure) {
162 if (closure == null) {
163 return null;
164 }
165
166 final EnvironmentBlockEvaluator evaluator = evaluateEnvironmentSpecificBlock(env, closure);
167 return evaluator.getCallable();
168 }
169
170 /**
171 * Takes an environment specific DSL block like:
172 *
173 * <code>
174 * environments {
175 * development {}
176 * production {}
177 * }
178 * </code>
179 *
180 * And executes the closure that relates to the current environment
181 *
182 * @param closure The top level closure
183 * @return The result of the closure execution
184 */
185 public static Object executeForCurrentEnvironment(Closure closure) {
186 final Environment env = getCurrent();
187 return executeForEnvironment(env, closure);
188 }
189
190 /**
191 * Takes an environment specific DSL block like:
192 *
193 * <code>
194 * environments {
195 * development {}
196 * production {}
197 * }
198 * </code>
199 *
200 * And executes the closure that relates to the specified environment
201 *
202 * @param env The environment to use
203 * @param closure The top level closure
204 * @return The result of the closure execution
205 */
206 public static Object executeForEnvironment(Environment env, Closure closure) {
207 if (closure == null) {
208 return null;
209 }
210
211 final EnvironmentBlockEvaluator evaluator = evaluateEnvironmentSpecificBlock(env, closure);
212 return evaluator.execute();
213 }
214
215 private static EnvironmentBlockEvaluator evaluateEnvironmentSpecificBlock(Environment environment, Closure closure) {
216 final EnvironmentBlockEvaluator evaluator = new EnvironmentBlockEvaluator(environment);
217 closure.setDelegate(evaluator);
218 closure.call();
219 return evaluator;
220 }
221
222 private static class EnvironmentBlockEvaluator extends GroovyObjectSupport {
223 private Environment current;
224 private Closure callable;
225
226 public Closure getCallable() {
227 return callable;
228 }
229
230 Object execute() {
231 return callable == null ? null : callable.call();
232 }
233
234 private EnvironmentBlockEvaluator(Environment e) {
235 this.current = e;
236 }
237
238 @SuppressWarnings("unused")
239 public void environments(Closure c) {
240 if (c != null) {
241 c.setDelegate(this);
242 c.call();
243 }
244 }
245 @SuppressWarnings("unused")
246 public void production(Closure c) {
247 if (current == Environment.PRODUCTION) {
248 this.callable = c;
249 }
250 }
251 @SuppressWarnings("unused")
252 public void development(Closure c) {
253 if (current == Environment.DEVELOPMENT) {
254 this.callable = c;
255 }
256 }
257 @SuppressWarnings("unused")
258 public void test(Closure c) {
259 if (current == Environment.TEST) {
260 this.callable = c;
261 }
262 }
263
264 @SuppressWarnings("unused")
265 public Object methodMissing(String name, Object args) {
266 Object[] argsArray = (Object[])args;
267 if (args != null && argsArray.length > 0 && (argsArray[0] instanceof Closure)) {
268 if (current == Environment.CUSTOM && current.getName().equals(name)) {
269 this.callable = (Closure) argsArray[0];
270 }
271 return null;
272 }
273 throw new MissingMethodException(name, Environment.class, argsArray);
274 }
275 }
276
277 private static boolean isBlank(String value) {
278 return value == null || value.trim().length() == 0;
279 }
280
281
282 private String name;
283
284 /**
285 * @return The name of the environment
286 */
287 public String getName() {
288 if(name == null) {
289 return this.toString().toLowerCase(Locale.getDefault());
290 }
291 return name;
292 }
293
294 public void setName(String name) {
295 this.name = name;
296 }
297 }
|