source: src/main/java/genius/core/Global.java@ 209

Last change on this file since 209 was 199, checked in by Tim Baarslag, 5 years ago

60s timeout default

File size: 17.9 KB
Line 
1package genius.core;
2
3import java.util.Calendar;
4import java.util.Date;
5import java.util.HashMap;
6import java.util.TimeZone;
7import java.util.regex.Matcher;
8
9import java.io.File;
10import java.io.IOException;
11import java.io.InputStream;
12import java.io.ObjectInputStream;
13import java.io.ObjectOutputStream;
14import java.io.OutputStream;
15import java.io.Serializable;
16import java.lang.reflect.Constructor;
17import java.lang.reflect.InvocationTargetException;
18import java.net.MalformedURLException;
19import java.net.URL;
20import java.net.URLClassLoader;
21import java.text.SimpleDateFormat;
22
23import javax.swing.JOptionPane;
24
25import genius.core.exceptions.InstantiateException;
26import genius.core.protocol.Protocol;
27import genius.core.repository.AgentRepItem;
28import genius.core.repository.ProfileRepItem;
29import genius.core.repository.ProtocolRepItem;
30import genius.core.tournament.TournamentConfiguration;
31import genius.core.tournament.VariablesAndValues.AgentParamValue;
32import genius.core.tournament.VariablesAndValues.AgentParameterVariable;
33import genius.gui.agentrepository.AgentRepositoryUI;
34
35/**
36 * Overview of global variables used throughout the application.
37 *
38 * @author dmytro
39 */
40public class Global {
41 /** Path to domain repository */
42 public static final String DOMAIN_REPOSITORY = "domainrepository.xml";
43 /** Path to agent repository */
44 public static final String AGENT_REPOSITORY = "agentrepository.xml";
45 /** Path to protocol repository */
46 public static final String PROTOCOL_REPOSITORY = "protocolrepository.xml";
47 /** Path to simulator repository */
48 public static final String SIMULATOR_REPOSITORY = "simulatorrepository.xml";
49
50 public static String logPrefix = "";
51
52 public static String logPreset = "";
53
54 private final static String WRONG_NAME = "wrong name: ";
55
56 private static final Date loadDate = Calendar.getInstance().getTime();
57
58 public static String getCurrentTime() {
59 Calendar cal = Calendar.getInstance(TimeZone.getDefault());
60 String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
61 java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(DATE_FORMAT);
62 /*
63 * on some JDK, the default TimeZone is wrong we must set the TimeZone
64 * manually.
65 */
66 sdf.setTimeZone(TimeZone.getDefault());
67
68 return sdf.format(cal.getTime());
69 }
70
71 public static String getFileNameWithoutExtension(String fileName) {
72
73 File tmpFile = new File(fileName);
74 tmpFile.getName();
75 int whereDot = tmpFile.getName().lastIndexOf('.');
76 if (0 < whereDot && whereDot <= tmpFile.getName().length() - 2) {
77 return tmpFile.getName().substring(0, whereDot);
78 }
79 return "";
80 }
81
82 public static Class<Protocol> getProtocolClass(ProtocolRepItem protRepItem) throws Exception {
83 java.lang.ClassLoader loader = Global.class.getClassLoader();// ClassLoader.getSystemClassLoader();
84 Class<Protocol> klass = (Class<Protocol>) loader.loadClass(protRepItem.getClassPath());
85 return klass;
86 }
87
88 public static Protocol createProtocolInstance(ProtocolRepItem protRepItem, AgentRepItem[] agentRepItems,
89 ProfileRepItem[] profileRepItems, HashMap<AgentParameterVariable, AgentParamValue>[] agentParams)
90 throws InstantiateException {
91 try {
92 Protocol ns;
93
94 java.lang.ClassLoader loader = ClassLoader.getSystemClassLoader();
95
96 Class klass;
97 klass = loader.loadClass(protRepItem.getClassPath());
98 Class[] paramTypes = { AgentRepItem[].class, ProfileRepItem[].class, HashMap[].class, int.class };
99
100 Constructor cons = klass.getConstructor(paramTypes);
101
102 System.out.println("Found the constructor: " + cons);
103
104 Object[] args = { agentRepItems, profileRepItems, agentParams, 1 };
105
106 Object theObject = cons.newInstance(args);
107 ns = (Protocol) (theObject);
108 return ns;
109 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException
110 | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
111 throw new InstantiateException("Failed to create instance", e);
112 }
113 }
114
115 /**
116 * Load an object from a given path. If it's a .class file, figure out the
117 * correct class path and use that. If it's not a .class file, we assume
118 * it's already in the existing classpath and load it with the standard
119 * class loader.
120 *
121 *
122 * <p>
123 * we can't properly typecheck here. Generics fail as we have type erasure,
124 * and casting to the given type does NOTHING. So we leave this a general
125 * object and leave it to the caller to do the type checking.
126 *
127 * @param path
128 * This can be either a class name or filename.<br>
129 * <ul>
130 * <li>class name like"agents.anac.y2010.AgentFSEGA.AgentFSEGA".
131 * In this case the agent must be already on the JVM's classpath
132 * otherwise the agent will not be found. <br>
133 * <li>a full path, eg
134 * "/Volumes/documents/NegoWorkspace3/NegotiatorGUI/src/agents/anac/y2010/AgentFSEGA/AgentFSEGA.java"
135 * . In this case, we can figure out the class path ourselves,
136 * but the ref is system dependent (backslashes on windows) and
137 * might be absolute path.
138 * </ul>
139 *
140 * @return the {@link Object} in the given file
141 * @throws InstantiateException
142 * if path can not be loaded as object.
143 */
144 public static Object loadObject(String path) throws InstantiateException {
145 try {
146 if (path.endsWith(".class")) {
147 return loadClassFromFile(new File(path));
148 } else {
149 java.lang.ClassLoader loaderA = Global.class.getClassLoader();
150 return (loaderA.loadClass(path).newInstance());
151 }
152 } catch (Exception e) {
153 throw new InstantiateException("failed to load class from " + path, e);
154 }
155 }
156
157 /**
158 * Runtime type-checked version of {@link #loadObject(String)}.
159 *
160 * @param path
161 * @param expectedClass
162 * the class type that the loaded object must extend.
163 * @return loaded object.
164 * @throws InstantiateException
165 */
166
167 public static Object loadObject(String path, Class<?> expectedClass) throws InstantiateException {
168 Object object = loadObject(path);
169 if (!object.getClass().isAssignableFrom(expectedClass)) {
170 throw new InstantiateException("Failed to load class " + path + ": It is not extending " + expectedClass);
171 }
172 return object;
173 }
174
175 /**
176 * Deserializes an object and casts it to the given type.
177 *
178 * @param is
179 * the input stream containing serialized object.
180 * @return object contained in given stream.
181 * @throws IOException
182 * if file can not be found
183 * @throws ClassNotFoundException
184 * if class in the object can't be found
185 * @throws ClassCastException
186 * if not of given class type
187 */
188 @SuppressWarnings("unchecked")
189 public static <T> T deserializeObject(InputStream is) throws ClassNotFoundException, IOException {
190 Object obj = new ObjectInputStream(is).readObject();
191 return (T) obj;
192 }
193
194 /**
195 * Serialize a serializable object to a outputstream.
196 *
197 * @param outputStream
198 * the stream to write to
199 * @param object
200 * the object to store
201 * @throws IOException
202 */
203 public static void serializeObject(OutputStream outputStream, Serializable object) throws IOException {
204 new ObjectOutputStream(outputStream).writeObject(object);
205 }
206
207 /**
208 * Load a file as a class. It 'reverse engineers' the correct path by first
209 * just trying to load the file. Assuming the file exists, we probably get
210 * an error that we then use to determine the correct base directory.
211 *
212 * @param file
213 * the object to be loaded. Filename should end with ".class".
214 * @return the object contained in the file.
215 * @throws ClassNotFoundException
216 * @throws IllegalAccessException
217 * @throws InstantiationException
218 * @throws MalformedURLException
219 */
220 public static Object loadClassFromFile(File file)
221 throws MalformedURLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
222 String className = file.getName();
223 if (!className.endsWith(".class")) {
224 throw new IllegalArgumentException("file " + file + " is not a .class file");
225 }
226 // strip the trailing '.class' from the string.
227 className = className.substring(0, className.length() - 6);
228 File packageDir = file.getParentFile();
229 if (packageDir == null) {
230 packageDir = new File(".");
231 }
232
233 try {
234 return loadClassfile(className, packageDir);
235 } catch (NoClassDefFoundError e) {
236 /**
237 * We try to get the correct name from the error message. Err msg ~
238 * "SimpleAgent (wrong name: agents/SimpleAgent)"
239 */
240 String errormsg = e.getMessage();
241 // "wrong name" is what we expect.
242 int i = errormsg.indexOf(WRONG_NAME);
243 if (i == -1) {
244 throw e; // unknown error. We can't handle...
245 }
246 // remove leading and trailing stuff. We now have
247 // 'agents.SimpleAgent'
248 String correctName = errormsg.substring(i + WRONG_NAME.length(), errormsg.length() - 1).replaceAll("/",
249 ".");
250
251 // Check that file is in correct directory path
252 // we need quoteReplacement because on Windows "\" will be treated
253 // in special way by replaceAll. #906
254 String expectedPath = File.separator
255 + correctName.replaceAll("\\.", Matcher.quoteReplacement(File.separator)) + ".class";
256 if (!(file.getAbsolutePath().endsWith(expectedPath))) {
257 throw new NoClassDefFoundError("file " + file + "\nis not in the correct directory structure, "
258 + "\nas its class is " + correctName + "." + "\nEnsure the file is in ..." + expectedPath);
259 }
260
261 // number of dots is number of times we need to go to parent
262 // directory. We are already in the directory of the agent, so -1.
263 for (int up = 0; up < correctName.split("\\.").length - 1; up++) {
264 // since we checked the path already, parents must exist.
265 packageDir = packageDir.getParentFile();
266 }
267 return loadClassfile(correctName, packageDir);
268 }
269 }
270
271 /**
272 * Try to load an object with given classnamem from a given packagedir
273 *
274 * @param classname
275 * the exact class name, eg "examplepackage.example"
276 * @param packagedir
277 * the root directory of the classes to be loaded. If you add the
278 * given classname to it, you should end up at the correct
279 * location for the class file. Eg,
280 * "/Volumes/Users/wouter/Desktop/genius/".
281 * @return the loaded class object.
282 * @throws MalformedURLException
283 * @throws InstantiationException
284 * @throws IllegalAccessException
285 * @throws ClassNotFoundException
286 */
287 private static Object loadClassfile(String classname, File packagedir)
288 throws MalformedURLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
289 try {
290 java.lang.ClassLoader loader = AgentRepositoryUI.class.getClassLoader();
291 URLClassLoader urlLoader = new URLClassLoader(new URL[] { packagedir.toURI().toURL() }, loader);
292 Class<?> theclass;
293 theclass = urlLoader.loadClass(classname);
294 return (Object) theclass.newInstance();
295 } catch (ClassNotFoundException e) {
296 // improve on the standard error message...
297 throw new ClassNotFoundException(
298 "agent " + classname + " is not available in directory '" + packagedir + "'", e);
299 }
300
301 }
302
303 /**
304 * Load an agent using the given classname/filename. DOES NOT call
305 * {@link Agent#parseStrategyParameters(String)}
306 *
307 * @param path
308 * This can be either a class name or filename.<br>
309 * <ul>
310 * <li>class name like"agents.anac.y2010.AgentFSEGA.AgentFSEGA".
311 * In this case the agent must be already on the JVM's classpath
312 * otherwise the agent will not be found.
313 * <li>a full path, eg
314 * "/Volumes/documents/NegoWorkspace3/NegotiatorGUI/src/agents/anac/y2010/AgentFSEGA/AgentFSEGA.java"
315 * . In this case, we can figure out the class path ourselves,
316 * but the ref is system dependent (backslashes on windows) and
317 * might be absolute path.
318 * </ul>
319 * @return instantiated agent ready to use.
320 * @throws InstantiateException
321 * if object can't be loaded
322 */
323 public static Agent loadAgent(String path) throws InstantiateException {
324 return (Agent) loadObject(path);
325 }
326
327 /**
328 * load agent and then set the parameters. See {@link #loadAgent(String)}
329 *
330 * @param agentClassName
331 * @param variables
332 * the variables to use, as string (eg, "time=0.9;e=1.0").
333 * @return the agent contained in the given class name, and using the given
334 * variables.
335 * @throws InstantiateException
336 * if class can't be loaded
337 */
338 public static Agent loadAgent(String agentClassName, String variables) throws InstantiateException {
339
340 Agent agent = loadAgent(agentClassName);
341
342 // CHECK why do we catch failures in parseStrategyParameters?
343 try {
344 agent.parseStrategyParameters(variables);
345 } catch (Exception e) {
346 e.printStackTrace();
347 }
348 return agent;
349
350 }
351
352 /**
353 * Gives a useful agent name.
354 */
355 public static String getAgentDescription(Agent agent) {
356 if (agent == null)
357 return "";
358 String agentDescription = agent.getName();
359 if (agentDescription == null || "Agent A".equals(agentDescription) || "Agent B".equals(agentDescription))
360 agentDescription = agent.getClass().getSimpleName();
361
362 return agentDescription;
363 }
364
365 /**
366 * Show a dialog to the user, explaining the exception that was raised while
367 * loading file fc. Typically this is used in combination with
368 * {@link #loadObject(String)} and associates. Also dumps a copy of the full
369 * stacktrace to the console, to help us debugging #906
370 *
371 * @param fc
372 * file that was attempted to be loaded
373 * @param e
374 * the exception that was raised
375 */
376 public static void showLoadError(File fc, Throwable e) {
377 e.printStackTrace();
378 if (e instanceof ClassNotFoundException) {
379 showLoadError("No class found at " + fc, e);
380 } else if (e instanceof InstantiationException) {
381 // happens when object instantiated is interface or abstract
382 showLoadError(
383 "Class cannot be instantiated. Reasons may be that there is no constructor without arguments, "
384 + "or the class is abstract or an interface.",
385 e);
386 } else if (e instanceof IllegalAccessException) {
387 showLoadError("Missing constructor without arguments", e);
388 } else if (e instanceof NoClassDefFoundError) {
389 showLoadError("Errors in loaded class.", e);
390 } else if (e instanceof ClassCastException) {
391 showLoadError("The loaded class seems to be of the wrong type. ", e);
392 } else if (e instanceof IllegalArgumentException) {
393 showLoadError("The given file can not be used.", e);
394 } else if (e instanceof IOException) {
395 showLoadError("The file can not be read.", e);
396 } else {
397 showLoadError("Something went wrong loading the file", e);
398 }
399 }
400
401 /*
402 * show error while loading agent file. Also show the detail message.
403 */
404 private static void showLoadError(String text, Throwable e) {
405 String message = e.getMessage();
406 if (message == null) {
407 message = "";
408 }
409
410 JOptionPane.showMessageDialog(null, text + "\n" + message, "Load error", 0);
411 }
412
413 /**
414 * @return the agentsLoader
415 */
416 private static String getLoadDate() {
417 // (2) createFrom our "formatter" (our custom format)
418 SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH.mm.ss");
419
420 // (3) createFrom a new String in the format we want
421 String name = formatter.format(loadDate);
422
423 return name;
424 }
425
426 public static String getOutcomesFileName() {
427 if (!logPreset.equals("")) {
428 return logPreset;
429 }
430 if (!logPrefix.equals(""))
431 return logPrefix + "log.xml";
432
433 return "log/" + getLoadDate() + getPostFix() + ".xml";
434 }
435
436 public static String getDistributedOutcomesFileName() {
437 return "log/DT-" + getLoadDate() + getPostFix() + ".xml";
438 }
439
440 public static String getTournamentOutcomeFileName() {
441 return "log/TM-" + getLoadDate() + getPostFix() + ".xml";
442 }
443
444 public static String getExtensiveOutcomesFileName() {
445 if (!logPrefix.equals(""))
446 return logPrefix + "extensive_log.xml";
447 return "log/extensive " + getLoadDate() + getPostFix() + ".xml";
448 }
449
450 public static String getOQMOutcomesFileName() {
451 return "log/OQM " + getLoadDate() + getPostFix() + ".csv";
452 }
453
454 private static String getPostFix() {
455 String postFix = "";
456 if (TournamentConfiguration.getBooleanOption("appendModeAndDeadline", false)) {
457 String mode = "time";
458 if (TournamentConfiguration.getBooleanOption("protocolMode", false)) {
459 mode = "rounds";
460 }
461 postFix += "_" + mode + "_" + TournamentConfiguration.getIntegerOption("deadline", 60);
462 }
463 return postFix;
464 }
465
466 /**
467 * @param classname
468 * @return Removes trailing ".class" from string if it is there. In absolute
469 * paths, the \ and / are replaced with '.' and we do as if that is
470 * a fully specified class path (it isn't but it gives at least some
471 * 'short name')
472 */
473 public static String nameOfClass(String classname1) {
474 // FIXME can we use class.forName.getShortName?
475 String classname = classname1.replaceAll("\\W", ".");
476 if (classname.endsWith(".class")) {
477 classname = classname.substring(0, classname.length() - 6);
478 }
479 return classname;
480 }
481
482 /**
483 * @param classname
484 * @return Removes trailing ".class" from string if it is there. If there is
485 * no "." in the remainder, the remainder is returned. Otherwise,
486 * the string after the last "." in the remainder is returned. In
487 * absolute paths, the \ and / are replaced with '.' and we do as if
488 * that is a fully specified class path (it isn't but it gives at
489 * least some 'short name')
490 */
491 public static String shortNameOfClass(String classname1) {
492 String classname = nameOfClass(classname1);
493 if (!(classname.contains(".")))
494 return classname;
495 return classname.substring(classname.lastIndexOf(".") + 1);
496 }
497
498}
Note: See TracBrowser for help on using the repository browser.