00001 /* 00002 * ################################################################ 00003 * 00004 * ProActive: The Java(TM) library for Parallel, Distributed, 00005 * Concurrent computing with Security and Mobility 00006 * 00007 * Copyright (C) 1997-2007 INRIA/University of Nice-Sophia Antipolis 00008 * Contact: proactive@objectweb.org 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with this library; if not, write to the Free Software 00022 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 * USA 00024 * 00025 * Initial developer(s): The ProActive Team 00026 * http://www.inria.fr/oasis/ProActive/contacts.html 00027 * Contributor(s): 00028 * 00029 * ################################################################ 00030 */ 00031 package org.objectweb.proactive.core.process; 00032 00033 import java.io.File; 00034 import java.io.IOException; 00035 import java.io.Serializable; 00036 import java.util.ArrayList; 00037 00038 import org.apache.log4j.Logger; 00039 import org.objectweb.proactive.core.util.RemoteProcessMessageLogger; 00040 import org.objectweb.proactive.core.util.log.Loggers; 00041 import org.objectweb.proactive.core.util.log.ProActiveLogger; 00042 00043 00067 public class JVMProcessImpl extends AbstractExternalProcess 00068 implements JVMProcess, Serializable { 00069 static Logger logger = ProActiveLogger.getLogger(Loggers.DEPLOYMENT_PROCESS); 00070 private static final String FILE_SEPARATOR = System.getProperty( 00071 "file.separator"); 00072 00073 //private final static String POLICY_FILE = "proactive.java.policy"; 00074 private final static String POLICY_OPTION = " -Djava.security.policy="; 00075 private final static String LOG4J_OPTION = " -Dlog4j.configuration=file:"; 00076 00077 //private final static String LOG4J_FILE = "proactive-log4j"; 00078 public final static String DEFAULT_CLASSPATH = convertClasspathToAbsolutePath(System.getProperty( 00079 "java.class.path")); 00080 public final static String DEFAULT_JAVAPATH = System.getProperty( 00081 "java.home") + FILE_SEPARATOR + "bin" + FILE_SEPARATOR + "java"; 00082 public static String DEFAULT_POLICY_FILE = System.getProperty( 00083 "java.security.policy"); 00084 public static String DEFAULT_LOG4J_FILE = System.getProperty( 00085 "log4j.configuration"); 00086 00087 static { 00088 if (DEFAULT_POLICY_FILE != null) { 00089 DEFAULT_POLICY_FILE = getAbsolutePath(DEFAULT_POLICY_FILE); 00090 } 00091 if (DEFAULT_LOG4J_FILE != null) { 00092 DEFAULT_LOG4J_FILE = getAbsolutePath(DEFAULT_LOG4J_FILE); 00093 } 00094 } 00095 00096 public final static String DEFAULT_CLASSNAME = "org.objectweb.proactive.core.node.StartNode"; 00097 public final static String DEFAULT_JVMPARAMETERS = ""; 00098 protected String classpath = DEFAULT_CLASSPATH; 00099 protected String bootClasspath; 00100 protected String javaPath = DEFAULT_JAVAPATH; 00101 protected String policyFile = DEFAULT_POLICY_FILE; 00102 protected String log4jFile = DEFAULT_LOG4J_FILE; 00103 protected String classname = DEFAULT_CLASSNAME; 00104 00105 // protected String parameters = DEFAULT_JVMPARAMETERS; 00106 // protected String jvmParameters; 00107 protected StringBuffer parameters = new StringBuffer(); 00108 protected StringBuffer jvmParameters = new StringBuffer(); 00109 00110 //this array will be used to know which options have been modified in case 00111 //this process extends anothe jvmprocess in the descriptor 00112 protected ArrayList<String> modifiedOptions; 00113 00119 protected boolean overwrite = false; 00120 00121 // How many paths leading to a JVMProcessImpl have been encountered 00122 static private int groupID = 0; 00123 00124 // 00125 // -- CONSTRUCTORS ----------------------------------------------- 00126 // 00127 00132 public JVMProcessImpl() { 00133 this.modifiedOptions = new ArrayList<String>(); 00134 } 00135 00140 public JVMProcessImpl(RemoteProcessMessageLogger messageLogger) { 00141 super(messageLogger); 00142 this.modifiedOptions = new ArrayList<String>(); 00143 } 00144 00150 public JVMProcessImpl(RemoteProcessMessageLogger inputMessageLogger, 00151 RemoteProcessMessageLogger errorMessageLogger) { 00152 super(inputMessageLogger, errorMessageLogger); 00153 this.modifiedOptions = new ArrayList<String>(); 00154 } 00155 00156 // 00157 // -- PUBLIC METHODS ----------------------------------------------- 00158 // 00159 public static void main(String[] args) { 00160 try { 00161 JVMProcessImpl rsh = new JVMProcessImpl(new StandardOutputMessageLogger()); 00162 rsh.setClassname("org.objectweb.proactive.core.node.StartNode"); 00163 rsh.setParameters(args[0]); 00164 rsh.startProcess(); 00165 } catch (Exception e) { 00166 e.printStackTrace(); 00167 } 00168 } 00169 00170 // 00171 // -- implements JVMProcess ----------------------------------------------- 00172 // 00173 public String getClasspath() { 00174 return classpath; 00175 } 00176 00177 public void setClasspath(String classpath) { 00178 checkStarted(); 00179 modifiedOptions.add("classpath"); 00180 this.classpath = classpath; 00181 } 00182 00183 public void setBootClasspath(String bootClasspath) { 00184 checkStarted(); 00185 modifiedOptions.add("bootClasspath"); 00186 this.bootClasspath = bootClasspath; 00187 } 00188 00189 public String getBootClasspath() { 00190 return bootClasspath; 00191 } 00192 00193 public String getJavaPath() { 00194 return javaPath; 00195 } 00196 00197 public void setJavaPath(String javaPath) { 00198 checkStarted(); 00199 if (javaPath == null) { 00200 throw new NullPointerException(); 00201 } 00202 modifiedOptions.add("javaPath"); 00203 this.javaPath = javaPath; 00204 } 00205 00206 public String getPolicyFile() { 00207 return policyFile; 00208 } 00209 00210 public void setPolicyFile(String policyFile) { 00211 checkStarted(); 00212 modifiedOptions.add("policyFile"); 00213 this.policyFile = policyFile; 00214 } 00215 00216 public String getLog4jFile() { 00217 return log4jFile; 00218 } 00219 00220 public void setLog4jFile(String log4jFile) { 00221 modifiedOptions.add("log4jFile"); 00222 this.log4jFile = log4jFile; 00223 } 00224 00225 public String getClassname() { 00226 return classname; 00227 } 00228 00229 public void setClassname(String classname) { 00230 checkStarted(); 00231 this.classname = classname; 00232 } 00233 00234 public String getParameters() { 00235 return parameters.toString(); 00236 } 00237 00238 public void resetParameters() { 00239 this.parameters = new StringBuffer(); 00240 } 00241 00242 public void setParameters(String parameters) { 00243 checkStarted(); 00244 this.parameters.append(parameters + " "); 00245 } 00246 00247 public void setJvmOptions(String string) { 00248 checkStarted(); 00249 jvmParameters.append(string + " "); 00250 } 00251 00252 public String getJvmOptions() { 00253 return jvmParameters.toString(); 00254 } 00255 00259 public String getProcessId() { 00260 return "jvm"; 00261 } 00262 00266 public int getNodeNumber() { 00267 return 1; 00268 } 00269 00273 public UniversalProcess getFinalProcess() { 00274 return this; 00275 } 00276 00277 public void setOverwrite(boolean overwrite) { 00278 this.overwrite = overwrite; 00279 } 00280 00281 public void setExtendedJVM(JVMProcessImpl jvmProcess) { 00282 changeSettings(jvmProcess); 00283 } 00284 00285 // 00286 // -- PROTECTED METHODS ----------------------------------------------- 00287 // 00288 protected String buildCommand() { 00289 return buildJavaCommand(); 00290 } 00291 00292 protected String buildJavaCommand() { 00293 StringBuffer javaCommand = new StringBuffer(); 00294 00295 // append java command 00296 if (javaPath == null) { 00297 javaCommand.append("java"); 00298 } else { 00299 javaCommand.append(checkWhiteSpaces(javaPath)); 00300 } 00301 00302 if (bootClasspath != null) { 00303 javaCommand.append(" -Xbootclasspath:"); 00304 javaCommand.append(checkWhiteSpaces(bootClasspath)); 00305 javaCommand.append(" "); 00306 } 00307 00308 // append jvmParameters 00309 if (jvmParameters != null) { 00310 javaCommand.append(" " + jvmParameters); 00311 } 00312 00313 // append classpath 00314 if ((classpath != null) && (classpath.length() > 0)) { 00315 javaCommand.append(" -cp "); 00316 javaCommand.append(checkWhiteSpaces(classpath)); 00317 } 00318 00319 // append policy option 00320 if (policyFile != null) { 00321 javaCommand.append(POLICY_OPTION); 00322 javaCommand.append(checkWhiteSpaces(policyFile)); 00323 } 00324 00325 // append log4j option 00326 if (log4jFile != null) { 00327 javaCommand.append(LOG4J_OPTION); 00328 javaCommand.append(checkWhiteSpaces(log4jFile)); 00329 } 00330 00331 // dynamic classloading through runtimes 00332 // check system classloader when ProActive.jar is used (where by default : "proactive.classloader" == "disable") 00333 if ("enable".equals(System.getProperty("proactive.classloader")) || 00334 "org.objectweb.proactive.core.classloader.ProActiveClassLoader".equals( 00335 System.getProperty("java.system.class.loader"))) { 00336 javaCommand.append( 00337 " -Djava.system.class.loader=org.objectweb.proactive.core.classloader.ProActiveClassLoader "); 00338 // the following allows the deserializing of streams that were annotated with rmi utilities 00339 javaCommand.append( 00340 " -Djava.rmi.server.RMIClassLoaderSpi=org.objectweb.proactive.core.classloader.ProActiveRMIClassLoaderSpi"); 00341 // to avoid clashes due to multiple classloader, we initiate the 00342 // configuration of log4j ourselves 00343 // (see StartRuntime.main) 00344 javaCommand.append(" -Dlog4j.defaultInitOverride=true"); 00345 } 00346 00347 // append proactive policy File 00348 // if (securityFile != null) { 00349 // javaCommand.append(PROACTIVE_POLICYFILE_OPTION); 00350 // javaCommand.append(securityFile); 00351 // }// else if (System.getProperty("proactive.runtime.security") != null) { 00352 // javaCommand.append(PROACTIVE_POLICYFILE_OPTION); 00353 // javaCommand.append(System.getProperty("proactive.runtime.security")); 00354 // } 00355 // append classname 00356 javaCommand.append(" "); 00357 javaCommand.append(classname); 00358 if (logger.isDebugEnabled()) { 00359 logger.debug("JVMProcessImpl.buildJavaCommand() Parameters " + 00360 parameters); 00361 } 00362 if (parameters != null) { 00363 javaCommand.append(" "); 00364 javaCommand.append(parameters); 00365 } 00366 if (logger.isDebugEnabled()) { 00367 logger.debug(javaCommand.toString()); 00368 } 00369 if (logger.isDebugEnabled()) { 00370 logger.debug(javaCommand.toString() + "\n"); 00371 } 00372 if (logger.isDebugEnabled()) { 00373 logger.debug("JVMProcessImpl.buildJavaCommand() " + javaCommand); 00374 } 00375 return javaCommand.toString(); 00376 } 00377 00378 protected void changeSettings(JVMProcess jvmProcess) { 00379 if (!modifiedOptions.contains("classpath")) { 00380 this.classpath = jvmProcess.getClasspath(); 00381 } 00382 if (!modifiedOptions.contains("bootClasspath")) { 00383 this.bootClasspath = jvmProcess.getBootClasspath(); 00384 } 00385 if (!modifiedOptions.contains("javaPath")) { 00386 this.javaPath = jvmProcess.getJavaPath(); 00387 } 00388 if (!modifiedOptions.contains("policyFile")) { 00389 this.policyFile = jvmProcess.getPolicyFile(); 00390 } 00391 if (!modifiedOptions.contains("log4jFile")) { 00392 this.log4jFile = jvmProcess.getLog4jFile(); 00393 } 00394 if (!overwrite) { 00395 setJvmOptions(jvmProcess.getJvmOptions()); 00396 } 00397 } 00398 00399 // 00400 // -- PRIVATE METHODS ----------------------------------------------- 00401 // 00402 private static String convertClasspathToAbsolutePath(String classpath) { 00403 StringBuffer absoluteClasspath = new StringBuffer(); 00404 String pathSeparator = System.getProperty("path.separator"); 00405 java.util.StringTokenizer st = new java.util.StringTokenizer(classpath, 00406 pathSeparator); 00407 while (st.hasMoreTokens()) { 00408 absoluteClasspath.append(new java.io.File(st.nextToken()).getAbsolutePath()); 00409 absoluteClasspath.append(pathSeparator); 00410 } 00411 return absoluteClasspath.substring(0, absoluteClasspath.length() - 1); 00412 } 00413 00414 private static String getAbsolutePath(String path) { 00415 if (path.startsWith("file:")) { 00416 //remove file part to build absolute path 00417 path = path.substring(5); 00418 } 00419 try { 00420 return new File(path).getCanonicalPath(); 00421 } catch (IOException e) { 00422 logger.error(e.getMessage()); 00423 return path; 00424 } 00425 } 00426 00427 private String checkWhiteSpaces(String path) { 00428 if (!path.startsWith("\"") && !path.startsWith("'")) { 00429 //if path does not start with " or ' we can check if there is whitespaces, 00430 //if it does, we let the user handle its path 00431 if (path.indexOf(" ") > 0) { 00432 //if whitespaces, we surround all the path with double quotes 00433 path = "\"" + path + "\""; 00434 } 00435 } 00436 return path; 00437 } 00438 00439 public int getNewGroupId() { 00440 return groupID++; 00441 } 00442 }