View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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.argeo.slc.core.execution.tasks;
17  
18  import java.io.File;
19  import java.io.FileNotFoundException;
20  import java.io.FileOutputStream;
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.Properties;
26  
27  import org.apache.commons.io.IOUtils;
28  import org.argeo.slc.SlcException;
29  import org.springframework.beans.factory.InitializingBean;
30  import org.springframework.core.io.Resource;
31  
32  /** A Java Virtual Machine process. */
33  public class JvmProcess extends SystemCall implements InitializingBean {
34  	private Properties systemProperties = new Properties();
35  	private List<Resource> classpath = new ArrayList<Resource>();
36  	private List<Resource> pBootClasspath = new ArrayList<Resource>();
37  	private Resource jvm = null;
38  	private String mainClass;
39  	private String mainJar;
40  	private List<String> jvmArgs = new ArrayList<String>();
41  	private List<String> args = new ArrayList<String>();
42  
43  	private String systemPropertiesFileProperty = null;
44  	private String systemPropertiesFileDir = null;
45  	private String systemPropertiesFileName = null;
46  
47  	public void afterPropertiesSet() throws Exception {
48  		List<Object> command = new ArrayList<Object>();
49  		if (jvm != null)
50  			command.add(asFile(jvm).getPath());
51  		else
52  			command.add("java");
53  
54  		if (pBootClasspath.size() > 0) {
55  			StringBuffer buf = new StringBuffer("-Xbootclasspath/p:");
56  			Boolean first = true;
57  			for (Resource res : pBootClasspath) {
58  				if (first)
59  					first = false;
60  				else
61  					buf.append(File.pathSeparatorChar);
62  
63  				buf.append(asFile(res));
64  			}
65  			command.add(buf.toString());
66  		}
67  
68  		for (String jvmArg : jvmArgs) {
69  			command.add(jvmArg);
70  		}
71  
72  		if (classpath.size() > 0) {
73  			command.add("-cp");
74  			StringBuffer buf = new StringBuffer("");
75  			for (Resource res : classpath) {
76  				if (buf.length() != 0)
77  					buf.append(File.pathSeparatorChar);
78  				buf.append(asFile(res));
79  			}
80  			command.add(buf.toString());
81  		}
82  
83  		if (systemPropertiesFileProperty == null) {
84  			// pass system properties as argument
85  			for (Map.Entry<Object, Object> entry : systemProperties.entrySet()) {
86  				command.add("-D" + entry.getKey() + "=" + entry.getValue());
87  			}
88  		} else {
89  			// write system properties in a file to work around OS limitations
90  			// with command line (e.g. Win XP)
91  			String dir = systemPropertiesFileDir;
92  			if (dir == null)
93  				dir = getExecDirToUse();
94  			String fileName = systemPropertiesFileName;
95  			if (fileName == null)
96  				fileName = systemPropertiesFileProperty + ".properties";
97  
98  			// Write file
99  			FileOutputStream fos = null;
100 			File file = new File(dir + File.separator + fileName);
101 			try {
102 
103 				if (!file.getParentFile().exists())
104 					file.getParentFile().mkdirs();
105 				fos = new FileOutputStream(file);
106 				systemProperties.store(fos, "Automatically generated by "
107 						+ getClass());
108 				command.add("-D" + systemPropertiesFileProperty + "="
109 						+ file.getCanonicalPath());
110 			} catch (IOException e) {
111 				throw new SlcException("Cannot write to system properties to "
112 						+ file, e);
113 			} finally {
114 				IOUtils.closeQuietly(fos);
115 			}
116 		}
117 
118 		// Program
119 		if (mainClass != null) {
120 			command.add(mainClass);
121 		} else if (mainJar != null) {
122 			command.add("-jar");
123 			command.add(mainJar);
124 		} else {
125 			throw new SlcException("No main class or jar defined");
126 		}
127 
128 		for (String arg : args) {
129 			command.add(arg);
130 		}
131 
132 		setCommand(command);
133 	}
134 
135 	protected File asFile(Resource res) {
136 		try {
137 			return res.getFile();
138 		} catch (FileNotFoundException e) {
139 			return copyToTempFile(res);
140 		} catch (IOException e) {
141 			throw new SlcException("Cannot convert resource to file", e);
142 		}
143 
144 	}
145 
146 	protected File copyToTempFile(Resource res) {
147 		File tempFile;
148 		FileOutputStream fos;
149 		try {
150 			tempFile = File.createTempFile("slcJvmProcess-", res.getFilename());
151 			tempFile.deleteOnExit();
152 			fos = new FileOutputStream(tempFile);
153 			IOUtils.copy(res.getInputStream(), fos);
154 		} catch (IOException e) {
155 			throw new SlcException("Cannot copy " + res + " to temp file.", e);
156 		}
157 		IOUtils.closeQuietly(fos);
158 		return tempFile;
159 	}
160 
161 	/** Append the argument (for chaining) */
162 	@Override
163 	public SystemCall arg(String arg) {
164 		args.add(arg);
165 		return this;
166 	}
167 
168 	/** Append the argument (for chaining) */
169 	@Override
170 	public SystemCall arg(String arg, String value) {
171 		args.add(arg);
172 		args.add(value);
173 		return this;
174 	}
175 
176 	public Properties getSystemProperties() {
177 		return systemProperties;
178 	}
179 
180 	public void setSystemProperties(Properties systemProperties) {
181 		this.systemProperties = systemProperties;
182 	}
183 
184 	public List<Resource> getClasspath() {
185 		return classpath;
186 	}
187 
188 	public void setClasspath(List<Resource> classpath) {
189 		this.classpath = classpath;
190 	}
191 
192 	public List<Resource> getPBootClasspath() {
193 		return pBootClasspath;
194 	}
195 
196 	public void setPBootClasspath(List<Resource> bootClasspath) {
197 		pBootClasspath = bootClasspath;
198 	}
199 
200 	public Resource getJvm() {
201 		return jvm;
202 	}
203 
204 	public void setJvm(Resource jvm) {
205 		this.jvm = jvm;
206 	}
207 
208 	public String getMainClass() {
209 		return mainClass;
210 	}
211 
212 	public void setMainClass(String mainClass) {
213 		this.mainClass = mainClass;
214 	}
215 
216 	public String getMainJar() {
217 		return mainJar;
218 	}
219 
220 	public void setMainJar(String mainJar) {
221 		this.mainJar = mainJar;
222 	}
223 
224 	public List<String> getJvmArgs() {
225 		return jvmArgs;
226 	}
227 
228 	public void setJvmArgs(List<String> jvmArgs) {
229 		this.jvmArgs = jvmArgs;
230 	}
231 
232 	public List<String> getArgs() {
233 		return args;
234 	}
235 
236 	public void setArgs(List<String> args) {
237 		this.args = args;
238 	}
239 
240 	public void setSystemPropertiesFileProperty(
241 			String systemPropertiesFilePropertyName) {
242 		this.systemPropertiesFileProperty = systemPropertiesFilePropertyName;
243 	}
244 
245 	public void setSystemPropertiesFileDir(String systemPropertiesFileDir) {
246 		this.systemPropertiesFileDir = systemPropertiesFileDir;
247 	}
248 
249 	public void setSystemPropertiesFileName(String systemPropertiesFileName) {
250 		this.systemPropertiesFileName = systemPropertiesFileName;
251 	}
252 
253 }