You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TestServer.java 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*******************************************************************************
  2. * Copyright (c) 2006,2017 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *******************************************************************************/
  8. package org.aspectj.testing.server;
  9. import java.io.File;
  10. import java.io.FileInputStream;
  11. import java.io.IOException;
  12. import java.lang.reflect.InvocationTargetException;
  13. import java.lang.reflect.Method;
  14. import java.net.URL;
  15. import java.net.URLClassLoader;
  16. import java.util.ArrayList;
  17. import java.util.Enumeration;
  18. import java.util.HashMap;
  19. import java.util.List;
  20. import java.util.Map;
  21. import java.util.Properties;
  22. import java.util.StringTokenizer;
  23. /**
  24. * @author Matthew Webster
  25. * @author Andy Clement
  26. */
  27. public class TestServer implements Runnable {
  28. private static final boolean debug = Boolean.getBoolean("org.aspectj.testing.server.debug");
  29. // AspectJ project root folder nameing pattern, case-insensitive (i.e. org.aspectj, AspectJ)
  30. protected static final String REGEX_PROJECT_ROOT_FOLDER = "(?i)(org[.])?aspectj";
  31. private boolean exitOnError = true;
  32. private File workingDirectory;
  33. private ClassLoader rootLoader;
  34. private Map<String,ClassLoader> loaders = new HashMap<>();
  35. private String mainClass = "UnknownClass";
  36. private String mainLoader = "UnknownLoader";
  37. public void initialize () throws IOException {
  38. createRootLoader();
  39. loadConfiguration();
  40. }
  41. private void loadConfiguration () throws IOException {
  42. File file = new File(workingDirectory,"server.properties");
  43. Properties props = new Properties();
  44. FileInputStream in = new FileInputStream(file);
  45. props.load(in);
  46. in.close();
  47. Enumeration<?> enu = props.propertyNames();
  48. while (enu.hasMoreElements()) {
  49. String key = (String)enu.nextElement();
  50. if (key.startsWith("loader.")) {
  51. createLoader(props.getProperty(key));
  52. }
  53. else if (key.equals("main")) {
  54. StringTokenizer st = new StringTokenizer(props.getProperty(key),",");
  55. mainClass = st.nextToken();
  56. mainLoader = st.nextToken();
  57. }
  58. }
  59. }
  60. private void createLoader (String property) throws IOException {
  61. ClassLoader parent = rootLoader;
  62. StringTokenizer st = new StringTokenizer(property,",");
  63. String name = st.nextToken();
  64. String classpath = st.nextToken();
  65. if (debug) System.err.println("Creating loader "+name+" with classpath "+classpath);
  66. if (st.hasMoreTokens()) {
  67. String parentName = st.nextToken();
  68. parent = loaders.get(parentName);
  69. if (parent == null) error("No such loader: " + parentName);
  70. }
  71. List<URL> urlList = new ArrayList<>();
  72. st = new StringTokenizer(classpath,";");
  73. while (st.hasMoreTokens()) {
  74. String fileName = st.nextToken();
  75. File file = new File(workingDirectory,fileName).getCanonicalFile();
  76. if (!file.exists()) error("Missing or invalid file: " + file.getPath());
  77. URL url = file.toURI().toURL();
  78. urlList.add(url);
  79. }
  80. URL[] urls = new URL[urlList.size()];
  81. urlList.toArray(urls);
  82. ClassLoader loader = new URLClassLoader(urls, parent);
  83. if (debug) System.err.println("? TestServer.createLoader() loader=" + loader + ", name='" + name + "', urls=" + urlList + ", parent=" + parent);
  84. loaders.put(name,loader);
  85. }
  86. private void createRootLoader() throws IOException {
  87. List<URL> urlList = new ArrayList<>();
  88. // Sandbox
  89. urlList.add(workingDirectory.getCanonicalFile().toURI().toURL());
  90. File projectRootFolder = findProjectRootFolder();
  91. urlList.add(new File(projectRootFolder,"runtime/target/classes").toURI().toURL());
  92. // urlList.add(new File(projectRootFolder,"aspectjrt/target/classes").toURI().toURL());
  93. // urlList.add(new File(projectRootFolder,"aspectj5rt/target/classes").toURI().toURL());
  94. URL[] urls = new URL[urlList.size()];
  95. urlList.toArray(urls);
  96. ClassLoader parent = getClass().getClassLoader().getParent();
  97. rootLoader = new URLClassLoader(urls,parent);
  98. if (debug) System.err.println("? TestServer.createRootLoader() loader=" + rootLoader + ", urlList=" + urlList + ", parent=" + parent);
  99. }
  100. // Make protected in order to at least make this part of the code testable -> TestServerTest
  101. protected File findProjectRootFolder() throws IOException {
  102. // Find the AspectJ project root folder
  103. File currentFolder = new File(".").getCanonicalFile();
  104. while (currentFolder != null && !currentFolder.getName().matches(REGEX_PROJECT_ROOT_FOLDER)) {
  105. currentFolder = currentFolder.getParentFile();
  106. }
  107. if (currentFolder == null) {
  108. error(
  109. "Unable to locate project root folder matching regex '" + REGEX_PROJECT_ROOT_FOLDER +
  110. "' in " + new File(".").getCanonicalPath()
  111. );
  112. }
  113. return currentFolder;
  114. }
  115. public void setExitOntError (boolean b) {
  116. exitOnError = b;
  117. }
  118. public void setWorkingDirectory (String name) {
  119. workingDirectory = new File(name);
  120. if (!workingDirectory.exists()) error("Missing or invalid working directory: " + workingDirectory.getPath());
  121. }
  122. public static void main(String[] args) throws Exception {
  123. System.out.println("Starting ...");
  124. TestServer server = new TestServer();
  125. server.setWorkingDirectory(args[0]);
  126. server.initialize();
  127. Thread thread = new Thread(server,"application");
  128. thread.start();
  129. thread.join();
  130. System.out.println("Stopping ...");
  131. }
  132. public void run() {
  133. System.out.println("Running " + mainClass);
  134. runClass(mainClass,loaders.get(mainLoader));
  135. }
  136. private void runClass (String className, ClassLoader classLoader) {
  137. try {
  138. Class<?> clazz = Class.forName(className,false,classLoader);
  139. invokeMain(clazz,new String[] {});
  140. }
  141. catch (ClassNotFoundException ex) {
  142. ex.printStackTrace();
  143. error(ex.toString());
  144. }
  145. }
  146. public void invokeMain (Class<?> clazz, String[] args)
  147. {
  148. Class<?>[] paramTypes = new Class[1];
  149. paramTypes[0] = args.getClass();
  150. try {
  151. Method method = clazz.getDeclaredMethod("main",paramTypes);
  152. Object[] params = new Object[1];
  153. params[0] = args;
  154. method.invoke(null,params);
  155. }
  156. catch (InvocationTargetException ex) {
  157. Throwable th = ex.getTargetException();
  158. th.printStackTrace();
  159. error(th.toString());
  160. }
  161. catch (Throwable th) {
  162. th.printStackTrace();
  163. error(th.toString());
  164. }
  165. }
  166. private void error (String message) {
  167. System.out.println(message);
  168. // FIXME:
  169. // This is horrible: Why not just throw an exception? And if we exit, why with exit code 0?
  170. // It basically makes the tests useless because they might log errors without checking any conditions.
  171. if (exitOnError) System.exit(0);
  172. }
  173. }