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

Last change on this file since 127 was 127, checked in by Wouter Pasman, 6 years ago

#41 ROLL BACK of rev.126 . So this version is equal to rev. 125

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