| /* |
| * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.sun.xml.internal.ws.server; |
| |
| import com.sun.istack.internal.NotNull; |
| import com.sun.istack.internal.Nullable; |
| import com.sun.xml.internal.ws.api.EndpointAddress; |
| import com.sun.xml.internal.ws.api.config.management.policy.ManagedClientAssertion; |
| import com.sun.xml.internal.ws.api.config.management.policy.ManagedServiceAssertion; |
| import com.sun.xml.internal.ws.api.config.management.policy.ManagementAssertion.Setting; |
| import com.sun.xml.internal.ws.api.server.BoundEndpoint; |
| import com.sun.xml.internal.ws.api.server.Container; |
| import com.sun.xml.internal.ws.api.server.Module; |
| import com.sun.xml.internal.ws.api.server.WSEndpoint; |
| import com.sun.xml.internal.ws.client.Stub; |
| import com.sun.org.glassfish.external.amx.AMXGlassfish; |
| import com.sun.org.glassfish.gmbal.Description; |
| import com.sun.org.glassfish.gmbal.InheritedAttribute; |
| import com.sun.org.glassfish.gmbal.InheritedAttributes; |
| import com.sun.org.glassfish.gmbal.ManagedData; |
| import com.sun.org.glassfish.gmbal.ManagedObjectManager; |
| import com.sun.org.glassfish.gmbal.ManagedObjectManagerFactory; |
| import java.io.IOException; |
| import java.lang.reflect.*; |
| import java.net.URL; |
| import java.util.List; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.management.ObjectName; |
| import javax.xml.namespace.QName; |
| |
| // BEGIN IMPORTS FOR RewritingMOM |
| import java.util.ResourceBundle ; |
| import java.io.Closeable ; |
| import java.lang.reflect.AnnotatedElement ; |
| import java.lang.annotation.Annotation ; |
| import javax.management.ObjectName ; |
| import javax.management.MBeanServer ; |
| import com.sun.org.glassfish.gmbal.AMXClient; |
| import com.sun.org.glassfish.gmbal.GmbalMBean; |
| // END IMPORTS FOR RewritingMOM |
| |
| /** |
| * @author Harold Carr |
| */ |
| public abstract class MonitorBase { |
| |
| private static final Logger logger = Logger.getLogger( |
| com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".monitoring"); |
| |
| /** |
| * Endpoint monitoring is ON by default. |
| * |
| * prop | no assert | assert/no mon | assert/mon off | assert/mon on |
| * ------------------------------------------------------------------- |
| * not set | on | on | off | on |
| * false | off | off | off | off |
| * true | on | on | off | on |
| */ |
| @NotNull public ManagedObjectManager createManagedObjectManager(final WSEndpoint endpoint) { |
| // serviceName + portName identifies the managed objects under it. |
| // There can be multiple services in the container. |
| // The same serviceName+portName can live in different apps at |
| // different endpoint addresses. |
| // |
| // In general, monitoring will add -N, where N is unique integer, |
| // in case of collisions. |
| // |
| // The endpoint address would be unique, but we do not know |
| // the endpoint address until the first request comes in, |
| // which is after monitoring is setup. |
| |
| String rootName = |
| endpoint.getServiceName().getLocalPart() |
| + "-" |
| + endpoint.getPortName().getLocalPart(); |
| |
| if (rootName.equals("-")) { |
| rootName = "provider"; |
| } |
| |
| // contextPath is not always available |
| final String contextPath = getContextPath(endpoint); |
| if (contextPath != null) { |
| rootName = contextPath + "-" + rootName; |
| } |
| |
| final ManagedServiceAssertion assertion = |
| ManagedServiceAssertion.getAssertion(endpoint); |
| if (assertion != null) { |
| final String id = assertion.getId(); |
| if (id != null) { |
| rootName = id; |
| } |
| if (assertion.monitoringAttribute() == Setting.OFF) { |
| return disabled("This endpoint", rootName); |
| } |
| } |
| |
| if (endpointMonitoring.equals(Setting.OFF)) { |
| return disabled("Global endpoint", rootName); |
| } |
| return createMOMLoop(rootName, 0); |
| } |
| |
| private String getContextPath(final WSEndpoint endpoint) { |
| try { |
| Container container = endpoint.getContainer(); |
| Method getSPI = |
| container.getClass().getDeclaredMethod("getSPI", Class.class); |
| getSPI.setAccessible(true); |
| Class servletContextClass = |
| Class.forName("javax.servlet.ServletContext"); |
| Object servletContext = |
| getSPI.invoke(container, servletContextClass); |
| if (servletContext != null) { |
| Method getContextPath = servletContextClass.getDeclaredMethod("getContextPath"); |
| getContextPath.setAccessible(true); |
| return (String) getContextPath.invoke(servletContext); |
| } |
| return null; |
| } catch (Throwable t) { |
| logger.log(Level.FINEST, "getContextPath", t); |
| } |
| return null; |
| } |
| |
| /** |
| * Client monitoring is OFF by default because there is |
| * no standard stub.close() method. Therefore people do |
| * not typically close a stub when they are done with it |
| * (even though the RI does provide a .close). |
| * <pre> |
| * prop | no assert | assert/no mon | assert/mon off | assert/mon on |
| * ------------------------------------------------------------------- |
| * not set | off | off | off | on |
| * false | off | off | off | off |
| * true | on | on | off | on |
| * </pre> |
| */ |
| @NotNull public ManagedObjectManager createManagedObjectManager(final Stub stub) { |
| EndpointAddress ea = stub.requestContext.getEndpointAddress(); |
| if (ea == null) { |
| return ManagedObjectManagerFactory.createNOOP(); |
| } |
| |
| String rootName = ea.toString(); |
| |
| final ManagedClientAssertion assertion = |
| ManagedClientAssertion.getAssertion(stub.getPortInfo()); |
| if (assertion != null) { |
| final String id = assertion.getId(); |
| if (id != null) { |
| rootName = id; |
| } |
| if (assertion.monitoringAttribute() == Setting.OFF) { |
| return disabled("This client", rootName); |
| } else if (assertion.monitoringAttribute() == Setting.ON && |
| clientMonitoring != Setting.OFF) { |
| return createMOMLoop(rootName, 0); |
| } |
| } |
| |
| if (clientMonitoring == Setting.NOT_SET || |
| clientMonitoring == Setting.OFF) |
| { |
| return disabled("Global client", rootName); |
| } |
| return createMOMLoop(rootName, 0); |
| } |
| |
| @NotNull private ManagedObjectManager disabled(final String x, final String rootName) { |
| final String msg = x + " monitoring disabled. " + rootName + " will not be monitored"; |
| logger.log(Level.CONFIG, msg); |
| return ManagedObjectManagerFactory.createNOOP(); |
| } |
| |
| private @NotNull ManagedObjectManager createMOMLoop(final String rootName, final int unique) { |
| final boolean isFederated = AMXGlassfish.getGlassfishVersion() != null; |
| ManagedObjectManager mom = createMOM(isFederated); |
| mom = initMOM(mom); |
| mom = createRoot(mom, rootName, unique); |
| return mom; |
| } |
| |
| private @NotNull ManagedObjectManager createMOM(final boolean isFederated) { |
| try { |
| return new RewritingMOM(isFederated ? |
| ManagedObjectManagerFactory.createFederated( |
| AMXGlassfish.DEFAULT.serverMon(AMXGlassfish.DEFAULT.dasName())) |
| : |
| ManagedObjectManagerFactory.createStandalone("com.sun.metro")); |
| } catch (Throwable t) { |
| if (isFederated) { |
| logger.log(Level.CONFIG, "Problem while attempting to federate with GlassFish AMX monitoring. Trying standalone.", t); |
| return createMOM(false); |
| } else { |
| logger.log(Level.WARNING, "Ignoring exception - starting up without monitoring", t); |
| return ManagedObjectManagerFactory.createNOOP(); |
| } |
| } |
| } |
| |
| private @NotNull ManagedObjectManager initMOM(final ManagedObjectManager mom) { |
| try { |
| if (typelibDebug != -1) { |
| mom.setTypelibDebug(typelibDebug); |
| } |
| if (registrationDebug.equals("FINE")) { |
| mom.setRegistrationDebug(ManagedObjectManager.RegistrationDebugLevel.FINE); |
| } else if (registrationDebug.equals("NORMAL")) { |
| mom.setRegistrationDebug(ManagedObjectManager.RegistrationDebugLevel.NORMAL); |
| } else { |
| mom.setRegistrationDebug(ManagedObjectManager.RegistrationDebugLevel.NONE); |
| } |
| |
| mom.setRuntimeDebug(runtimeDebug); |
| |
| // Instead of GMBAL throwing an exception and logging |
| // duplicate name, just have it return null. |
| mom.suppressDuplicateRootReport(true); |
| |
| mom.stripPrefix( |
| "com.sun.xml.internal.ws.server", |
| "com.sun.xml.internal.ws.rx.rm.runtime.sequence"); |
| |
| // Add annotations to a standard class |
| mom.addAnnotation(javax.xml.ws.WebServiceFeature.class, DummyWebServiceFeature.class.getAnnotation(ManagedData.class)); |
| mom.addAnnotation(javax.xml.ws.WebServiceFeature.class, DummyWebServiceFeature.class.getAnnotation(Description.class)); |
| mom.addAnnotation(javax.xml.ws.WebServiceFeature.class, DummyWebServiceFeature.class.getAnnotation(InheritedAttributes.class)); |
| |
| // Defer so we can register "this" as root from |
| // within constructor. |
| mom.suspendJMXRegistration(); |
| |
| } catch (Throwable t) { |
| try { |
| mom.close(); |
| } catch (IOException e) { |
| logger.log(Level.CONFIG, "Ignoring exception caught when closing unused ManagedObjectManager", e); |
| } |
| logger.log(Level.WARNING, "Ignoring exception - starting up without monitoring", t); |
| return ManagedObjectManagerFactory.createNOOP(); |
| } |
| return mom; |
| } |
| |
| private ManagedObjectManager createRoot(final ManagedObjectManager mom, final String rootName, int unique) { |
| final String name = rootName + (unique == 0 ? "" : "-" + String.valueOf(unique)); |
| try { |
| final Object ignored = mom.createRoot(this, name); |
| if (ignored != null) { |
| ObjectName ignoredName = mom.getObjectName(mom.getRoot()); |
| // The name is null when the MOM is a NOOP. |
| if (ignoredName != null) { |
| logger.log(Level.INFO, "Metro monitoring rootname successfully set to: " + ignoredName); |
| } |
| return mom; |
| } |
| try { |
| mom.close(); |
| } catch (IOException e) { |
| logger.log(Level.CONFIG, "Ignoring exception caught when closing unused ManagedObjectManager", e); |
| } |
| final String basemsg ="Duplicate Metro monitoring rootname: " + name + " : "; |
| if (unique > maxUniqueEndpointRootNameRetries) { |
| final String msg = basemsg + "Giving up."; |
| logger.log(Level.INFO, msg); |
| return ManagedObjectManagerFactory.createNOOP(); |
| } |
| final String msg = basemsg + "Will try to make unique"; |
| logger.log(Level.CONFIG, msg); |
| return createMOMLoop(rootName, ++unique); |
| } catch (Throwable t) { |
| logger.log(Level.WARNING, "Error while creating monitoring root with name: " + rootName, t); |
| return ManagedObjectManagerFactory.createNOOP(); |
| } |
| } |
| |
| public static void closeMOM(ManagedObjectManager mom) { |
| try { |
| final ObjectName name = mom.getObjectName(mom.getRoot()); |
| // The name is null when the MOM is a NOOP. |
| if (name != null) { |
| logger.log(Level.INFO, "Closing Metro monitoring root: " + name); |
| } |
| mom.close(); |
| } catch (java.io.IOException e) { |
| logger.log(Level.WARNING, "Ignoring error when closing Managed Object Manager", e); |
| } |
| } |
| |
| private static Setting clientMonitoring = Setting.NOT_SET; |
| private static Setting endpointMonitoring = Setting.NOT_SET; |
| private static int typelibDebug = -1; |
| private static String registrationDebug = "NONE"; |
| private static boolean runtimeDebug = false; |
| private static int maxUniqueEndpointRootNameRetries = 100; |
| private static final String monitorProperty = "com.sun.xml.internal.ws.monitoring."; |
| |
| private static Setting propertyToSetting(String propName) { |
| String s = System.getProperty(propName); |
| if (s == null) { |
| return Setting.NOT_SET; |
| } |
| s = s.toLowerCase(); |
| if (s.equals("false") || s.equals("off")) { |
| return Setting.OFF; |
| } else if (s.equals("true") || s.equals("on")) { |
| return Setting.ON; |
| } |
| return Setting.NOT_SET; |
| } |
| |
| static { |
| try { |
| endpointMonitoring = propertyToSetting(monitorProperty + "endpoint"); |
| |
| clientMonitoring = propertyToSetting(monitorProperty + "client"); |
| |
| Integer i = Integer.getInteger(monitorProperty + "typelibDebug"); |
| if (i != null) { |
| typelibDebug = i; |
| } |
| |
| String s = System.getProperty(monitorProperty + "registrationDebug"); |
| if (s != null) { |
| registrationDebug = s.toUpperCase(); |
| } |
| |
| s = System.getProperty(monitorProperty + "runtimeDebug"); |
| if (s != null && s.toLowerCase().equals("true")) { |
| runtimeDebug = true; |
| } |
| |
| i = Integer.getInteger(monitorProperty + "maxUniqueEndpointRootNameRetries"); |
| if (i != null) { |
| maxUniqueEndpointRootNameRetries = i; |
| } |
| } catch (Exception e) { |
| logger.log(Level.WARNING, "Error while reading monitoring properties", e); |
| } |
| } |
| } |
| |
| |
| // This enables us to annotate the WebServiceFeature class even thought |
| // we can't explicitly put the annotations in the class itself. |
| @ManagedData |
| @Description("WebServiceFeature") |
| @InheritedAttributes({ |
| @InheritedAttribute(methodName="getID", description="unique id for this feature"), |
| @InheritedAttribute(methodName="isEnabled", description="true if this feature is enabled") |
| }) |
| interface DummyWebServiceFeature {} |
| |
| class RewritingMOM implements ManagedObjectManager |
| { |
| private final ManagedObjectManager mom; |
| |
| private final static String gmbalQuotingCharsRegex = "\n|\\|\"|\\*|\\?|:|=|,"; |
| private final static String jmxQuotingCharsRegex = ",|=|:|\""; |
| private final static String replacementChar = "-"; |
| |
| RewritingMOM(final ManagedObjectManager mom) { this.mom = mom; } |
| |
| private String rewrite(final String x) { |
| return x.replaceAll(gmbalQuotingCharsRegex, replacementChar); |
| } |
| |
| // The interface |
| |
| public void suspendJMXRegistration() { mom.suspendJMXRegistration(); } |
| public void resumeJMXRegistration() { mom.resumeJMXRegistration(); } |
| public GmbalMBean createRoot() { return mom.createRoot(); } |
| public GmbalMBean createRoot(Object root) { return mom.createRoot(root); } |
| public GmbalMBean createRoot(Object root, String name) { |
| return mom.createRoot(root, rewrite(name)); |
| } |
| public Object getRoot() { return mom.getRoot(); } |
| public GmbalMBean register(Object parent, Object obj, String name) { |
| return mom.register(parent, obj, rewrite(name)); |
| } |
| public GmbalMBean register(Object parent, Object obj) { return mom.register(parent, obj);} |
| public GmbalMBean registerAtRoot(Object obj, String name) { |
| return mom.registerAtRoot(obj, rewrite(name)); |
| } |
| public GmbalMBean registerAtRoot(Object obj) { return mom.registerAtRoot(obj); } |
| public void unregister(Object obj) { mom.unregister(obj); } |
| public ObjectName getObjectName(Object obj) { return mom.getObjectName(obj); } |
| public AMXClient getAMXClient(Object obj) { return mom.getAMXClient(obj); } |
| public Object getObject(ObjectName oname) { return mom.getObject(oname); } |
| public void stripPrefix(String... str) { mom.stripPrefix(str); } |
| public void stripPackagePrefix() { mom.stripPackagePrefix(); } |
| public String getDomain() { return mom.getDomain(); } |
| public void setMBeanServer(MBeanServer server){mom.setMBeanServer(server); } |
| public MBeanServer getMBeanServer() { return mom.getMBeanServer(); } |
| public void setResourceBundle(ResourceBundle rb) { mom.setResourceBundle(rb); } |
| public ResourceBundle getResourceBundle() { return mom.getResourceBundle(); } |
| public void addAnnotation(AnnotatedElement element, Annotation annotation) { mom.addAnnotation(element, annotation); } |
| public void setRegistrationDebug(RegistrationDebugLevel level) { mom.setRegistrationDebug(level); } |
| public void setRuntimeDebug(boolean flag) { mom.setRuntimeDebug(flag); } |
| public void setTypelibDebug(int level) { mom.setTypelibDebug(level); } |
| public String dumpSkeleton(Object obj) { return mom.dumpSkeleton(obj); } |
| public void suppressDuplicateRootReport(boolean suppressReport) { mom.suppressDuplicateRootReport(suppressReport); } |
| public void close() throws IOException { mom.close(); } |
| public void setJMXRegistrationDebug(boolean x) { mom.setJMXRegistrationDebug(x); } |
| public boolean isManagedObject(Object x) { return mom.isManagedObject(x); } |
| } |
| |
| // End of file. |