| 1 | package de.uka.ipd.sdq.simucomframework.simulationdock; |
| 2 | |
| 3 | import java.io.File; |
| 4 | import java.io.FileOutputStream; |
| 5 | import java.io.IOException; |
| 6 | import java.util.Hashtable; |
| 7 | import java.util.Map; |
| 8 | |
| 9 | import org.apache.log4j.ConsoleAppender; |
| 10 | import org.apache.log4j.Logger; |
| 11 | import org.apache.log4j.PatternLayout; |
| 12 | import org.eclipse.emf.ecore.util.EcoreUtil; |
| 13 | import org.osgi.framework.Bundle; |
| 14 | import org.osgi.framework.BundleContext; |
| 15 | import org.osgi.framework.BundleException; |
| 16 | import org.osgi.framework.ServiceReference; |
| 17 | import org.osgi.service.event.Event; |
| 18 | import org.osgi.service.event.EventAdmin; |
| 19 | import org.osgi.util.tracker.ServiceTracker; |
| 20 | |
| 21 | import de.uka.ipd.sdq.simucomframework.AbstractMain; |
| 22 | import de.uka.ipd.sdq.simucomframework.model.SimuComModel; |
| 23 | import de.uka.ipd.sdq.simucomframework.simucomstatus.SimuComStatus; |
| 24 | import de.uka.ipd.sdq.simulation.AbstractSimulationConfig; |
| 25 | import de.uka.ipd.sdq.simulation.ISimulationControl; |
| 26 | import de.uka.ipd.sdq.simulation.SimulationResult; |
| 27 | |
| 28 | public class SimulationDockServiceImpl implements SimulationDockService { |
| 29 | |
| 30 | public static final String SIMTIME_TOTAL = "SIMTIMETOTAL"; |
| 31 | |
| 32 | protected static Logger logger = |
| 33 | Logger.getLogger(SimulationDockServiceImpl.class.getName()); |
| 34 | |
| 35 | private BundleContext context; |
| 36 | private String myID = EcoreUtil.generateUUID(); |
| 37 | private ServiceTracker service; |
| 38 | private ServiceTracker eventService; |
| 39 | private EventAdmin eventAdmin; |
| 40 | |
| 41 | private DebugObserver debugObserver; |
| 42 | |
| 43 | public SimulationDockServiceImpl(BundleContext context) { |
| 44 | this.context = context; |
| 45 | ServiceReference eventServiceRef = context.getServiceReference(EventAdmin.class.getName()); |
| 46 | eventService = new ServiceTracker(context,eventServiceRef,null); |
| 47 | eventService.open(); |
| 48 | eventAdmin = (EventAdmin)eventService.getService(); |
| 49 | |
| 50 | logger.addAppender(new ConsoleAppender(new PatternLayout(),ConsoleAppender.SYSTEM_OUT)); |
| 51 | logger.debug("Simulation Dock Started"); |
| 52 | } |
| 53 | |
| 54 | @Override |
| 55 | protected void finalize() throws Throwable { |
| 56 | eventService.close(); |
| 57 | super.finalize(); |
| 58 | } |
| 59 | |
| 60 | public void load(AbstractSimulationConfig config, byte[] simulationBundle, boolean isRemoteRun) { |
| 61 | sendEvent("de/uka/ipd/sdq/simucomframework/simucomdock/DOCK_BUSY"); |
| 62 | |
| 63 | if (config.isDebug()) { |
| 64 | this.debugObserver = new DebugObserver(eventAdmin,this); |
| 65 | } else { |
| 66 | this.debugObserver = null; |
| 67 | } |
| 68 | |
| 69 | ensurePluginLoaded(context, "org.eclipse.equinox.event"); |
| 70 | unloadPluginIfExists(context, "de.uka.ipd.sdq.codegen.simucominstance"); |
| 71 | |
| 72 | try { |
| 73 | loadBundle(config, simulationBundle, eventAdmin, isRemoteRun); |
| 74 | } catch (Exception e) { |
| 75 | unloadPluginIfExists(context, "de.uka.ipd.sdq.codegen.simucominstance"); |
| 76 | sendEvent("de/uka/ipd/sdq/simucomframework/simucomdock/DOCK_IDLE"); |
| 77 | throw new RuntimeException("Simulation preparation failed",e); |
| 78 | } finally { |
| 79 | |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | |
| 84 | public void simulate(AbstractSimulationConfig config, byte[] simulationBundle, boolean isRemoteRun) { |
| 85 | |
| 86 | try { |
| 87 | simulateBundle(config, simulationBundle, eventAdmin, isRemoteRun); |
| 88 | } catch (Exception e) { |
| 89 | throw new RuntimeException("Simulation failed",e); |
| 90 | } finally { |
| 91 | unloadPluginIfExists(context, "de.uka.ipd.sdq.codegen.simucominstance"); |
| 92 | sendEvent("de/uka/ipd/sdq/simucomframework/simucomdock/DOCK_IDLE"); |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | Bundle simulationBundleRef = null; |
| 97 | private DispatchingSimulationObserver simulationObservers = null; |
| 98 | long simulationStartTime = -1; |
| 99 | |
| 100 | private void loadBundle(AbstractSimulationConfig config, |
| 101 | byte[] simulationBundle, EventAdmin eventAdmin, boolean isRemoteRun) { |
| 102 | String bundleLocation = persistBundleInTempDir(simulationBundle); |
| 103 | try { |
| 104 | simulationBundleRef = context.installBundle(new File(bundleLocation).toURI().toString()); |
| 105 | simulationBundleRef.start(); |
| 106 | |
| 107 | } catch (BundleException e) { |
| 108 | throw new RuntimeException("OSGi failure",e); |
| 109 | } |
| 110 | ServiceReference[] services = simulationBundleRef.getRegisteredServices(); |
| 111 | assert services.length == 1; |
| 112 | |
| 113 | service = new ServiceTracker(context,services[0],null); |
| 114 | service.open(); |
| 115 | try { |
| 116 | simulationObservers = new DispatchingSimulationObserver(); |
| 117 | simulationObservers.addObserver(new SimulationProgressReportingObserver(config,eventAdmin,this)); |
| 118 | if (debugObserver != null) { |
| 119 | simulationObservers.addObserver(debugObserver); |
| 120 | } |
| 121 | |
| 122 | simulationStartTime = System.nanoTime(); |
| 123 | sendEvent("de/uka/ipd/sdq/simucomframework/simucomdock/SIM_STARTED"); |
| 124 | ((ISimulationControl) service.getService()).prepareSimulation(config, simulationObservers, isRemoteRun); |
| 125 | } catch (Exception ex) { |
| 126 | throw new RuntimeException(ex); |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | public SimuComModel getSimuComModel() { |
| 131 | if (service != null) { |
| 132 | return ((AbstractMain)service.getService()).getModel(); |
| 133 | } |
| 134 | return null; |
| 135 | } |
| 136 | |
| 137 | private void simulateBundle(AbstractSimulationConfig config, |
| 138 | byte[] simulationBundle, EventAdmin eventAdmin, boolean isRemoteRun) { |
| 139 | try { |
| 140 | simulate(config, simulationBundleRef, eventAdmin, isRemoteRun); |
| 141 | } catch (Exception e) { |
| 142 | throw new RuntimeException("OSGi failure",e); |
| 143 | } finally { |
| 144 | if (simulationBundleRef != null) { |
| 145 | try { |
| 146 | if (simulationBundleRef.getState() == Bundle.ACTIVE) |
| 147 | simulationBundleRef.stop(); |
| 148 | |
| 149 | simulationBundleRef.uninstall(); |
| 150 | } catch (BundleException e) { |
| 151 | throw new RuntimeException("OSGi failure",e); |
| 152 | } |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | } |
| 157 | |
| 158 | private void simulate(final AbstractSimulationConfig config, Bundle simulationBundleRef, final EventAdmin eventAdmin, boolean isRemoteRun) { |
| 159 | try { |
| 160 | SimulationResult result = ((ISimulationControl)service.getService()).startSimulation( |
| 161 | config, simulationObservers, isRemoteRun); |
| 162 | |
| 163 | if (result == SimulationResult.ERROR) { |
| 164 | throw new RuntimeException("Simulation failed.",((ISimulationControl)service.getService()).getErrorThrowable()); |
| 165 | } |
| 166 | } catch (Exception ex) { |
| 167 | throw new RuntimeException(ex); |
| 168 | } finally { |
| 169 | service.close(); |
| 170 | Hashtable<String, Object> eventData = new Hashtable<String, Object>(); |
| 171 | eventData.put(SIMTIME_TOTAL, System.nanoTime()-simulationStartTime); |
| 172 | sendEvent("de/uka/ipd/sdq/simucomframework/simucomdock/SIM_STOPPED",eventData); |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | public void suspend() { |
| 177 | if (debugObserver == null) |
| 178 | throw new IllegalStateException("Suspend only available in debug mode"); |
| 179 | debugObserver.suspend(); |
| 180 | } |
| 181 | |
| 182 | public void resume() { |
| 183 | if (debugObserver == null) |
| 184 | throw new IllegalStateException("Suspend only available in debug mode"); |
| 185 | debugObserver.resume(); |
| 186 | } |
| 187 | |
| 188 | private void sendEvent(String topic) { |
| 189 | sendEvent(topic, new Hashtable()); |
| 190 | } |
| 191 | |
| 192 | private void sendEvent(String topic, Hashtable newProperties) { |
| 193 | Hashtable properties = new Hashtable(); |
| 194 | properties.put("DOCK_ID", SimulationDockServiceImpl.this.getDockId()); |
| 195 | properties.putAll(newProperties); |
| 196 | Event event = new Event(topic, (Map)properties); |
| 197 | eventAdmin.sendEvent(event); |
| 198 | } |
| 199 | |
| 200 | private String persistBundleInTempDir(byte[] simulationBundle) { |
| 201 | File tempFile = null; |
| 202 | try { |
| 203 | tempFile = File.createTempFile("simucominstance", ".jar"); |
| 204 | tempFile.deleteOnExit(); |
| 205 | FileOutputStream fos = new FileOutputStream(tempFile); |
| 206 | fos.write(simulationBundle); |
| 207 | fos.close(); |
| 208 | } catch (IOException e) { |
| 209 | throw new RuntimeException("OSGi failure",e); |
| 210 | } |
| 211 | return tempFile.getAbsolutePath(); |
| 212 | } |
| 213 | |
| 214 | public String getDockId() { |
| 215 | return myID; |
| 216 | } |
| 217 | |
| 218 | private void unloadPluginIfExists(BundleContext context, String bundleName) { |
| 219 | for (Bundle b : context.getBundles()) { |
| 220 | if (b.getSymbolicName() != null && b.getSymbolicName().equals(bundleName)) { |
| 221 | try { |
| 222 | if (b.getState() == Bundle.ACTIVE){ |
| 223 | b.stop(); |
| 224 | } |
| 225 | b.uninstall(); |
| 226 | } catch (BundleException e) { |
| 227 | throw new RuntimeException("OSGi failure",e); |
| 228 | } |
| 229 | } |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | private void ensurePluginLoaded(BundleContext context, String bundleName) { |
| 234 | for (Bundle b : context.getBundles()) { |
| 235 | if (b.getSymbolicName() != null && b.getSymbolicName().equals(bundleName)) { |
| 236 | if (b.getState() != Bundle.ACTIVE){ |
| 237 | try { |
| 238 | b.start(); |
| 239 | } catch (BundleException e) { |
| 240 | throw new RuntimeException("OSGi failure",e); |
| 241 | } |
| 242 | } |
| 243 | } |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | public void stopSimulation() { |
| 248 | if (service != null && service.getService() != null) { |
| 249 | ((ISimulationControl)service.getService()).stopSimulation(); |
| 250 | } |
| 251 | if (debugObserver != null) { |
| 252 | debugObserver.resume(); |
| 253 | } |
| 254 | } |
| 255 | |
| 256 | public void step() { |
| 257 | if (debugObserver == null) |
| 258 | throw new IllegalStateException("Stepping only available in debug mode"); |
| 259 | debugObserver.step(); |
| 260 | } |
| 261 | |
| 262 | public SimuComStatus getSimuComStatus() { |
| 263 | return ((ISimulationControl)service.getService()).getStatus(); |
| 264 | } |
| 265 | } |