From 0c793c2f84459bf7a9e93d8648355d4f75eee9b1 Mon Sep 17 00:00:00 2001 From: David BRASSELY Date: Thu, 16 Apr 2015 21:01:41 +0200 Subject: [PATCH] OESE-85 Let JNDI context provider reading XML files from a single directory --- .../openesb/standalone/LocalStringKeys.java | 8 ++ .../standalone/naming/ContextProvider.java | 2 +- .../naming/jndi/AbstractContextFactory.java | 82 +++++++++++++++++++ .../naming/jndi/InitialContexFactoryImpl.java | 81 ++++++++---------- .../naming/jndi/JAXBContextReader.java | 22 ++--- .../node/internal/InstanceNode.java | 16 ++-- .../net/openesb/standalone/Bundle.properties | 6 +- 7 files changed, 151 insertions(+), 66 deletions(-) create mode 100644 openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/AbstractContextFactory.java diff --git a/openesb-standalone-container/src/main/java/net/openesb/standalone/LocalStringKeys.java b/openesb-standalone-container/src/main/java/net/openesb/standalone/LocalStringKeys.java index 66a35b6..5dd1415 100644 --- a/openesb-standalone-container/src/main/java/net/openesb/standalone/LocalStringKeys.java +++ b/openesb-standalone-container/src/main/java/net/openesb/standalone/LocalStringKeys.java @@ -82,6 +82,14 @@ public interface LocalStringKeys { "NAMING_UNMARSHAL_FAILURE"; static final String NAMING_UNMARSHAL_SUCCESS = "NAMING_UNMARSHAL_SUCCESS"; + static final String NAMING_CONTEXT_LOADING_URL = + "NAMING_CONTEXT_LOADING_URL"; + static final String NAMING_CONTEXT_BIND_FAILURE = + "NAMING_CONTEXT_BIND_FAILURE"; + static final String NAMING_CONTEXT_SCHEMA_FAILURE = + "NAMING_CONTEXT_SCHEMA_FAILURE"; + static final String NAMING_CONTEXT_JAXB_FAILURE = + "NAMING_CONTEXT_JAXB_FAILURE"; /** * HTTP Messages. diff --git a/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/ContextProvider.java b/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/ContextProvider.java index 9fef781..1099ea5 100644 --- a/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/ContextProvider.java +++ b/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/ContextProvider.java @@ -23,7 +23,7 @@ import net.openesb.standalone.utils.StringUtils; public class ContextProvider implements Provider { private static final Logger LOG = - Logger.getLogger(ContextProvider.class.getPackage().getName()); + Logger.getLogger(ContextProvider.class.getName()); private static final String DEFAULT_CONTEXT_XML = "${openesb.home}/config/context.xml"; private static final String CONTEXT_PATH = "jndi.context"; diff --git a/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/AbstractContextFactory.java b/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/AbstractContextFactory.java new file mode 100644 index 0000000..cd2fa93 --- /dev/null +++ b/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/AbstractContextFactory.java @@ -0,0 +1,82 @@ +package net.openesb.standalone.naming.jndi; + +import java.io.File; +import java.io.FilenameFilter; +import java.net.URL; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.openesb.standalone.LocalStringKeys; +import net.openesb.standalone.naming.jaxb.Context; +import net.openesb.standalone.utils.I18NBundle; + +/** + * + * @author David BRASSELY (brasseld at gmail.com) + * @author OpenESB Community + */ +public abstract class AbstractContextFactory { + + private static final Logger LOG = Logger.getLogger(AbstractContextFactory.class.getName()); + + protected Set loadContexts(String providerUrl) { + if (providerUrl == null) { + LOG.log(Level.SEVERE, I18NBundle.getBundle().getMessage( + LocalStringKeys.NAMING_CONTEXT_NO_CONTEXT_URL)); + + return Collections.EMPTY_SET; + } + + try { + File providerFile = new File(new URL(providerUrl).toURI()); + + if (providerFile.isDirectory()) { + // Load XML Files + File[] potentialFiles = providerFile.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".xml"); + } + }); + + // Check if we can read them using JAXB + return loadContexts(potentialFiles); + } else { + return loadContexts(providerFile); + } + + } catch (Exception ex) { + Logger.getLogger(AbstractContextFactory.class.getName()).log(Level.SEVERE, null, ex); + return Collections.EMPTY_SET; + } + } + + private Set loadContexts(File... contextFiles) { + JAXBContextReader contextReader; + + try { + contextReader = new JAXBContextReader(); + } catch (Exception ex) { + LOG.log(Level.SEVERE, null, ex); + return Collections.EMPTY_SET; + } + + Set contexts = new HashSet(contextFiles.length); + for (File contextFile : contextFiles) { + try { + LOG.log(Level.INFO, I18NBundle.getBundle().getMessage( + LocalStringKeys.NAMING_CONTEXT_LOADING_URL, contextFile)); + + Context context = contextReader.getContext(contextFile.toURI().toURL()); + contexts.add(context); + } catch (Exception ex) { + LOG.log(Level.SEVERE, I18NBundle.getBundle().getMessage( + LocalStringKeys.NAMING_CONTEXT_CONTEXT_URL_INVALID, contextFile), ex); + } + } + + return contexts; + } +} diff --git a/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/InitialContexFactoryImpl.java b/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/InitialContexFactoryImpl.java index 777cb79..1091a19 100644 --- a/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/InitialContexFactoryImpl.java +++ b/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/InitialContexFactoryImpl.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.Context; @@ -26,55 +27,46 @@ import net.openesb.standalone.utils.I18NBundle; * @author David BRASSELY (brasseld at gmail.com) * @author OpenESB Community */ -public class InitialContexFactoryImpl implements InitialContextFactory { +public class InitialContexFactoryImpl extends AbstractContextFactory implements InitialContextFactory { private static final Logger LOG = Logger.getLogger(InitialContexFactoryImpl.class.getName()); public static final String DATASOURCE_TYPE = "Datasource"; public static final String XADATASOURCE_TYPE = "XADatasource"; private final Map mDSPMap = new HashMap(); - -// @Inject - private DataSourcePoolFactory mDSPFactory = new TomcatDataSourcePoolFactory(); + private final DataSourcePoolFactory mDSPFactory = new TomcatDataSourcePoolFactory(); - /* Regarding the exception management, If the context file if not correct, - * I choosed to return an initial context in any case even empty. So if input data - is not correct, I log this information but catch the exception in order to return - an initial context. Another policy would be to stop at any exception. I did not choose - it. Naming exception will be thrown only if I cannot create the initial context */ - /* The initial context I use is the one found in Tomcat 7 */ @Override public Context getInitialContext(Hashtable environment) throws NamingException { + Context namingContext = getContext(); + + String urlValue = (String) environment.get(Context.PROVIDER_URL); + if (urlValue == null) { + LOG.log(Level.SEVERE, I18NBundle.getBundle().getMessage( + LocalStringKeys.NAMING_CONTEXT_NO_CONTEXT_URL)); + } else { + Set contexts = loadContexts(urlValue); + for (net.openesb.standalone.naming.jaxb.Context context : contexts) { + try { + populate(context, namingContext); + } catch (NamingException ne) { + LOG.log(Level.SEVERE, I18NBundle.getBundle().getMessage( + LocalStringKeys.NAMING_CONTEXT_BIND_FAILURE)); + } + } + } + + return namingContext; + } + + private Context getContext() throws NamingException { /*Context initialisation Just set the system properties and use the class InitialContext*/ System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory"); System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming"); - Context initialContext = new InitialContext(); - - /* Second step read the XML file URL where context configuration is described - * The URL can be file:// http:// ... - * The XML File URL must be in environement hashmap and read the key URL must be equal to - * CONTEXT_URL*/ - String urlValue = null; - if (environment.containsKey(Context.PROVIDER_URL)) { - urlValue = (String) environment.get(Context.PROVIDER_URL); - } else { - LOG.log(Level.SEVERE, I18NBundle.getBundle().getMessage( - LocalStringKeys.NAMING_CONTEXT_NO_CONTEXT_URL)); - } - - /* Read the context from the URL */ - net.openesb.standalone.naming.jaxb.Context context = null; - - try { - context = new JAXBContextReader(urlValue).getContext(); - } catch (Exception ex) { - LOG.log(Level.SEVERE, I18NBundle.getBundle().getMessage( - LocalStringKeys.NAMING_CONTEXT_CONTEXT_URL_INVALID, urlValue), ex); - - // Skip context population - return initialContext; - } + return new InitialContext(); + } + private void populate(net.openesb.standalone.naming.jaxb.Context context, Context namingContext) throws NamingException { /* OeContext contains the complete context */ /* I create a map with the datasourcePool Name as key and datasourcePool as Value * This will be useful to instanciate the db connector later. @@ -116,16 +108,15 @@ public class InitialContexFactoryImpl implements InitialContextFactory { * second instance is not taken into account */ try { - initialContext.lookup(jndiName); + namingContext.lookup(jndiName); LOG.log(Level.FINE, I18NBundle.getBundle().getMessage("jndi.value.already.defined", jndiName)); continue; } catch (NamingException ex) { // Nothing else to do. Having an exception is the normal process } - Map datasourceMap = new HashMap(); - + /* Create datasource or XA Datasource thanks to the underlying dbConnector * DBConnector refeence is in the DataSourcePoolProperties. DBConnector are instanciated * dynamically and must be present in the classpath @@ -136,9 +127,9 @@ public class InitialContexFactoryImpl implements InitialContextFactory { */ if (datasourceMap.containsKey(dbConnectorName)) { if (datasourceMap.get(dbConnectorName) instanceof XADataSource) { - initialContext.rebind(jndiName, (XADataSource) datasourceMap.get(dbConnectorName)); + namingContext.rebind(jndiName, (XADataSource) datasourceMap.get(dbConnectorName)); } else { - initialContext.rebind(jndiName, datasourceMap.get(dbConnectorName)); + namingContext.rebind(jndiName, datasourceMap.get(dbConnectorName)); } continue; } @@ -154,9 +145,9 @@ public class InitialContexFactoryImpl implements InitialContextFactory { if (null != dataSource) { datasourceMap.put(dbConnectorName, dataSource); try { - initialContext.rebind(jndiName, dataSource); + namingContext.rebind(jndiName, dataSource); } catch (NamingException ex) { - initialContext.bind(jndiName, dataSource); + namingContext.bind(jndiName, dataSource); } LOG.log(Level.FINE, I18NBundle.getBundle().getMessage("datasource.processed.bind.success", jndiName)); } @@ -168,7 +159,7 @@ public class InitialContexFactoryImpl implements InitialContextFactory { if (null != xaDataSource) { /* Store the XAdatasource in a map for reusing purpose see above */ datasourceMap.put(dbConnectorName, (DataSource) xaDataSource); - initialContext.rebind(jndiName, xaDataSource); + namingContext.rebind(jndiName, xaDataSource); LOG.log(Level.FINE, I18NBundle.getBundle().getMessage("xadatasource.processed.bind.success", jndiName)); } } else { @@ -177,7 +168,5 @@ public class InitialContexFactoryImpl implements InitialContextFactory { } } } - - return initialContext; } } diff --git a/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/JAXBContextReader.java b/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/JAXBContextReader.java index d4fa505..940e388 100644 --- a/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/JAXBContextReader.java +++ b/openesb-standalone-container/src/main/java/net/openesb/standalone/naming/jndi/JAXBContextReader.java @@ -7,6 +7,7 @@ import java.util.logging.Logger; import javax.xml.XMLConstants; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.bind.ValidationEvent; import javax.xml.bind.ValidationEventHandler; @@ -16,6 +17,7 @@ import net.openesb.standalone.Constants; import net.openesb.standalone.LocalStringKeys; import net.openesb.standalone.naming.jaxb.Context; import net.openesb.standalone.utils.I18NBundle; +import org.xml.sax.SAXException; /** * @@ -27,11 +29,8 @@ public final class JAXBContextReader { private static final Logger LOG = Logger.getLogger(JAXBContextReader.class.getName()); private final Unmarshaller unmarshaller; - private final String contextFile; - - public JAXBContextReader(String contextFile) throws Exception { - this.contextFile = contextFile; + public JAXBContextReader() throws Exception { try { SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); @@ -53,17 +52,20 @@ public final class JAXBContextReader { return false; } }); - } catch (Exception ex) { + } catch (SAXException saxe) { LOG.log(Level.SEVERE, I18NBundle.getBundle().getMessage( - LocalStringKeys.NAMING_CONTEXT_CONTEXT_URL_INVALID, contextFile)); - - throw ex; + LocalStringKeys.NAMING_CONTEXT_SCHEMA_FAILURE)); + throw saxe; + } catch (JAXBException jaxbe) { + LOG.log(Level.SEVERE, I18NBundle.getBundle().getMessage( + LocalStringKeys.NAMING_CONTEXT_JAXB_FAILURE)); + throw jaxbe; } } - public Context getContext() throws Exception { + public Context getContext(URL contextUrl) throws Exception { Context context = ((JAXBElement) unmarshaller.unmarshal( - new URL(contextFile))).getValue(); + contextUrl)).getValue(); if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, I18NBundle.getBundle().getMessage( diff --git a/openesb-standalone-container/src/main/java/net/openesb/standalone/node/internal/InstanceNode.java b/openesb-standalone-container/src/main/java/net/openesb/standalone/node/internal/InstanceNode.java index 6036d18..1e4e341 100644 --- a/openesb-standalone-container/src/main/java/net/openesb/standalone/node/internal/InstanceNode.java +++ b/openesb-standalone-container/src/main/java/net/openesb/standalone/node/internal/InstanceNode.java @@ -91,10 +91,6 @@ public class InstanceNode implements Node { } long startTime = System.currentTimeMillis(); // Get the start Time - - for (Class plugin : pluginsService.services()) { - injector.getInstance(plugin).start(); - } jMXService = injector.getInstance(JMXService.class); jMXService.start(); @@ -105,6 +101,10 @@ public class InstanceNode implements Node { injector.getInstance(FrameworkService.class).start(); injector.getInstance(HttpServer.class).start(); + for (Class plugin : pluginsService.services()) { + injector.getInstance(plugin).start(); + } + PlatformContext platformContext = injector.getInstance(PlatformContext.class); try { @@ -146,15 +146,15 @@ public class InstanceNode implements Node { LocalStringKeys.CONTAINER_STOP_INSTANCE), nodeName); } + for (Class plugin : pluginsService.services()) { + injector.getInstance(plugin).stop(); + } + injector.getInstance(HttpServer.class).stop(); injector.getInstance(FrameworkService.class).stop(); tmService.stop(); jMXService.stop(); - for (Class plugin : pluginsService.services()) { - injector.getInstance(plugin).stop(); - } - if (LOG.isLoggable(Level.INFO)) { LOG.log(Level.INFO, I18NBundle.getBundle().getMessage( LocalStringKeys.CONTAINER_STOP_INSTANCE_DONE), nodeName); diff --git a/openesb-standalone-container/src/main/resources/net/openesb/standalone/Bundle.properties b/openesb-standalone-container/src/main/resources/net/openesb/standalone/Bundle.properties index 9965603..25b4dd1 100644 --- a/openesb-standalone-container/src/main/resources/net/openesb/standalone/Bundle.properties +++ b/openesb-standalone-container/src/main/resources/net/openesb/standalone/Bundle.properties @@ -51,12 +51,16 @@ SETTINGS_CONFIGURATION_FAILURE = OESE-1302: Unable to load configuration file { # OpenESB Standalone : Naming messages (14xx) # ============================================================================ # -NAMING_CONTEXT_PATH = OESE-1400: Preparing naming context using file {0} +NAMING_CONTEXT_PATH = OESE-1400: Preparing JNDI Naming Context from {0}. NAMING_CONTEXT_INVALID_PATH = OESE-1401: Unable to create naming context, invalid path: {0}. NAMING_CONTEXT_NO_CONTEXT_URL = OESE-1402: Context URL is not provided. NAMING_CONTEXT_CONTEXT_URL_INVALID = OESE-1403: Context URL <{0}> is malformed. NAMING_UNMARSHAL_FAILURE = OESE-1404: Unmarshalling failed with the provided URL {0}. NAMING_UNMARSHAL_SUCCESS = OESE-1405: Naming context have been unmarshalled successfully. +NAMING_CONTEXT_LOADING_URL = OESE-1406: Loading context from {0}. +NAMING_CONTEXT_BIND_FAILURE = OESE-1407: JNDI binding fails. +NAMING_CONTEXT_SCHEMA_FAILURE = OESE-1408: An error occurs while loading XML Schema for JNDI Naming Context. +NAMING_CONTEXT_JAXB_FAILURE = OESE-1409: An error occurs while preparing JAXB unmarshaller. # # ============================================================================