Thu, 31 Aug 2017 15:18:52 +0800
merge
1 /*
2 * Copyright (c) 1997, 2013, 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.ComponentsFeature;
36 import com.sun.xml.internal.ws.api.SOAPVersion;
37 import com.sun.xml.internal.ws.api.WSBinding;
38 import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
39 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
40 import com.sun.xml.internal.ws.api.message.Message;
41 import com.sun.xml.internal.ws.api.message.Packet;
42 import com.sun.xml.internal.ws.api.model.SEIModel;
43 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
44 import com.sun.xml.internal.ws.api.pipe.*;
45 import com.sun.xml.internal.ws.api.server.*;
46 import com.sun.xml.internal.ws.binding.BindingImpl;
47 import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
48 import com.sun.xml.internal.ws.model.wsdl.WSDLDirectProperties;
49 import com.sun.xml.internal.ws.model.wsdl.WSDLPortProperties;
50 import com.sun.xml.internal.ws.model.wsdl.WSDLProperties;
51 import com.sun.xml.internal.ws.policy.PolicyMap;
52 import com.sun.xml.internal.ws.resources.HandlerMessages;
53 import com.sun.xml.internal.ws.util.Pool;
54 import com.sun.xml.internal.ws.util.Pool.TubePool;
55 import com.sun.xml.internal.ws.util.ServiceFinder;
56 import com.sun.xml.internal.ws.wsdl.OperationDispatcher;
57 import com.sun.org.glassfish.gmbal.ManagedObjectManager;
58 import org.w3c.dom.Element;
60 import javax.annotation.PreDestroy;
61 import javax.xml.namespace.QName;
62 import javax.xml.stream.XMLStreamException;
63 import javax.xml.ws.EndpointReference;
64 import javax.xml.ws.WebServiceException;
65 import javax.xml.ws.handler.Handler;
66 import java.lang.reflect.Method;
67 import java.util.*;
68 import java.util.concurrent.CopyOnWriteArraySet;
69 import java.util.concurrent.Executor;
70 import java.util.logging.Level;
71 import java.util.logging.Logger;
72 import javax.management.ObjectName;
74 /**
75 * {@link WSEndpoint} implementation.
76 *
77 * @author Kohsuke Kawaguchi
78 * @author Jitendra Kotamraju
79 */
80 public /*final*/ class WSEndpointImpl<T> extends WSEndpoint<T> implements LazyMOMProvider.WSEndpointScopeChangeListener {
82 private static final Logger logger = Logger.getLogger(com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server.endpoint");
84 private final @NotNull QName serviceName;
85 private final @NotNull QName portName;
86 protected final WSBinding binding;
87 private final SEIModel seiModel;
88 private final @NotNull Container container;
89 private final WSDLPort port;
91 protected final Tube masterTubeline;
92 private final ServiceDefinitionImpl serviceDef;
93 private final SOAPVersion soapVersion;
94 private final Engine engine;
95 private final @NotNull Codec masterCodec;
96 private final @NotNull PolicyMap endpointPolicy;
97 private final Pool<Tube> tubePool;
98 private final OperationDispatcher operationDispatcher;
99 private @NotNull ManagedObjectManager managedObjectManager;
100 private boolean managedObjectManagerClosed = false;
101 private final Object managedObjectManagerLock = new Object();
102 private LazyMOMProvider.Scope lazyMOMProviderScope = LazyMOMProvider.Scope.STANDALONE;
103 private final @NotNull ServerTubeAssemblerContext context;
105 private Map<QName, WSEndpointReference.EPRExtension> endpointReferenceExtensions = new HashMap<QName, WSEndpointReference.EPRExtension>();
106 /**
107 * Set to true once we start shutting down this endpoint. Used to avoid
108 * running the clean up processing twice.
109 *
110 * @see #dispose()
111 */
112 private boolean disposed;
113 private final Class<T> implementationClass;
114 private final @NotNull
115 WSDLProperties wsdlProperties;
116 private final Set<Component> componentRegistry = new CopyOnWriteArraySet<Component>();
118 protected WSEndpointImpl(@NotNull QName serviceName, @NotNull QName portName, WSBinding binding,
119 Container container, SEIModel seiModel, WSDLPort port,
120 Class<T> implementationClass,
121 @Nullable ServiceDefinitionImpl serviceDef,
122 EndpointAwareTube terminalTube, boolean isSynchronous,
123 PolicyMap endpointPolicy) {
124 this.serviceName = serviceName;
125 this.portName = portName;
126 this.binding = binding;
127 this.soapVersion = binding.getSOAPVersion();
128 this.container = container;
129 this.port = port;
130 this.implementationClass = implementationClass;
131 this.serviceDef = serviceDef;
132 this.seiModel = seiModel;
133 this.endpointPolicy = endpointPolicy;
135 LazyMOMProvider.INSTANCE.registerEndpoint(this);
136 initManagedObjectManager();
138 if (serviceDef != null) {
139 serviceDef.setOwner(this);
140 }
142 ComponentFeature cf = binding.getFeature(ComponentFeature.class);
143 if (cf != null) {
144 switch (cf.getTarget()) {
145 case ENDPOINT:
146 componentRegistry.add(cf.getComponent());
147 break;
148 case CONTAINER:
149 container.getComponents().add(cf.getComponent());
150 break;
151 default:
152 throw new IllegalArgumentException();
153 }
154 }
155 ComponentsFeature csf = binding.getFeature(ComponentsFeature.class);
156 if (csf != null) {
157 for (ComponentFeature cfi : csf.getComponentFeatures()) {
158 switch (cfi.getTarget()) {
159 case ENDPOINT:
160 componentRegistry.add(cfi.getComponent());
161 break;
162 case CONTAINER:
163 container.getComponents().add(cfi.getComponent());
164 break;
165 default:
166 throw new IllegalArgumentException();
167 }
168 }
169 }
171 TubelineAssembler assembler = TubelineAssemblerFactory.create(
172 Thread.currentThread().getContextClassLoader(), binding.getBindingId(), container);
173 assert assembler != null;
175 this.operationDispatcher = (port == null) ? null : new OperationDispatcher(port, binding, seiModel);
177 context = createServerTubeAssemblerContext(terminalTube, isSynchronous);
178 this.masterTubeline = assembler.createServer(context);
180 Codec c = context.getCodec();
181 if (c instanceof EndpointAwareCodec) {
182 // create a copy to avoid sharing the codec between multiple endpoints
183 c = c.copy();
184 ((EndpointAwareCodec) c).setEndpoint(this);
185 }
186 this.masterCodec = c;
188 tubePool = new TubePool(masterTubeline);
189 terminalTube.setEndpoint(this);
190 engine = new Engine(toString(), container);
191 wsdlProperties = (port == null) ? new WSDLDirectProperties(serviceName, portName, seiModel) : new WSDLPortProperties(port, seiModel);
193 Map<QName, WSEndpointReference.EPRExtension> eprExtensions = new HashMap<QName, WSEndpointReference.EPRExtension>();
194 try {
195 if (port != null) {
196 //gather EPR extrensions from WSDL Model
197 WSEndpointReference wsdlEpr = port.getEPR();
198 if (wsdlEpr != null) {
199 for (WSEndpointReference.EPRExtension extnEl : wsdlEpr.getEPRExtensions()) {
200 eprExtensions.put(extnEl.getQName(), extnEl);
201 }
202 }
203 }
205 EndpointReferenceExtensionContributor[] eprExtnContributors = ServiceFinder.find(EndpointReferenceExtensionContributor.class).toArray();
206 for(EndpointReferenceExtensionContributor eprExtnContributor :eprExtnContributors) {
207 WSEndpointReference.EPRExtension wsdlEPRExtn = eprExtensions.remove(eprExtnContributor.getQName());
208 WSEndpointReference.EPRExtension endpointEprExtn = eprExtnContributor.getEPRExtension(this,wsdlEPRExtn);
209 if (endpointEprExtn != null) {
210 eprExtensions.put(endpointEprExtn.getQName(), endpointEprExtn);
211 }
212 }
213 for (WSEndpointReference.EPRExtension extn : eprExtensions.values()) {
214 endpointReferenceExtensions.put(extn.getQName(), new WSEPRExtension(
215 XMLStreamBuffer.createNewBufferFromXMLStreamReader(extn.readAsXMLStreamReader()),extn.getQName()));
216 }
217 } catch (XMLStreamException ex) {
218 throw new WebServiceException(ex);
219 }
220 if(!eprExtensions.isEmpty()) {
221 serviceDef.addFilter(new EPRSDDocumentFilter(this));
222 }
223 }
225 protected ServerTubeAssemblerContext createServerTubeAssemblerContext(
226 EndpointAwareTube terminalTube, boolean isSynchronous) {
227 ServerTubeAssemblerContext ctx = new ServerPipeAssemblerContext(
228 seiModel, port, this, terminalTube, isSynchronous);
229 return ctx;
230 }
232 protected WSEndpointImpl(@NotNull QName serviceName, @NotNull QName portName, WSBinding binding, Container container,
233 SEIModel seiModel, WSDLPort port,
234 Tube masterTubeline) {
235 this.serviceName = serviceName;
236 this.portName = portName;
237 this.binding = binding;
238 this.soapVersion = binding.getSOAPVersion();
239 this.container = container;
240 this.endpointPolicy = null;
241 this.port = port;
242 this.seiModel = seiModel;
243 this.serviceDef = null;
244 this.implementationClass = null;
245 this.masterTubeline = masterTubeline;
246 this.masterCodec = ((BindingImpl) this.binding).createCodec();
248 LazyMOMProvider.INSTANCE.registerEndpoint(this);
249 initManagedObjectManager();
251 this.operationDispatcher = (port == null) ? null : new OperationDispatcher(port, binding, seiModel);
252 this.context = new ServerPipeAssemblerContext(
253 seiModel, port, this, null /* not known */, false);
255 tubePool = new TubePool(masterTubeline);
256 engine = new Engine(toString(), container);
257 wsdlProperties = (port == null) ? new WSDLDirectProperties(serviceName, portName, seiModel) : new WSDLPortProperties(port, seiModel);
258 }
260 public Collection<WSEndpointReference.EPRExtension> getEndpointReferenceExtensions() {
261 return endpointReferenceExtensions.values();
262 }
264 /**
265 * Nullable when there is no associated WSDL Model
266 * @return
267 */
268 public @Nullable OperationDispatcher getOperationDispatcher() {
269 return operationDispatcher;
270 }
272 public PolicyMap getPolicyMap() {
273 return endpointPolicy;
274 }
276 public @NotNull Class<T> getImplementationClass() {
277 return implementationClass;
278 }
280 public @NotNull WSBinding getBinding() {
281 return binding;
282 }
284 public @NotNull Container getContainer() {
285 return container;
286 }
288 public WSDLPort getPort() {
289 return port;
290 }
292 @Override
293 public @Nullable SEIModel getSEIModel() {
294 return seiModel;
295 }
297 public void setExecutor(Executor exec) {
298 engine.setExecutor(exec);
299 }
301 @Override
302 public Engine getEngine() {
303 return engine;
304 }
306 public void schedule(final Packet request, final CompletionCallback callback, FiberContextSwitchInterceptor interceptor) {
307 processAsync(request, callback, interceptor, true);
308 }
310 private void processAsync(final Packet request,
311 final CompletionCallback callback,
312 FiberContextSwitchInterceptor interceptor, boolean schedule) {
313 Container old = ContainerResolver.getDefault().enterContainer(container);
314 try {
315 request.endpoint = WSEndpointImpl.this;
316 request.addSatellite(wsdlProperties);
318 Fiber fiber = engine.createFiber();
319 fiber.setDeliverThrowableInPacket(true);
320 if (interceptor != null) {
321 fiber.addInterceptor(interceptor);
322 }
323 final Tube tube = tubePool.take();
324 Fiber.CompletionCallback cbak = new Fiber.CompletionCallback() {
325 public void onCompletion(@NotNull Packet response) {
326 ThrowableContainerPropertySet tc = response.getSatellite(ThrowableContainerPropertySet.class);
327 if (tc == null) {
328 // Only recycle tubes in non-exception path as some Tubes may be
329 // in invalid state following exception
330 tubePool.recycle(tube);
331 }
333 if (callback != null) {
334 if (tc != null) {
335 response = createServiceResponseForException(tc,
336 response,
337 soapVersion,
338 request.endpoint.getPort(),
339 null,
340 request.endpoint.getBinding());
341 }
342 callback.onCompletion(response);
343 }
344 }
346 public void onCompletion(@NotNull Throwable error) {
347 // will never be called now that we are using
348 // fiber.setDeliverThrowableInPacket(true);
349 throw new IllegalStateException();
350 }
351 };
353 fiber.start(tube, request, cbak,
354 binding.isFeatureEnabled(SyncStartForAsyncFeature.class)
355 || !schedule);
356 } finally {
357 ContainerResolver.getDefault().exitContainer(old);
358 }
359 }
361 @Override
362 public Packet createServiceResponseForException(final ThrowableContainerPropertySet tc,
363 final Packet responsePacket,
364 final SOAPVersion soapVersion,
365 final WSDLPort wsdlPort,
366 final SEIModel seiModel,
367 final WSBinding binding)
368 {
369 // This will happen in addressing if it is enabled.
370 if (tc.isFaultCreated()) return responsePacket;
372 final Message faultMessage = SOAPFaultBuilder.createSOAPFaultMessage(soapVersion, null, tc.getThrowable());
373 final Packet result = responsePacket.createServerResponse(faultMessage, wsdlPort, seiModel, binding);
374 // Pass info to upper layers
375 tc.setFaultMessage(faultMessage);
376 tc.setResponsePacket(responsePacket);
377 tc.setFaultCreated(true);
378 return result;
379 }
381 @Override
382 public void process(final Packet request, final CompletionCallback callback, FiberContextSwitchInterceptor interceptor) {
383 processAsync(request, callback, interceptor, false);
384 }
386 public @NotNull
387 PipeHead createPipeHead() {
388 return new PipeHead() {
389 private final Tube tube = TubeCloner.clone(masterTubeline);
391 public @NotNull
392 Packet process(Packet request, WebServiceContextDelegate wscd,
393 TransportBackChannel tbc) {
394 Container old = ContainerResolver.getDefault().enterContainer(container);
395 try {
396 request.webServiceContextDelegate = wscd;
397 request.transportBackChannel = tbc;
398 request.endpoint = WSEndpointImpl.this;
399 request.addSatellite(wsdlProperties);
401 Fiber fiber = engine.createFiber();
402 Packet response;
403 try {
404 response = fiber.runSync(tube, request);
405 } catch (RuntimeException re) {
406 // Catch all runtime exceptions so that transport
407 // doesn't
408 // have to worry about converting to wire message
409 // TODO XML/HTTP binding
410 Message faultMsg = SOAPFaultBuilder
411 .createSOAPFaultMessage(soapVersion, null, re);
412 response = request.createServerResponse(faultMsg,
413 request.endpoint.getPort(), null,
414 request.endpoint.getBinding());
415 }
416 return response;
417 } finally {
418 ContainerResolver.getDefault().exitContainer(old);
419 }
420 }
421 };
422 }
424 public synchronized void dispose() {
425 if (disposed) {
426 return;
427 }
428 disposed = true;
430 masterTubeline.preDestroy();
432 for (Handler handler : binding.getHandlerChain()) {
433 for (Method method : handler.getClass().getMethods()) {
434 if (method.getAnnotation(PreDestroy.class) == null) {
435 continue;
436 }
437 try {
438 method.invoke(handler);
439 } catch (Exception e) {
440 logger.log(Level.WARNING, HandlerMessages.HANDLER_PREDESTROY_IGNORE(e.getMessage()), e);
441 }
442 break;
443 }
444 }
445 closeManagedObjectManager();
446 LazyMOMProvider.INSTANCE.unregisterEndpoint(this);
447 }
449 public ServiceDefinitionImpl getServiceDefinition() {
450 return serviceDef;
451 }
453 public Set<EndpointComponent> getComponentRegistry() {
454 Set<EndpointComponent> sec = new EndpointComponentSet();
455 for (Component c : componentRegistry) {
456 sec.add(c instanceof EndpointComponentWrapper ?
457 ((EndpointComponentWrapper) c).component :
458 new ComponentWrapper(c));
459 }
460 return sec;
461 }
463 private class EndpointComponentSet extends HashSet<EndpointComponent> {
465 @Override
466 public Iterator<EndpointComponent> iterator() {
467 final Iterator<EndpointComponent> it = super.iterator();
468 return new Iterator<EndpointComponent>() {
469 private EndpointComponent last = null;
471 public boolean hasNext() {
472 return it.hasNext();
473 }
475 public EndpointComponent next() {
476 last = it.next();
477 return last;
478 }
480 public void remove() {
481 it.remove();
482 if (last != null) {
483 componentRegistry.remove(last instanceof ComponentWrapper ?
484 ((ComponentWrapper) last).component :
485 new EndpointComponentWrapper(last));
486 }
487 last = null;
488 }
489 };
490 }
492 @Override
493 public boolean add(EndpointComponent e) {
494 boolean result = super.add(e);
495 if (result) {
496 componentRegistry.add(new EndpointComponentWrapper(e));
497 }
498 return result;
499 }
501 @Override
502 public boolean remove(Object o) {
503 boolean result = super.remove(o);
504 if (result) {
505 componentRegistry.remove(o instanceof ComponentWrapper ?
506 ((ComponentWrapper) o).component :
507 new EndpointComponentWrapper((EndpointComponent)o));
508 }
509 return result;
510 }
512 }
514 private static class ComponentWrapper implements EndpointComponent {
515 private final Component component;
517 public ComponentWrapper(Component component) {
518 this.component = component;
519 }
521 public <S> S getSPI(Class<S> spiType) {
522 return component.getSPI(spiType);
523 }
525 @Override
526 public int hashCode() {
527 return component.hashCode();
528 }
530 @Override
531 public boolean equals(Object obj) {
532 return component.equals(obj);
533 }
534 }
536 private static class EndpointComponentWrapper implements Component {
537 private final EndpointComponent component;
539 public EndpointComponentWrapper(EndpointComponent component) {
540 this.component = component;
541 }
543 public <S> S getSPI(Class<S> spiType) {
544 return component.getSPI(spiType);
545 }
547 @Override
548 public int hashCode() {
549 return component.hashCode();
550 }
552 @Override
553 public boolean equals(Object obj) {
554 return component.equals(obj);
555 }
556 }
558 @Override
559 public @NotNull Set<Component> getComponents() {
560 return componentRegistry;
561 }
563 public <T extends EndpointReference> T getEndpointReference(Class<T> clazz, String address, String wsdlAddress, Element... referenceParameters) {
564 List<Element> refParams = null;
565 if (referenceParameters != null) {
566 refParams = Arrays.asList(referenceParameters);
567 }
568 return getEndpointReference(clazz, address, wsdlAddress, null, refParams);
569 }
571 public <T extends EndpointReference> T getEndpointReference(Class<T> clazz,
572 String address, String wsdlAddress, List<Element> metadata,
573 List<Element> referenceParameters) {
574 QName portType = null;
575 if (port != null) {
576 portType = port.getBinding().getPortTypeName();
577 }
579 AddressingVersion av = AddressingVersion.fromSpecClass(clazz);
580 return new WSEndpointReference(
581 av, address, serviceName, portName, portType, metadata, wsdlAddress, referenceParameters, endpointReferenceExtensions.values(), null).toSpec(clazz);
583 }
585 public @NotNull QName getPortName() {
586 return portName;
587 }
590 public @NotNull Codec createCodec() {
591 return masterCodec.copy();
592 }
594 public @NotNull QName getServiceName() {
595 return serviceName;
596 }
598 private void initManagedObjectManager() {
599 synchronized (managedObjectManagerLock) {
600 if (managedObjectManager == null) {
601 switch (this.lazyMOMProviderScope) {
602 case GLASSFISH_NO_JMX:
603 managedObjectManager = new WSEndpointMOMProxy(this);
604 break;
605 default:
606 managedObjectManager = obtainManagedObjectManager();
607 }
608 }
609 }
610 }
612 public @NotNull ManagedObjectManager getManagedObjectManager() {
613 return managedObjectManager;
614 }
616 /**
617 * Obtains a real instance of {@code ManagedObjectManager} class no matter what lazyMOMProviderScope is this endpoint in (or if the
618 * Gmbal API calls should be deferred).
619 *
620 * @see com.sun.xml.internal.ws.api.server.LazyMOMProvider.Scope
621 * @return an instance of {@code ManagedObjectManager}
622 */
623 @NotNull ManagedObjectManager obtainManagedObjectManager() {
624 final MonitorRootService monitorRootService = new MonitorRootService(this);
625 final ManagedObjectManager mOM = monitorRootService.createManagedObjectManager(this);
627 // ManagedObjectManager was suspended due to root creation (see MonitorBase#initMOM)
628 mOM.resumeJMXRegistration();
630 return mOM;
631 }
633 public void scopeChanged(LazyMOMProvider.Scope scope) {
634 synchronized (managedObjectManagerLock) {
635 if (managedObjectManagerClosed) {
636 return;
637 }
639 this.lazyMOMProviderScope = scope;
641 // possible lazyMOMProviderScope change can be LazyMOMProvider.Scope.GLASSFISH_NO_JMX or LazyMOMProvider.Scope.GLASSFISH_JMX
642 if (managedObjectManager == null) {
643 if (scope != LazyMOMProvider.Scope.GLASSFISH_NO_JMX) {
644 managedObjectManager = obtainManagedObjectManager();
645 } else {
646 managedObjectManager = new WSEndpointMOMProxy(this);
647 }
648 } else {
649 // if ManagedObjectManager for this endpoint has already been created and is uninitialized proxy then
650 // fill it with a real instance
651 if (managedObjectManager instanceof WSEndpointMOMProxy
652 && !((WSEndpointMOMProxy)managedObjectManager).isInitialized()) {
653 ((WSEndpointMOMProxy)managedObjectManager).setManagedObjectManager(obtainManagedObjectManager());
654 }
655 }
656 }
657 }
659 private static final Logger monitoringLogger = Logger.getLogger(com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".monitoring");
661 // This can be called independently of WSEndpoint.dispose.
662 // Example: the WSCM framework calls this before dispose.
663 @Override
664 public void closeManagedObjectManager() {
665 synchronized (managedObjectManagerLock) {
666 if (managedObjectManagerClosed == true) {
667 return;
668 }
669 if (managedObjectManager != null) {
670 boolean close = true;
672 // ManagedObjectManager doesn't need to be closed because it exists only as a proxy
673 if (managedObjectManager instanceof WSEndpointMOMProxy
674 && !((WSEndpointMOMProxy)managedObjectManager).isInitialized()) {
675 close = false;
676 }
678 if (close) {
679 try {
680 final ObjectName name = managedObjectManager.getObjectName(managedObjectManager.getRoot());
681 // The name is null when the MOM is a NOOP.
682 if (name != null) {
683 monitoringLogger.log(Level.INFO, "Closing Metro monitoring root: {0}", name);
684 }
685 managedObjectManager.close();
686 } catch (java.io.IOException e) {
687 monitoringLogger.log(Level.WARNING, "Ignoring error when closing Managed Object Manager", e);
688 }
689 }
690 }
691 managedObjectManagerClosed = true;
692 }
693 }
695 public @NotNull @Override ServerTubeAssemblerContext getAssemblerContext() {
696 return context;
697 }
698 }