Tue, 06 Mar 2012 16:09:35 -0800
7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom
1 /*
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.xml.internal.ws.server;
28 import com.sun.istack.internal.NotNull;
29 import com.sun.istack.internal.Nullable;
30 import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
31 import com.sun.xml.internal.ws.addressing.EPRSDDocumentFilter;
32 import com.sun.xml.internal.ws.addressing.WSEPRExtension;
33 import com.sun.xml.internal.ws.api.Component;
34 import com.sun.xml.internal.ws.api.ComponentFeature;
35 import com.sun.xml.internal.ws.api.SOAPVersion;
36 import com.sun.xml.internal.ws.api.WSBinding;
37 import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
38 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
39 import com.sun.xml.internal.ws.api.message.Message;
40 import com.sun.xml.internal.ws.api.message.Packet;
41 import com.sun.xml.internal.ws.api.model.SEIModel;
42 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
43 import com.sun.xml.internal.ws.api.pipe.Codec;
44 import com.sun.xml.internal.ws.api.pipe.Engine;
45 import com.sun.xml.internal.ws.api.pipe.Fiber;
46 import com.sun.xml.internal.ws.api.pipe.FiberContextSwitchInterceptor;
47 import com.sun.xml.internal.ws.api.pipe.ServerPipeAssemblerContext;
48 import com.sun.xml.internal.ws.api.pipe.ServerTubeAssemblerContext;
49 import com.sun.xml.internal.ws.api.pipe.SyncStartForAsyncFeature;
50 import com.sun.xml.internal.ws.api.pipe.Tube;
51 import com.sun.xml.internal.ws.api.pipe.TubeCloner;
52 import com.sun.xml.internal.ws.api.pipe.TubelineAssembler;
53 import com.sun.xml.internal.ws.api.pipe.TubelineAssemblerFactory;
54 import com.sun.xml.internal.ws.api.server.Container;
55 import com.sun.xml.internal.ws.api.server.EndpointAwareCodec;
56 import com.sun.xml.internal.ws.api.server.EndpointComponent;
57 import com.sun.xml.internal.ws.api.server.EndpointReferenceExtensionContributor;
58 import com.sun.xml.internal.ws.api.server.LazyMOMProvider;
59 import com.sun.xml.internal.ws.api.server.TransportBackChannel;
60 import com.sun.xml.internal.ws.api.server.WSEndpoint;
61 import com.sun.xml.internal.ws.api.server.WebServiceContextDelegate;
62 import com.sun.xml.internal.ws.binding.BindingImpl;
63 import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
64 import com.sun.xml.internal.ws.model.wsdl.WSDLDirectProperties;
65 import com.sun.xml.internal.ws.model.wsdl.WSDLPortImpl;
66 import com.sun.xml.internal.ws.model.wsdl.WSDLPortProperties;
67 import com.sun.xml.internal.ws.model.wsdl.WSDLProperties;
68 import com.sun.xml.internal.ws.policy.PolicyMap;
69 import com.sun.xml.internal.ws.resources.HandlerMessages;
70 import com.sun.xml.internal.ws.util.Pool;
71 import com.sun.xml.internal.ws.util.Pool.TubePool;
72 import com.sun.xml.internal.ws.util.ServiceFinder;
73 import com.sun.xml.internal.ws.wsdl.OperationDispatcher;
74 import com.sun.org.glassfish.gmbal.ManagedObjectManager;
75 import org.w3c.dom.Element;
77 import javax.annotation.PreDestroy;
78 import javax.xml.namespace.QName;
79 import javax.xml.stream.XMLStreamException;
80 import javax.xml.ws.EndpointReference;
81 import javax.xml.ws.WebServiceException;
82 import javax.xml.ws.handler.Handler;
83 import java.lang.reflect.Method;
84 import java.util.Arrays;
85 import java.util.Collection;
86 import java.util.HashMap;
87 import java.util.HashSet;
88 import java.util.Iterator;
89 import java.util.List;
90 import java.util.Map;
91 import java.util.Set;
92 import java.util.concurrent.CopyOnWriteArraySet;
93 import java.util.concurrent.Executor;
94 import java.util.logging.Level;
95 import java.util.logging.Logger;
97 /**
98 * {@link WSEndpoint} implementation.
99 *
100 * @author Kohsuke Kawaguchi
101 * @author Jitendra Kotamraju
102 */
103 public /*final*/ class WSEndpointImpl<T> extends WSEndpoint<T> implements LazyMOMProvider.WSEndpointScopeChangeListener {
104 private static final Logger LOGGER = Logger.getLogger(WSEndpointImpl.class.getName());
106 private final @NotNull QName serviceName;
107 private final @NotNull QName portName;
108 protected final WSBinding binding;
109 private final SEIModel seiModel;
110 private final @NotNull Container container;
111 private final WSDLPort port;
113 protected final Tube masterTubeline;
114 private final ServiceDefinitionImpl serviceDef;
115 private final SOAPVersion soapVersion;
116 private final Engine engine;
117 private final @NotNull Codec masterCodec;
118 private final @NotNull PolicyMap endpointPolicy;
119 private final Pool<Tube> tubePool;
120 private final OperationDispatcher operationDispatcher;
121 private @NotNull ManagedObjectManager managedObjectManager;
122 private boolean managedObjectManagerClosed = false;
123 private Object managedObjectManagerLock = new Object();
124 private LazyMOMProvider.Scope lazyMOMProviderScope = LazyMOMProvider.Scope.STANDALONE;
125 private final @NotNull ServerTubeAssemblerContext context;
127 private Map<QName, WSEndpointReference.EPRExtension> endpointReferenceExtensions = new HashMap<QName, WSEndpointReference.EPRExtension>();
128 /**
129 * Set to true once we start shutting down this endpoint.
130 * Used to avoid running the clean up processing twice.
131 *
132 * @see #dispose()
133 */
134 private boolean disposed;
136 private final Class<T> implementationClass;
137 private final @NotNull WSDLProperties wsdlProperties;
138 private final Set<Component> componentRegistry = new CopyOnWriteArraySet<Component>();
140 protected WSEndpointImpl(@NotNull QName serviceName, @NotNull QName portName, WSBinding binding,
141 Container container, SEIModel seiModel, WSDLPort port,
142 Class<T> implementationClass,
143 @Nullable ServiceDefinitionImpl serviceDef,
144 EndpointAwareTube terminalTube, boolean isSynchronous,
145 PolicyMap endpointPolicy) {
146 this.serviceName = serviceName;
147 this.portName = portName;
148 this.binding = binding;
149 this.soapVersion = binding.getSOAPVersion();
150 this.container = container;
151 this.port = port;
152 this.implementationClass = implementationClass;
153 this.serviceDef = serviceDef;
154 this.seiModel = seiModel;
155 this.endpointPolicy = endpointPolicy;
157 LazyMOMProvider.INSTANCE.registerEndpoint(this);
158 initManagedObjectManager();
160 if (serviceDef != null) {
161 serviceDef.setOwner(this);
162 }
164 ComponentFeature cf = binding.getFeature(ComponentFeature.class);
165 if (cf != null) {
166 switch(cf.getTarget()) {
167 case ENDPOINT:
168 componentRegistry.add(cf.getComponent());
169 break;
170 case CONTAINER:
171 container.getComponents().add(cf.getComponent());
172 default:
173 throw new IllegalArgumentException();
174 }
175 }
177 TubelineAssembler assembler = TubelineAssemblerFactory.create(
178 Thread.currentThread().getContextClassLoader(), binding.getBindingId(), container);
179 assert assembler != null;
181 this.operationDispatcher = (port == null) ? null : new OperationDispatcher(port, binding, seiModel);
183 context = createServerTubeAssemblerContext(terminalTube, isSynchronous);
184 this.masterTubeline = assembler.createServer(context);
186 Codec c = context.getCodec();
187 if (c instanceof EndpointAwareCodec) {
188 // create a copy to avoid sharing the codec between multiple endpoints
189 c = c.copy();
190 ((EndpointAwareCodec) c).setEndpoint(this);
191 }
192 this.masterCodec = c;
194 tubePool = new TubePool(masterTubeline);
195 terminalTube.setEndpoint(this);
196 engine = new Engine(toString());
197 wsdlProperties = (port == null) ? new WSDLDirectProperties(serviceName, portName, seiModel) : new WSDLPortProperties(port, seiModel);
199 Map<QName, WSEndpointReference.EPRExtension> eprExtensions = new HashMap<QName, WSEndpointReference.EPRExtension>();
200 try {
201 if (port != null) {
202 //gather EPR extrensions from WSDL Model
203 WSEndpointReference wsdlEpr = ((WSDLPortImpl) port).getEPR();
204 if (wsdlEpr != null) {
205 for (WSEndpointReference.EPRExtension extnEl : wsdlEpr.getEPRExtensions()) {
206 eprExtensions.put(extnEl.getQName(), extnEl);
207 }
208 }
209 }
211 EndpointReferenceExtensionContributor[] eprExtnContributors = ServiceFinder.find(EndpointReferenceExtensionContributor.class).toArray();
212 for(EndpointReferenceExtensionContributor eprExtnContributor :eprExtnContributors) {
213 WSEndpointReference.EPRExtension wsdlEPRExtn = eprExtensions.remove(eprExtnContributor.getQName());
214 WSEndpointReference.EPRExtension endpointEprExtn = eprExtnContributor.getEPRExtension(this,wsdlEPRExtn);
215 if (endpointEprExtn != null) {
216 eprExtensions.put(endpointEprExtn.getQName(), endpointEprExtn);
217 }
218 }
219 for (WSEndpointReference.EPRExtension extn : eprExtensions.values()) {
220 endpointReferenceExtensions.put(extn.getQName(), new WSEPRExtension(
221 XMLStreamBuffer.createNewBufferFromXMLStreamReader(extn.readAsXMLStreamReader()),extn.getQName()));
222 }
223 } catch (XMLStreamException ex) {
224 throw new WebServiceException(ex);
225 }
226 if(!eprExtensions.isEmpty()) {
227 serviceDef.addFilter(new EPRSDDocumentFilter(this));
228 }
229 }
231 protected ServerTubeAssemblerContext createServerTubeAssemblerContext(
232 EndpointAwareTube terminalTube, boolean isSynchronous) {
233 ServerTubeAssemblerContext context = new ServerPipeAssemblerContext(
234 seiModel, port, this, terminalTube, isSynchronous);
235 return context;
236 }
238 protected WSEndpointImpl(@NotNull QName serviceName, @NotNull QName portName, WSBinding binding, Container container,
239 SEIModel seiModel, WSDLPort port,
240 Tube masterTubeline) {
241 this.serviceName = serviceName;
242 this.portName = portName;
243 this.binding = binding;
244 this.soapVersion = binding.getSOAPVersion();
245 this.container = container;
246 this.endpointPolicy = null;
247 this.port = port;
248 this.seiModel = seiModel;
249 this.serviceDef = null;
250 this.implementationClass = null;
251 this.masterTubeline = masterTubeline;
252 this.masterCodec = ((BindingImpl) this.binding).createCodec();
254 LazyMOMProvider.INSTANCE.registerEndpoint(this);
255 initManagedObjectManager();
257 this.operationDispatcher = (port == null) ? null : new OperationDispatcher(port, binding, seiModel);
258 this.context = new ServerPipeAssemblerContext(
259 seiModel, port, this, null /* not known */, false);
261 tubePool = new TubePool(masterTubeline);
262 engine = new Engine(toString());
263 wsdlProperties = (port == null) ? new WSDLDirectProperties(serviceName, portName, seiModel) : new WSDLPortProperties(port, seiModel);
264 }
266 public Collection<WSEndpointReference.EPRExtension> getEndpointReferenceExtensions() {
267 return endpointReferenceExtensions.values();
268 }
270 /**
271 * Nullable when there is no associated WSDL Model
272 * @return
273 */
274 public @Nullable OperationDispatcher getOperationDispatcher() {
275 return operationDispatcher;
276 }
278 public PolicyMap getPolicyMap() {
279 return endpointPolicy;
280 }
282 public @NotNull Class<T> getImplementationClass() {
283 return implementationClass;
284 }
286 public @NotNull WSBinding getBinding() {
287 return binding;
288 }
290 public @NotNull Container getContainer() {
291 return container;
292 }
294 public WSDLPort getPort() {
295 return port;
296 }
298 @Override
299 public @Nullable SEIModel getSEIModel() {
300 return seiModel;
301 }
303 public void setExecutor(Executor exec) {
304 engine.setExecutor(exec);
305 }
307 @Override
308 public Engine getEngine() {
309 return engine;
310 }
312 public void schedule(final Packet request, final CompletionCallback callback, FiberContextSwitchInterceptor interceptor) {
313 processAsync(request, callback, interceptor, true);
314 }
316 private void processAsync(final Packet request, final CompletionCallback callback, FiberContextSwitchInterceptor interceptor, boolean schedule) {
317 request.endpoint = WSEndpointImpl.this;
318 request.addSatellite(wsdlProperties);
320 Fiber fiber = engine.createFiber();
321 if (interceptor != null) {
322 fiber.addInterceptor(interceptor);
323 }
324 final Tube tube = tubePool.take();
325 Fiber.CompletionCallback cbak = new Fiber.CompletionCallback() {
326 public void onCompletion(@NotNull Packet response) {
327 tubePool.recycle(tube);
328 if (callback != null) {
329 callback.onCompletion(response);
330 }
331 }
333 public void onCompletion(@NotNull Throwable error) {
334 // let's not reuse tubes as they might be in a wrong state, so not
335 // calling tubePool.recycle()
336 // Convert all runtime exceptions to Packet so that transport doesn't
337 // have to worry about converting to wire message
338 // TODO XML/HTTP binding
339 Message faultMsg = SOAPFaultBuilder.createSOAPFaultMessage(
340 soapVersion, null, error);
341 Packet response = request.createServerResponse(faultMsg, request.endpoint.getPort(), null,
342 request.endpoint.getBinding());
343 if (callback != null) {
344 callback.onCompletion(response);
345 }
346 }
347 };
349 fiber.start(tube, request, cbak,
350 binding.isFeatureEnabled(SyncStartForAsyncFeature.class) || !schedule);
351 }
353 @Override
354 public void process(final Packet request, final CompletionCallback callback, FiberContextSwitchInterceptor interceptor) {
355 processAsync(request, callback, interceptor, false);
356 }
358 public @NotNull PipeHead createPipeHead() {
359 return new PipeHead() {
360 private final Tube tube = TubeCloner.clone(masterTubeline);
362 public @NotNull Packet process(Packet request, WebServiceContextDelegate wscd, TransportBackChannel tbc) {
363 request.webServiceContextDelegate = wscd;
364 request.transportBackChannel = tbc;
365 request.endpoint = WSEndpointImpl.this;
366 request.addSatellite(wsdlProperties);
368 Fiber fiber = engine.createFiber();
369 Packet response;
370 try {
371 response = fiber.runSync(tube, request);
372 } catch (RuntimeException re) {
373 // Catch all runtime exceptions so that transport doesn't
374 // have to worry about converting to wire message
375 // TODO XML/HTTP binding
376 Message faultMsg = SOAPFaultBuilder.createSOAPFaultMessage(
377 soapVersion, null, re);
378 response = request.createServerResponse(faultMsg, request.endpoint.getPort(), null, request.endpoint.getBinding());
379 }
380 return response;
381 }
382 };
383 }
385 public synchronized void dispose() {
386 if (disposed)
387 return;
388 disposed = true;
390 masterTubeline.preDestroy();
392 for (Handler handler : binding.getHandlerChain()) {
393 for (Method method : handler.getClass().getMethods()) {
394 if (method.getAnnotation(PreDestroy.class) == null) {
395 continue;
396 }
397 try {
398 method.invoke(handler);
399 } catch (Exception e) {
400 logger.log(Level.WARNING, HandlerMessages.HANDLER_PREDESTROY_IGNORE(e.getMessage()), e);
401 }
402 break;
403 }
404 }
405 closeManagedObjectManager();
406 }
408 public ServiceDefinitionImpl getServiceDefinition() {
409 return serviceDef;
410 }
412 public Set<EndpointComponent> getComponentRegistry() {
413 Set<EndpointComponent> sec = new EndpointComponentSet();
414 for (Component c : componentRegistry) {
415 sec.add(c instanceof EndpointComponentWrapper ?
416 ((EndpointComponentWrapper) c).component :
417 new ComponentWrapper(c));
418 }
419 return sec;
420 }
422 private class EndpointComponentSet extends HashSet<EndpointComponent> {
424 @Override
425 public Iterator<EndpointComponent> iterator() {
426 final Iterator<EndpointComponent> it = super.iterator();
427 return new Iterator<EndpointComponent>() {
428 private EndpointComponent last = null;
430 public boolean hasNext() {
431 return it.hasNext();
432 }
434 public EndpointComponent next() {
435 last = it.next();
436 return last;
437 }
439 public void remove() {
440 it.remove();
441 if (last != null) {
442 componentRegistry.remove(last instanceof ComponentWrapper ?
443 ((ComponentWrapper) last).component :
444 new EndpointComponentWrapper(last));
445 }
446 last = null;
447 }
448 };
449 }
451 @Override
452 public boolean add(EndpointComponent e) {
453 boolean result = super.add(e);
454 if (result) {
455 componentRegistry.add(new EndpointComponentWrapper(e));
456 }
457 return result;
458 }
460 @Override
461 public boolean remove(Object o) {
462 boolean result = super.remove(o);
463 if (result) {
464 componentRegistry.remove(o instanceof ComponentWrapper ?
465 ((ComponentWrapper) o).component :
466 new EndpointComponentWrapper((EndpointComponent)o));
467 }
468 return result;
469 }
471 }
473 private static class ComponentWrapper implements EndpointComponent {
474 private final Component component;
476 public ComponentWrapper(Component component) {
477 this.component = component;
478 }
480 public <S> S getSPI(Class<S> spiType) {
481 return component.getSPI(spiType);
482 }
484 @Override
485 public int hashCode() {
486 return component.hashCode();
487 }
489 @Override
490 public boolean equals(Object obj) {
491 return component.equals(obj);
492 }
493 }
495 private static class EndpointComponentWrapper implements Component {
496 private final EndpointComponent component;
498 public EndpointComponentWrapper(EndpointComponent component) {
499 this.component = component;
500 }
502 public <S> S getSPI(Class<S> spiType) {
503 return component.getSPI(spiType);
504 }
506 @Override
507 public int hashCode() {
508 return component.hashCode();
509 }
511 @Override
512 public boolean equals(Object obj) {
513 return component.equals(obj);
514 }
515 }
517 public @NotNull Set<Component> getComponents() {
518 return componentRegistry;
519 }
521 private static final Logger logger = Logger.getLogger(
522 com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server.endpoint");
524 public <T extends EndpointReference> T getEndpointReference(Class<T>
525 clazz, String address, String wsdlAddress, Element... referenceParameters) {
526 List<Element> refParams = null;
527 if (referenceParameters != null) {
528 refParams = Arrays.asList(referenceParameters);
529 }
530 return getEndpointReference(clazz, address, wsdlAddress, null, refParams);
531 }
532 public <T extends EndpointReference> T getEndpointReference(Class<T> clazz,
533 String address, String wsdlAddress, List<Element> metadata,
534 List<Element> referenceParameters) {
535 QName portType = null;
536 if (port != null) {
537 portType = port.getBinding().getPortTypeName();
538 }
540 AddressingVersion av = AddressingVersion.fromSpecClass(clazz);
541 return new WSEndpointReference(
542 av, address, serviceName, portName, portType, metadata, wsdlAddress, referenceParameters,endpointReferenceExtensions.values(), null).toSpec(clazz);
544 }
546 public @NotNull QName getPortName() {
547 return portName;
548 }
551 public @NotNull Codec createCodec() {
552 return masterCodec.copy();
553 }
555 public @NotNull QName getServiceName() {
556 return serviceName;
557 }
559 private void initManagedObjectManager() {
560 synchronized (managedObjectManagerLock) {
561 if (managedObjectManager == null) {
562 switch (this.lazyMOMProviderScope) {
563 case GLASSFISH_NO_JMX:
564 managedObjectManager = new WSEndpointMOMProxy(this);
565 break;
566 default:
567 managedObjectManager = obtainManagedObjectManager();
568 }
569 }
570 }
571 }
573 public @NotNull ManagedObjectManager getManagedObjectManager() {
574 return managedObjectManager;
575 }
577 /**
578 * Obtains a real instance of {@code ManagedObjectManager} class no matter what lazyMOMProviderScope is this endpoint in (or if the
579 * Gmbal API calls should be deferred).
580 *
581 * @see com.sun.xml.internal.ws.api.server.LazyMOMProvider.Scope
582 * @return an instance of {@code ManagedObjectManager}
583 */
584 @NotNull ManagedObjectManager obtainManagedObjectManager() {
585 final MonitorRootService monitorRootService = new MonitorRootService(this);
586 final ManagedObjectManager managedObjectManager = monitorRootService.createManagedObjectManager(this);
588 // ManagedObjectManager was suspended due to root creation (see MonitorBase#initMOM)
589 managedObjectManager.resumeJMXRegistration();
591 return managedObjectManager;
592 }
594 public void scopeChanged(LazyMOMProvider.Scope scope) {
595 synchronized (managedObjectManagerLock) {
596 if (managedObjectManagerClosed) {
597 return;
598 }
600 this.lazyMOMProviderScope = scope;
602 // possible lazyMOMProviderScope change can be LazyMOMProvider.Scope.GLASSFISH_NO_JMX or LazyMOMProvider.Scope.GLASSFISH_JMX
603 if (managedObjectManager == null) {
604 if (scope != LazyMOMProvider.Scope.GLASSFISH_NO_JMX) {
605 managedObjectManager = obtainManagedObjectManager();
606 } else {
607 managedObjectManager = new WSEndpointMOMProxy(this);
608 }
609 } else {
610 // if ManagedObjectManager for this endpoint has already been created and is uninitialized proxy then
611 // fill it with a real instance
612 if (managedObjectManager instanceof WSEndpointMOMProxy
613 && !((WSEndpointMOMProxy)managedObjectManager).isInitialized()) {
614 ((WSEndpointMOMProxy)managedObjectManager).setManagedObjectManager(obtainManagedObjectManager());
615 }
616 }
617 }
618 }
620 // This can be called independently of WSEndpoint.dispose.
621 // Example: the WSCM framework calls this before dispose.
622 public void closeManagedObjectManager() {
623 synchronized (managedObjectManagerLock) {
624 if (managedObjectManagerClosed == true) {
625 return;
626 }
627 if (managedObjectManager != null) {
628 boolean close = true;
630 // ManagedObjectManager doesn't need to be closed because it exists only as a proxy
631 if (managedObjectManager instanceof WSEndpointMOMProxy
632 && !((WSEndpointMOMProxy)managedObjectManager).isInitialized()) {
633 close = false;
634 }
636 if (close) {
637 // no further notification on scope change
638 LazyMOMProvider.INSTANCE.unregisterEndpoint(this);
639 MonitorBase.closeMOM(managedObjectManager);
640 }
641 }
642 managedObjectManagerClosed = true;
643 }
644 }
646 public @NotNull ServerTubeAssemblerContext getAssemblerContext() {
647 return context;
648 }
649 }