00001 package cast.clients;
00002
00003 import java.net.Inet4Address;
00004 import java.net.InetAddress;
00005 import java.net.NetworkInterface;
00006 import java.net.SocketException;
00007 import java.util.ArrayList;
00008 import java.util.Enumeration;
00009 import java.util.HashMap;
00010 import java.util.HashSet;
00011 import java.util.List;
00012 import java.util.Map;
00013
00014 import Ice.Application;
00015 import Ice.Communicator;
00016 import Ice.Identity;
00017 import Ice.ObjectAdapter;
00018 import Ice.ObjectNotExistException;
00019 import Ice.ObjectPrx;
00020 import cast.ComponentCreationException;
00021 import cast.cdl.CASTRELEASESTRING;
00022 import cast.cdl.CPPSERVERPORT;
00023 import cast.cdl.ComponentDescription;
00024 import cast.cdl.ComponentLanguage;
00025 import cast.cdl.JAVACLIENTSERVERPORT;
00026 import cast.cdl.JAVASERVERPORT;
00027 import cast.cdl.PYTHONSERVERPORT;
00028 import cast.configuration.ArchitectureConfigurationException;
00029 import cast.configuration.CASTConfigParser;
00030 import cast.configuration.SubarchitectureConfiguration;
00031 import cast.configuration.SubarchitectureProxies;
00032 import cast.core.CASTUtils;
00033 import cast.interfaces.CASTComponentPrx;
00034 import cast.interfaces.ComponentManagerPrx;
00035 import cast.interfaces.ComponentManagerPrxHelper;
00036 import cast.interfaces.ManagedComponentPrx;
00037 import cast.interfaces.TaskManagerPrx;
00038 import cast.interfaces.TimeServerPrx;
00039 import cast.interfaces.TimeServerPrxHelper;
00040 import cast.interfaces.WorkingMemoryAttachedComponentPrx;
00041 import cast.interfaces.WorkingMemoryPrx;
00042 import cast.server.CASTComponentManager;
00043
00044 public class CASTClient extends Application {
00045
00046
00047
00048
00049
00050
00051
00055 private static void showArgs() {
00056 System.err
00057 .println("CASTProcessServer arguments: -f config file REQUIRED");
00058 }
00059
00060 private ArrayList<CASTComponentPrx> m_components;
00061 private HashMap<String, ComponentDescription> m_componentDescriptions;
00062
00063 @Override
00064 public int run(String[] args) {
00065
00066 System.out.println("CoSy Architecture Schema Toolkit. Release: "
00067 + CASTRELEASESTRING.value);
00068
00069 String configFile = null;
00070
00071 try {
00072 for (int i = 0; i < args.length; i++) {
00073 if (args[i].equals("-f")) {
00074 configFile = args[i + 1];
00075 }
00076 }
00077 } catch (ArrayIndexOutOfBoundsException e) {
00078 showArgs();
00079 return 1;
00080 }
00081
00082 if (configFile == null) {
00083 showArgs();
00084 return 1;
00085 }
00086
00087
00088
00089 try {
00090 CASTConfigParser.parseConfigFile(configFile);
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 ComponentManagerPrx manager = getComponentManager();
00108 HashMap<String, TimeServerPrx> timeServers = getTimeServers();
00109
00110
00111
00112 for (TimeServerPrx ts : timeServers.values()) {
00113 ts.reset();
00114 }
00115
00116
00117
00118
00119 storeDescriptions(manager);
00120
00121 ArrayList<SubarchitectureProxies> subarchs = getProxies(
00122 CASTConfigParser.m_subarchitectures, manager, timeServers);
00123
00124 m_components = new ArrayList<CASTComponentPrx>();
00125
00126
00127 for (SubarchitectureProxies subarch : subarchs) {
00128
00129
00130 connectSubarchitecture(subarch, m_components);
00131
00132
00133 for (SubarchitectureProxies otherSubarch : subarchs) {
00134 if (otherSubarch != subarch) {
00135 subarch.getWorkingMemory().setWorkingMemory(
00136 otherSubarch.getWorkingMemory(),
00137 otherSubarch.getID());
00138 }
00139 }
00140 }
00141
00142
00143 assert (CASTConfigParser.m_extras != null);
00144 for (ComponentDescription cd : CASTConfigParser.m_extras) {
00145 int compPort = -1;
00146
00147 if (cd.language == ComponentLanguage.JAVA) {
00148 compPort = JAVASERVERPORT.value;
00149 } else if (cd.language == ComponentLanguage.PYTHON) {
00150 compPort = PYTHONSERVERPORT.value;
00151 } else if (cd.language == ComponentLanguage.CPP) {
00152 compPort = CPPSERVERPORT.value;
00153 } else {
00154 throw new RuntimeException("Unknown language value: "
00155 + cd.language);
00156 }
00157
00158 try {
00159
00160 CASTComponentPrx prx = CASTUtils.createCASTComponent(
00161 new Identity(cd.componentName, cd.className),
00162 communicator(), cd.hostName, compPort);
00163 assert prx != null : "created proxy is null";
00164 prx.setComponentManager(manager);
00165
00166 TimeServerPrx ts = timeServers.get(cd.hostName);
00167 assert (ts != null);
00168 prx.setTimeServer(ts);
00169 prx.configure(cd.configuration);
00170 m_components.add(prx);
00171
00172 } catch (ComponentCreationException e) {
00173 e = new ComponentCreationException("While creating a "
00174 + cd.language
00175 + " component the following error occurred: "
00176 + e.message);
00177 throw e;
00178 }
00179
00180 }
00181
00182 startComponents();
00183
00184 runComponents();
00185
00186
00187
00188
00189
00190
00191
00192
00193 setInterruptHook(new Thread(new Runnable() {
00194 public void run() {
00195 stopComponents();
00196 destroyComponents();
00197 }
00198 }));
00199
00200 communicator().waitForShutdown();
00201
00202 return 0;
00203
00204 } catch (ArchitectureConfigurationException e) {
00205 e.printStackTrace();
00206 }
00207
00208
00209
00210
00211 catch (ComponentCreationException e) {
00212 e.printStackTrace();
00213 }
00214
00215 return 1;
00216
00217 }
00218
00223 private void storeDescriptions(ComponentManagerPrx _manager) {
00224 m_componentDescriptions = new HashMap<String, ComponentDescription>();
00225 for (SubarchitectureConfiguration sa : CASTConfigParser.m_subarchitectures) {
00226 ArrayList<ComponentDescription> descriptions = sa.getDescriptions();
00227 for (ComponentDescription cd : descriptions) {
00228 m_componentDescriptions.put(cd.componentName, cd);
00229 _manager.addComponentDescription(cd);
00230 }
00231 }
00232 for (ComponentDescription cd : CASTConfigParser.m_extras) {
00233 m_componentDescriptions.put(cd.componentName, cd);
00234 _manager.addComponentDescription(cd);
00235 }
00236 }
00237
00238 private HashMap<String, TimeServerPrx> getTimeServers() {
00239 return getTimeServers(getHosts());
00240 }
00241
00242 private HashMap<String, TimeServerPrx> getTimeServers(HashSet<String> _hosts) {
00243
00244 HashMap<String, TimeServerPrx> servers = new HashMap<String, TimeServerPrx>();
00245 ArrayList<String> leftovers = new ArrayList<String>(_hosts.size());
00246
00247 for (String host : _hosts) {
00248 try {
00249 TimeServerPrx ts = getTimeServer(host, CPPSERVERPORT.value);
00250 servers.put(host, ts);
00251 } catch (RuntimeException e) {
00252 e.printStackTrace();
00253
00254 leftovers.add(host);
00255 }
00256 }
00257
00258 if (servers.isEmpty()) {
00259 throw new RuntimeException(
00260 "Unable to find any time servers anywhere. Try running the C++ component server somewhere.");
00261 }
00262
00263 TimeServerPrx fallback = servers.values().iterator().next();
00264
00265 for (String host : leftovers) {
00266 servers.put(host, fallback);
00267 }
00268
00269 return servers;
00270 }
00271
00280 private ComponentManagerPrx getComponentManager() {
00281 String javaHost = getAJavaHost(CASTConfigParser.m_subarchitectures);
00282
00283
00284 ComponentManagerPrx manager;
00285
00286 if (javaHost == null) {
00287
00288
00289
00290 String anyHost = null;
00291 if (!CASTConfigParser.m_subarchitectures.isEmpty()) {
00292 anyHost = CASTConfigParser.m_subarchitectures.get(0)
00293 .getWorkingMemoryConfig().hostName;
00294 } else if (!CASTConfigParser.m_extras.isEmpty()) {
00295 anyHost = CASTConfigParser.m_extras.get(0).hostName;
00296 }
00297
00298 if (anyHost == null) {
00299 throw new RuntimeException(
00300 "Your configuration file contains no components");
00301 }
00302
00303 try {
00304
00305 manager = getComponentManager(anyHost, JAVASERVERPORT.value);
00306 } catch (ObjectNotExistException e) {
00307
00308 setupServer();
00309 manager = getComponentManager(getExternalInterface(),
00310 JAVACLIENTSERVERPORT.value);
00311 }
00312 } else {
00313 manager = getComponentManager(javaHost, JAVASERVERPORT.value);
00314 }
00315 assert (manager != null);
00316 return manager;
00317 }
00318
00319 private void runComponents() {
00320
00321 int max = m_components.size();
00322 int count = 1;
00323
00324 for (CASTComponentPrx cmp : m_components) {
00325
00326
00327 System.out.println("[running [" + count++ + "/" + max + "]: "
00328 + cmp.getID() + "]");
00329
00330
00331
00332 cmp.run();
00333 }
00334 }
00335
00336 private void startComponents() {
00337
00338
00339 int max = m_components.size();
00340 int count = 1;
00341 for (CASTComponentPrx cmp : m_components) {
00342
00343
00344 System.out.println("[starting [" + count++ + "/" + max + "]: "
00345 + cmp.getID() + "]");
00346 cmp.start();
00347 }
00348 }
00349
00350 private void stopComponents() {
00351 int max = m_components.size();
00352 int count = 1;
00353
00354
00355 for (CASTComponentPrx cmp : m_components) {
00356
00357 System.out.println("[stopping [" + count++ + "/" + max + "]: "
00358 + cmp.getID() + "]");
00359 cmp.stop();
00360 }
00361
00362 }
00363
00364 private void destroyComponents() {
00365 int max = m_components.size();
00366 int count = 1;
00367
00368
00369 for (CASTComponentPrx cmp : m_components) {
00370
00371 String id = cmp.getID();
00372 System.out.println("[destroying [" + count++ + "/" + max + "]: "
00373 + id + "]");
00374
00375
00376
00377
00378
00379
00380 cmp.destroy();
00381 }
00382
00383 }
00384
00385 private String getExternalInterface() {
00386
00387 try {
00388 Enumeration<NetworkInterface> networkInterfaces = NetworkInterface
00389 .getNetworkInterfaces();
00390
00391 while (networkInterfaces.hasMoreElements()) {
00392 NetworkInterface netface = (NetworkInterface) networkInterfaces
00393 .nextElement();
00394
00395 System.out.println("Net interface: " + netface.getName());
00396
00397 Enumeration<?> e2 = netface.getInetAddresses();
00398
00399 while (e2.hasMoreElements()) {
00400 InetAddress ip = (InetAddress) e2.nextElement();
00401
00402 if (ip instanceof Inet4Address) {
00403
00404 System.out.println("-------");
00405
00406
00407
00408
00409
00410
00411 System.out.println(ip.getHostAddress());
00412
00413 System.out.println("-------");
00414
00415 if (!ip.isLinkLocalAddress() && !ip.isLoopbackAddress()) {
00416 return ip.getHostAddress();
00417 }
00418
00419 }
00420 }
00421 }
00422 } catch (SocketException e) {
00423 e.printStackTrace();
00424 }
00425
00426 System.out
00427 .println("Unable to find a suitable network address to connect to for component manager, using localhost instead");
00428 return "localhost";
00429 }
00430
00431 private TimeServerPrx getTimeServer(String _host, int _port) {
00432
00433 Identity id = new Identity("TimeServer", "TimeServer");
00434 ObjectPrx base = communicator().stringToProxy(
00435 communicator().identityToString(id) + ":default -h " + _host
00436 + " -p " + _port);
00437 if (base == null) {
00438 throw new RuntimeException(
00439 "Cannot create proxy to CPP TimeServer on " + _host);
00440 }
00441
00442 TimeServerPrx prx = TimeServerPrxHelper.checkedCast(base);
00443 assert (prx != null);
00444 return prx;
00445 }
00446
00447 private ComponentManagerPrx getComponentManager(String _host, int _port) {
00448
00449
00450
00451 Identity id = new Identity("comp.man", CASTComponentManager.class
00452 .getCanonicalName());
00453
00454 ObjectPrx base = communicator().stringToProxy(
00455 communicator().identityToString(id) + ":default -h " + _host
00456 + " -p " + _port);
00457
00458 if (base == null) {
00459 throw new RuntimeException(
00460 "Cannot create proxy to CPP ComponentServer on " + _host);
00461 }
00462
00463 ComponentManagerPrx prx = ComponentManagerPrxHelper.checkedCast(base);
00464 assert (prx != null);
00465 return prx;
00466 }
00467
00468 private void setupServer() {
00469
00470 Communicator ic = communicator();
00471 ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints(
00472 "ComponentServer2", "default -p " + JAVACLIENTSERVERPORT.value);
00473
00474 Identity manid = new Identity("comp.man", CASTComponentManager.class
00475 .getCanonicalName());
00476
00477 adapter.add(new CASTComponentManager(), manid);
00478
00479 adapter.activate();
00480
00481
00482
00483
00484
00485
00486
00487
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 private HashSet<String> getHosts() {
00505 HashSet<String> hosts = getHosts(CASTConfigParser.m_subarchitectures);
00506
00507 for (ComponentDescription cd : CASTConfigParser.m_extras) {
00508 hosts.add(cd.hostName);
00509 }
00510
00511 return hosts;
00512 }
00513
00514 private HashSet<String> getHosts(
00515 ArrayList<SubarchitectureConfiguration> _m_subarchitectures) {
00516 HashSet<String> hosts = new HashSet<String>();
00517 for (SubarchitectureConfiguration sa : _m_subarchitectures) {
00518 hosts.addAll(sa.getHosts());
00519 }
00520 return hosts;
00521 }
00522
00523 private void connectSubarchitecture(SubarchitectureProxies _subarch,
00524 List<CASTComponentPrx> _components) {
00525
00526
00527 WorkingMemoryPrx wm = _subarch.getWorkingMemory();
00528 TaskManagerPrx tm = _subarch.getTaskManager();
00529
00530 _components.add(wm);
00531 _components.add(tm);
00532
00533 for (ManagedComponentPrx prx : _subarch.getManagedComponents()) {
00534
00535 assert (prx != null);
00536 assert (wm != null);
00537 tm.addManagedComponent(prx);
00538 prx.setTaskManager(tm);
00539 prx.setWorkingMemory(wm);
00540 wm.addReader(prx);
00541 _components.add(prx);
00542 }
00543
00544 for (WorkingMemoryAttachedComponentPrx prx : _subarch
00545 .getUnmanagedComponents()) {
00546
00547 assert (prx != null);
00548 assert (wm != null);
00549
00550 prx.setWorkingMemory(wm);
00551 _components.add(prx);
00552 }
00553 }
00554
00555 private String getAJavaHost(
00556 ArrayList<SubarchitectureConfiguration> _m_subarchitectures) {
00557 for (SubarchitectureConfiguration subarch : _m_subarchitectures) {
00558 if (subarch.getAJavaServer() != null) {
00559 return subarch.getAJavaServer();
00560 }
00561 }
00562 return null;
00563 }
00564
00565 private ArrayList<SubarchitectureProxies> getProxies(
00566 ArrayList<SubarchitectureConfiguration> _m_subarchitectures,
00567 ComponentManagerPrx _man, Map<String, TimeServerPrx> _timeServers)
00568 throws ComponentCreationException {
00569 ArrayList<SubarchitectureProxies> proxies = new ArrayList<SubarchitectureProxies>();
00570 for (SubarchitectureConfiguration subarch : _m_subarchitectures) {
00571 proxies.add(new SubarchitectureProxies(subarch, _man, _timeServers,
00572 communicator()));
00573 }
00574 return proxies;
00575 }
00576
00580 public static void main(String[] args) {
00581
00582 CASTClient app = new CASTClient();
00583 int status = app.main("CASTClient", args);
00584 System.exit(status);
00585 }
00586
00587 }