/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.xml.config; import gw.config.ServiceKernel; import gw.internal.xml.IMarshaller; import gw.internal.xml.IXmlLoggerFactory; import gw.internal.xml.ws.server.IWsiWebService; import gw.internal.xml.ws.server.WsiUtilities; import gw.internal.xml.ws.server.marshal.MarshalContext; import gw.internal.xml.ws.server.marshal.UnmarshalContext; import gw.lang.parser.IParsedElement; import gw.lang.reflect.IType; import gw.lang.reflect.ReflectUtil; import gw.util.ILogger; import gw.util.SystemOutLogger; import gw.xml.XmlElement; import java.util.Map; public class XmlServices extends ServiceKernel { private static String _xmlLoggerFactoryClassName = "gw.internal.xml.XmlLoggerFactory"; private static String _marshallerClassName = "gw.internal.xml.Marshaller"; private static XmlServices _instance; private XmlServices() { } public static XmlServices getInstance() { if (_instance == null) { _instance = new XmlServices(); } return _instance; } protected void defineServices() { _instance = this; try { defineService( IXmlLoggerFactory.class, (IXmlLoggerFactory)Class.forName(_xmlLoggerFactoryClassName).newInstance() ); defineService( IMarshaller.class, (IMarshaller)Class.forName(_marshallerClassName).newInstance() ); } catch( Exception e ) { throw new RuntimeException( e ); } catch( NoClassDefFoundError e) { e.printStackTrace(); throw e; } } @Override protected void redefineServices() { // don't really want to do this here via another class // only have a couple of services, and the calling system can use // redefineService(Class<? extends T> service, Q newProvider) } public static void redefineService(Class serviceInterface, String className) { if (IXmlLoggerFactory.class.equals(serviceInterface)) { _xmlLoggerFactoryClassName = className; if (_instance != null) { final IXmlLoggerFactory factory = _instance.getService(IXmlLoggerFactory.class); if (factory != null /* && !factory.getClass().getName().equals(className)*/) { // logging properties may have changed _instance.resetKernel(); } } } else if (IMarshaller.class.equals(serviceInterface)) { _marshallerClassName = className; if (_instance != null) { final IMarshaller service = _instance.getService(IMarshaller.class); if (service != null && !service.getClass().getName().equals(className)) { _instance.resetKernel(); } } } } /** This will get the logger for the specific type * * @param category the category needed * @return the logger */ public static ILogger getLogger( IXmlLoggerFactory.Category category) { return getInstance().getService(IXmlLoggerFactory.class).getLogger(category); } /** This will get the logger for any custom category, it will also initialize it to * a console appender at warning level if not otherwise configured. * * @param category the category needed * @param level the level to set this temporary logger to * @return the logger */ public static ILogger getTempLogger(String category, SystemOutLogger.LoggingLevel level) { return getInstance().getService(IXmlLoggerFactory.class).getTempLogger(category, level); } /** This will get the logger for any custom category, it will also initialize it to * a console appender at warning level if not otherwise configured. * * @param category the category needed * @return the logger */ public static ILogger getLogger(String category) { return getInstance().getService(IXmlLoggerFactory.class).getLogger(category); } /** this will check that the supplied type is valid for a webservice, if it is not valid it will format a exception on the * parsedElement. * * @param parsedElement the element to attach warnings and errors to. * @param name the parameter name or "return" * @param type the type of the parameter or return value * @param seenNamespaces a map of namespaces already seen, a caller should treat this as opaque and ignore */ public static void checkWsiWebServiceType(IParsedElement parsedElement, String name, IType type, Map<String, Object> seenNamespaces) { getInstance().getService(IMarshaller.class).checkType(parsedElement, name, type, seenNamespaces); } /** this will create the target namespace for this type * * @param type to create a target namespace for * @return the uri for this type */ public static String createTargetNamespace( IType type ) { @SuppressWarnings( {"deprecation"} ) IWsiWebService clsAnnot = (IWsiWebService) ReflectUtil.evaluateAnnotation( type.getTypeInfo().getAnnotationsOfType( WsiUtilities.WSI_WEB_SERVICE_ANNOTATION_TYPE.get() ).get( 0 ) ); if ( clsAnnot.getTargetNamespace() == null ) { return getInstance().getService( IMarshaller.class ).createTargetNamespace( null, type ); } else { return clsAnnot.getTargetNamespace(); } } /** this will create the target namespace for this relative path * * @param path to create a target namespace for * @return the uri for this type */ public static String createTargetNamespace( String path ) { return getInstance().getService( IMarshaller.class ).createTargetNamespace( null, path ); } /** This will create elements for the type in the target. * * @param parameterElement where to write the value * @param type the expected type of the object (e.g., may be an interface) * @param obj the actual object * @param context the context for this marshalling */ public static void marshal(XmlElement parameterElement, IType type, Object obj, MarshalContext context) { getInstance().getService( IMarshaller.class ).marshal(parameterElement, type, obj, context); } /** This will create an object from the xml element. There are several marshalling * attributes that will affect this behavior. * * @param type the type desired * @param parameterElement the element to unmarshal * @param context the context for this unmarshalling * @return the create and populated object * @throws Exception on error */ public static Object unmarshal(IType type, XmlElement parameterElement, UnmarshalContext context) { return getInstance().getService( IMarshaller.class ).unmarshal(type, parameterElement, context); } }