View Javadoc

1   /**
2    * Copyright 2010-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.common.util.execute;
17  
18  import java.io.File;
19  import java.util.Properties;
20  
21  import org.kuali.common.util.LocationUtils;
22  import org.kuali.common.util.PropertyUtils;
23  import org.slf4j.Logger;
24  import org.slf4j.LoggerFactory;
25  import org.springframework.util.Assert;
26  
27  public class RunOnceExecutable implements Executable {
28  
29  	private static final Logger logger = LoggerFactory.getLogger(RunOnceExecutable.class);
30  
31  	Executable executable;
32  	File propertiesFile;
33  	String property;
34  	String encoding;
35  
36  	@Override
37  	public void execute() {
38  		Assert.notNull(propertiesFile);
39  		Assert.notNull(property);
40  		Assert.notNull(executable);
41  
42  		if (!propertiesFile.exists()) {
43  			logger.info("Skipping execution. File does not exist - [{}]", LocationUtils.getCanonicalPath(propertiesFile));
44  			return;
45  		}
46  
47  		logger.info("Examining run once property [{}] in [{}]", property, LocationUtils.getCanonicalPath(propertiesFile));
48  		Properties properties = PropertyUtils.load(propertiesFile, encoding);
49  		ExecutionMode mode = getExecutionMode(properties, property);
50  		boolean runonce = isRunOnce(mode);
51  		if (runonce) {
52  			logger.info("{}={}", property, mode);
53  			// Make sure we have the ability to successfully store updated properties back to the file
54  			if (!isAlways(mode)) {
55  				setState(properties, property, ExecutionMode.INPROGRESS);
56  			}
57  			try {
58  				// Invoke execute now that we have successfully transitioned things to INPROGRESS
59  				executable.execute();
60  				// There is always a chance that the executable finishes correctly and we encounter some kind of
61  				// issue just storing the properties back to the file. This should be pretty rare considering
62  				// we were able to successfully store the properties just prior to the executable commencing
63  				if (!isAlways(mode)) {
64  					setState(properties, property, ExecutionMode.COMPLETED);
65  				}
66  			} catch (Exception e) {
67  				if (!isAlways(mode)) {
68  					setState(properties, property, ExecutionMode.FAILED);
69  				}
70  				throw new IllegalStateException("Unexpected execution error", e);
71  			}
72  		} else {
73  			logger.info("Skipping execution - [{}={}]", property, mode);
74  		}
75  	}
76  
77  	protected boolean isAlways(ExecutionMode mode) {
78  		return ExecutionMode.ALWAYS.equals(mode);
79  	}
80  
81  	protected boolean isRunOnce(ExecutionMode mode) {
82  		if (ExecutionMode.RUNONCE.equals(mode)) {
83  			return true;
84  		}
85  		if (isAlways(mode)) {
86  			return true;
87  		}
88  		return ExecutionMode.TRUE.equals(mode);
89  	}
90  
91  	protected ExecutionMode getExecutionMode(Properties properties, String key) {
92  		String value = properties.getProperty(property);
93  		if (value == null) {
94  			return ExecutionMode.NULL;
95  		} else {
96  			return ExecutionMode.valueOf(value.toUpperCase());
97  		}
98  
99  	}
100 
101 	protected void setState(Properties properties, String key, ExecutionMode mode) {
102 		logger.info("{}={}", key, mode);
103 		properties.setProperty(property, mode.name());
104 		PropertyUtils.store(properties, propertiesFile, encoding);
105 	}
106 
107 	public Executable getExecutable() {
108 		return executable;
109 	}
110 
111 	public void setExecutable(Executable executable) {
112 		this.executable = executable;
113 	}
114 
115 	public File getPropertiesFile() {
116 		return propertiesFile;
117 	}
118 
119 	public void setPropertiesFile(File propertiesFile) {
120 		this.propertiesFile = propertiesFile;
121 	}
122 
123 	public String getProperty() {
124 		return property;
125 	}
126 
127 	public void setProperty(String property) {
128 		this.property = property;
129 	}
130 
131 	public String getEncoding() {
132 		return encoding;
133 	}
134 
135 	public void setEncoding(String encoding) {
136 		this.encoding = encoding;
137 	}
138 }