| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.openejb.config; |
| |
| import org.apache.openejb.OpenEJBException; |
| import org.apache.openejb.cdi.CompositeBeans; |
| import org.apache.openejb.config.sys.JSonConfigReader; |
| import org.apache.openejb.config.sys.JaxbOpenejb; |
| import org.apache.openejb.config.sys.Resource; |
| import org.apache.openejb.config.sys.Resources; |
| import org.apache.openejb.core.ParentClassLoaderFinder; |
| import org.apache.openejb.jee.ApplicationClient; |
| import org.apache.openejb.jee.Beans; |
| import org.apache.openejb.jee.Connector; |
| import org.apache.openejb.jee.Connector10; |
| import org.apache.openejb.jee.EjbJar; |
| import org.apache.openejb.jee.FacesConfig; |
| import org.apache.openejb.jee.HandlerChains; |
| import org.apache.openejb.jee.JavaWsdlMapping; |
| import org.apache.openejb.jee.JaxbJavaee; |
| import org.apache.openejb.jee.Keyable; |
| import org.apache.openejb.jee.Listener; |
| import org.apache.openejb.jee.TldTaglib; |
| import org.apache.openejb.jee.WebApp; |
| import org.apache.openejb.jee.WebFragment; |
| import org.apache.openejb.jee.Webservices; |
| import org.apache.openejb.jee.bval.ValidationConfigType; |
| import org.apache.openejb.jee.jpa.EntityMappings; |
| import org.apache.openejb.jee.jpa.fragment.PersistenceFragment; |
| import org.apache.openejb.jee.jpa.fragment.PersistenceUnitFragment; |
| import org.apache.openejb.jee.jpa.unit.JaxbPersistenceFactory; |
| import org.apache.openejb.jee.jpa.unit.Persistence; |
| import org.apache.openejb.jee.jpa.unit.PersistenceUnit; |
| import org.apache.openejb.jee.oejb2.GeronimoEjbJarType; |
| import org.apache.openejb.jee.oejb2.JaxbOpenejbJar2; |
| import org.apache.openejb.jee.oejb2.OpenejbJarType; |
| import org.apache.openejb.jee.oejb3.JaxbOpenejbJar3; |
| import org.apache.openejb.jee.oejb3.OpenejbJar; |
| import org.apache.openejb.loader.IO; |
| import org.apache.openejb.loader.SystemInstance; |
| import org.apache.openejb.sxc.ApplicationClientXml; |
| import org.apache.openejb.sxc.EjbJarXml; |
| import org.apache.openejb.sxc.FacesConfigXml; |
| import org.apache.openejb.sxc.HandlerChainsXml; |
| import org.apache.openejb.sxc.TldTaglibXml; |
| import org.apache.openejb.sxc.WebXml; |
| import org.apache.openejb.sxc.WebservicesXml; |
| import org.apache.openejb.util.LengthInputStream; |
| import org.apache.openejb.util.LogCategory; |
| import org.apache.openejb.util.Logger; |
| import org.apache.openejb.util.Saxs; |
| import org.apache.openejb.util.URLs; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| import javax.xml.bind.JAXBElement; |
| import javax.xml.bind.JAXBException; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.parsers.SAXParser; |
| import javax.xml.parsers.SAXParserFactory; |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URL; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.Map; |
| |
| public class ReadDescriptors implements DynamicDeployer { |
| private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP, ReadDescriptors.class); |
| |
| private static final boolean ROOT_URL_FROM_WEBINF = SystemInstance.get().getOptions().get("openejb.jpa.root-url-from-webinf", false); |
| |
| public static final TldTaglib SKIP_TAGLIB = new TldTaglib(); |
| |
| @SuppressWarnings({"unchecked"}) |
| public AppModule deploy(final AppModule appModule) throws OpenEJBException { |
| for (final EjbModule ejbModule : appModule.getEjbModules()) { |
| |
| if (ejbModule.getEjbJar() == null) { |
| readEjbJar(ejbModule, appModule); |
| } |
| |
| if (ejbModule.getOpenejbJar() == null) { |
| readOpenejbJar(ejbModule); |
| } |
| |
| if (ejbModule.getBeans() == null) { |
| readBeans(ejbModule); |
| } |
| |
| readValidationConfigType(ejbModule); |
| readCmpOrm(ejbModule); |
| readResourcesXml(ejbModule); |
| } |
| |
| for (final ClientModule clientModule : appModule.getClientModules()) { |
| readAppClient(clientModule, appModule); |
| readValidationConfigType(clientModule); |
| readResourcesXml(clientModule); |
| } |
| |
| for (final ConnectorModule connectorModule : appModule.getConnectorModules()) { |
| readConnector(connectorModule, appModule); |
| readValidationConfigType(connectorModule); |
| readResourcesXml(connectorModule); |
| } |
| |
| for (final WebModule webModule : appModule.getWebModules()) { |
| readWebApp(webModule, appModule); |
| readValidationConfigType(webModule); |
| readResourcesXml(webModule); |
| } |
| |
| final List<Object> persistenceUrls = (List<Object>) appModule.getAltDDs().get("persistence.xml"); |
| if (persistenceUrls != null) { |
| for (final Object persistenceUrl : persistenceUrls) { |
| final boolean url = persistenceUrl instanceof URL; |
| final Source source = getSource(persistenceUrl); |
| |
| final String moduleName; |
| final String path; |
| final String rootUrl; |
| if (url) { |
| final URL pUrl = (URL) persistenceUrl; |
| File file = URLs.toFile(pUrl); |
| path = file.getAbsolutePath(); |
| |
| if (file.getName().endsWith("persistence.xml")) { |
| final File parentFile = file.getParentFile(); |
| final String parent = parentFile.getName(); |
| if (parent.equalsIgnoreCase("WEB-INF") || parent.equalsIgnoreCase("META-INF")) { |
| file = parentFile.getParentFile(); |
| } else { // we don't really know so simply go back (users will often put persistence.xml in root resource folder with arquillian) |
| file = file.getParentFile(); |
| } |
| } |
| moduleName = file.toURI().toString(); |
| |
| String tmpRootUrl = moduleName; |
| |
| final String extForm = pUrl.toExternalForm(); |
| if (extForm.contains("WEB-INF/classes/META-INF/")) { |
| if (!ROOT_URL_FROM_WEBINF) { |
| tmpRootUrl = extForm.substring(0, extForm.indexOf("/META-INF")); |
| } else { |
| tmpRootUrl = extForm.substring(0, extForm.indexOf("/classes/META-INF")); |
| } |
| } |
| if (tmpRootUrl.endsWith(".war")) { |
| tmpRootUrl = tmpRootUrl.substring(0, tmpRootUrl.length() - ".war".length()); |
| } |
| rootUrl = tmpRootUrl; |
| } else { |
| moduleName = ""; |
| rootUrl = ""; |
| path = null; |
| } |
| |
| try { |
| final Persistence persistence = JaxbPersistenceFactory.getPersistence(Persistence.class, source.get()); |
| final PersistenceModule persistenceModule = new PersistenceModule(appModule, rootUrl, persistence); |
| persistenceModule.getWatchedResources().add(moduleName); |
| if (url && "file".equals(((URL) persistenceUrl).getProtocol())) { |
| persistenceModule.getWatchedResources().add(path); |
| } |
| appModule.addPersistenceModule(persistenceModule); |
| } catch (final Exception e1) { |
| DeploymentLoader.LOGGER.error("Unable to load Persistence Unit from EAR: " + appModule.getJarLocation() + ", module: " + moduleName + ". Exception: " + e1.getMessage(), e1); |
| } |
| } |
| } |
| |
| final List<URL> persistenceFragmentUrls = (List<URL>) appModule.getAltDDs().get("persistence-fragment.xml"); |
| if (persistenceFragmentUrls != null) { |
| for (final URL persistenceFragmentUrl : persistenceFragmentUrls) { |
| try { |
| final PersistenceFragment persistenceFragment = JaxbPersistenceFactory.getPersistence(PersistenceFragment.class, persistenceFragmentUrl); |
| // merging |
| for (final PersistenceUnitFragment fragmentUnit : persistenceFragment.getPersistenceUnitFragment()) { |
| for (final PersistenceModule persistenceModule : appModule.getPersistenceModules()) { |
| final Persistence persistence = persistenceModule.getPersistence(); |
| for (final PersistenceUnit unit : persistence.getPersistenceUnit()) { |
| if (!fragmentUnit.getName().equals(unit.getName())) { |
| continue; |
| } |
| |
| if (!persistenceFragment.getVersion().equals(persistence.getVersion())) { |
| logger.error("persistence unit version and fragment version are different, fragment will be ignored"); |
| continue; |
| } |
| |
| if ("file".equals(persistenceFragmentUrl.getProtocol())) { |
| persistenceModule.getWatchedResources().add(URLs.toFile(persistenceFragmentUrl).getAbsolutePath()); |
| } |
| |
| for (final String clazz : fragmentUnit.getClazz()) { |
| if (!unit.getClazz().contains(clazz)) { |
| logger.info("Adding class " + clazz + " to persistence unit " + fragmentUnit.getName()); |
| unit.getClazz().add(clazz); |
| } |
| } |
| for (final String mappingFile : fragmentUnit.getMappingFile()) { |
| if (!unit.getMappingFile().contains(mappingFile)) { |
| logger.info("Adding mapping file " + mappingFile + " to persistence unit " + fragmentUnit.getName()); |
| unit.getMappingFile().add(mappingFile); |
| } |
| } |
| for (final String jarFile : fragmentUnit.getJarFile()) { |
| if (!unit.getJarFile().contains(jarFile)) { |
| logger.info("Adding jar file " + jarFile + " to persistence unit " + fragmentUnit.getName()); |
| unit.getJarFile().add(jarFile); |
| } |
| } |
| if (fragmentUnit.isExcludeUnlistedClasses()) { |
| unit.setExcludeUnlistedClasses(true); |
| logger.info("Excluding unlisted classes for persistence unit " + fragmentUnit.getName()); |
| } // else let the main persistence unit decide |
| } |
| } |
| } |
| } catch (final Exception e1) { |
| DeploymentLoader.LOGGER.error("Unable to load Persistence Unit Fragment from EAR: " + appModule.getJarLocation() + ", fragment: " + persistenceFragmentUrl.toString() + ". Exception: " + e1.getMessage(), e1); |
| } |
| } |
| } |
| |
| return appModule; |
| } |
| |
| public static void readResourcesXml(final Module module) { |
| { // xml |
| final Source url = getSource(module.getAltDDs().get("resources.xml")); |
| if (url != null) { |
| try { |
| final Resources openejb = JaxbOpenejb.unmarshal(Resources.class, url.get()); |
| module.initResources(check(openejb)); |
| } catch (final Exception e) { |
| logger.warning("can't read " + url.toString() + " to load resources for module " + module.toString(), e); |
| } |
| } |
| } |
| { // json |
| final Source url = getSource(module.getAltDDs().get("resources.json")); |
| if (url != null) { |
| try { |
| final Resources openejb = JSonConfigReader.read(Resources.class, url.get()); |
| module.initResources(check(openejb)); |
| } catch (final Exception e) { |
| logger.warning("can't read " + url.toString() + " to load resources for module " + module.toString(), e); |
| } |
| } |
| } |
| } |
| |
| public static Resources check(final Resources resources) { |
| final List<Resource> resourceList = resources.getResource(); |
| for (final Resource resource : resourceList) { |
| if (resource.getClassName() != null) { |
| try { |
| ParentClassLoaderFinder.Helper.get().loadClass(resource.getClassName()); |
| continue; |
| } catch (Exception e) { |
| // ignore if this class is not found in the classloader |
| } |
| |
| // if the resource class cannot be loaded, |
| // set the lazy property to true |
| // and the app classloader property to true |
| |
| final Boolean lazySpecified = Boolean.valueOf(resource.getProperties().getProperty("Lazy", "false")); |
| |
| resource.getProperties().setProperty("Lazy", "true"); |
| resource.getProperties().setProperty("UseAppClassLoader", "true"); |
| |
| if (!lazySpecified) { |
| resource.getProperties().setProperty("InitializeAfterDeployment", "true"); |
| } |
| } |
| } |
| |
| return resources; |
| } |
| |
| private void readValidationConfigType(final Module module) throws OpenEJBException { |
| if (module.getValidationConfig() != null) { |
| return; |
| } |
| |
| final Source value = getSource(module.getAltDDs().get("validation.xml")); |
| if (value != null) { |
| try { |
| final ValidationConfigType validationConfigType = JaxbOpenejb.unmarshal( |
| ValidationConfigType.class, value.get(), false, |
| "http://xmlns.jcp.org/xml/ns/validation/configuration", |
| "http://jboss.org/xml/ns/javax/validation/configuration"); |
| module.setValidationConfig(validationConfigType); |
| } catch (final Exception e) { |
| logger.warning("can't read validation.xml to construct a validation factory, it will be ignored"); |
| } |
| } |
| } |
| |
| private void readOpenejbJar(final EjbModule ejbModule) throws OpenEJBException { |
| final Source source = getSource(ejbModule.getAltDDs().get("openejb-jar.xml")); |
| |
| if (source != null) { |
| try { |
| // Attempt to parse it first as a v3 descriptor |
| final OpenejbJar openejbJar = JaxbOpenejbJar3.unmarshal(OpenejbJar.class, source.get()).postRead(); |
| ejbModule.setOpenejbJar(openejbJar); |
| } catch (final Exception v3ParsingException) { |
| // Attempt to parse it second as a v2 descriptor |
| final OpenejbJar openejbJar = new OpenejbJar(); |
| ejbModule.setOpenejbJar(openejbJar); |
| |
| try { |
| final JAXBElement element = (JAXBElement) JaxbOpenejbJar2.unmarshal(OpenejbJarType.class, source.get()); |
| final OpenejbJarType o2 = (OpenejbJarType) element.getValue(); |
| ejbModule.getAltDDs().put("openejb-jar.xml", o2); |
| |
| final GeronimoEjbJarType g2 = OpenEjb2Conversion.convertToGeronimoOpenejbXml(o2); |
| |
| ejbModule.getAltDDs().put("geronimo-openejb.xml", g2); |
| } catch (final Exception v2ParsingException) { |
| // Now we have to determine which error to throw; the v3 file exception or the fallback v2 file exception. |
| final Exception[] realIssue = {v3ParsingException}; |
| |
| try { |
| final SAXParserFactory factory = Saxs.namespaceAwareFactory(); |
| final SAXParser parser = factory.newSAXParser(); |
| parser.parse(source.get(), new DefaultHandler() { |
| public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException { |
| if (localName.equals("environment")) { |
| realIssue[0] = v2ParsingException; |
| throw new SAXException("Throw exception to stop parsing"); |
| } |
| if (uri == null) { |
| return; |
| } |
| if (uri.contains("openejb-jar-2.") || uri.contains("geronimo.apache.org/xml/ns")) { |
| realIssue[0] = v2ParsingException; |
| throw new SAXException("Throw exception to stop parsing"); |
| } |
| } |
| }); |
| } catch (final Exception dontCare) { |
| // no-op |
| } |
| |
| String filePath = "<error: could not be written>"; |
| try { |
| File tempFile; |
| try { |
| tempFile = File.createTempFile("openejb-jar-", ".xml"); |
| } catch (final Throwable e) { |
| final File tmp = new File("tmp"); |
| if (!tmp.exists() && !tmp.mkdirs()) { |
| throw new IOException("Failed to create local tmp directory: " + tmp.getAbsolutePath()); |
| } |
| |
| tempFile = File.createTempFile("openejb-jar-", ".xml", tmp); |
| } |
| try { |
| IO.copy(source.get(), tempFile); |
| } catch (final IOException e) { |
| // no-op |
| } |
| filePath = tempFile.getAbsolutePath(); |
| } catch (final IOException e) { |
| // no-op |
| } |
| |
| final Exception e = realIssue[0]; |
| if (e instanceof SAXException) { |
| throw new OpenEJBException("Cannot parse the openejb-jar.xml. Xml content written to: " + filePath, e); |
| } else if (e instanceof JAXBException) { |
| throw new OpenEJBException("Cannot unmarshall the openejb-jar.xml. Xml content written to: " + filePath, e); |
| } else if (e instanceof IOException) { |
| throw new OpenEJBException("Cannot read the openejb-jar.xml.", e); |
| } else { |
| throw new OpenEJBException("Encountered unknown error parsing the openejb-jar.xml.", e); |
| } |
| } |
| } |
| } |
| |
| final Source source1 = getSource(ejbModule.getAltDDs().get("geronimo-openejb.xml")); |
| if (source1 != null) { |
| try { |
| GeronimoEjbJarType geronimoEjbJarType = null; |
| final Object o = JaxbOpenejbJar2.unmarshal(GeronimoEjbJarType.class, source1.get()); |
| if (o instanceof GeronimoEjbJarType) { |
| geronimoEjbJarType = (GeronimoEjbJarType) o; |
| } else if (o instanceof JAXBElement) { |
| final JAXBElement element = (JAXBElement) o; |
| geronimoEjbJarType = (GeronimoEjbJarType) element.getValue(); |
| } |
| if (geronimoEjbJarType != null) { |
| final Object nested = geronimoEjbJarType.getOpenejbJar(); |
| if (nested != null && nested instanceof OpenejbJar) { |
| final OpenejbJar existingOpenejbJar = ejbModule.getOpenejbJar(); |
| if (existingOpenejbJar == null || existingOpenejbJar.getEjbDeploymentCount() <= 0) { |
| final OpenejbJar openejbJar = (OpenejbJar) nested; |
| ejbModule.getAltDDs().put("openejb-jar.xml", openejbJar); |
| ejbModule.setOpenejbJar(openejbJar); |
| } |
| } |
| ejbModule.getAltDDs().put("geronimo-openejb.xml", geronimoEjbJarType); |
| } |
| } catch (final Exception e) { |
| throw new OpenEJBException("Failed parsing geronimo-openejb.xml", e); |
| } |
| } |
| |
| } |
| |
| private void readAppClient(final ClientModule clientModule, final AppModule appModule) throws OpenEJBException { |
| if (clientModule.getApplicationClient() != null) { |
| return; |
| } |
| |
| final Object data = clientModule.getAltDDs().get("application-client.xml"); |
| if (data instanceof ApplicationClient) { |
| clientModule.setApplicationClient((ApplicationClient) data); |
| } else if (data instanceof URL) { |
| final URL url = (URL) data; |
| final ApplicationClient applicationClient = readApplicationClient(url); |
| clientModule.setApplicationClient(applicationClient); |
| } else { |
| if (!clientModule.isEjbModuleGenerated()) { |
| DeploymentLoader.LOGGER.debug("No application-client.xml found assuming annotations present: " + appModule.getJarLocation() + ", module: " + clientModule.getModuleId()); |
| clientModule.setApplicationClient(new ApplicationClient()); |
| } |
| } |
| } |
| |
| public void readEjbJar(final EjbModule ejbModule, final AppModule appModule) throws OpenEJBException { |
| if (ejbModule.getEjbJar() != null) { |
| return; |
| } |
| |
| final Source data = getSource(ejbModule.getAltDDs().get("ejb-jar.xml")); |
| if (data != null) { |
| try { |
| final EjbJar ejbJar = readEjbJar(data.get()); |
| ejbModule.setEjbJar(ejbJar); |
| } catch (final IOException e) { |
| throw new OpenEJBException(e); |
| } |
| } else { |
| DeploymentLoader.LOGGER.debug("No ejb-jar.xml found assuming annotated beans present: " + appModule.getJarLocation() + ", module: " + ejbModule.getModuleId()); |
| ejbModule.setEjbJar(new EjbJar()); |
| } |
| } |
| |
| private static void checkDuplicatedByBeansXml(final List<String> list, final List<String> duplicated) { |
| for (String str : list) { |
| if (list.indexOf(str) != list.lastIndexOf(str)) { |
| duplicated.add(str); |
| } |
| } |
| } |
| |
| public static void checkDuplicatedByBeansXml(final Beans beans, final Beans complete) { |
| checkDuplicatedByBeansXml(beans.getAlternativeClasses(), complete.getDuplicatedAlternatives().getClasses()); |
| checkDuplicatedByBeansXml(beans.getAlternativeStereotypes(), complete.getDuplicatedAlternatives().getStereotypes()); |
| checkDuplicatedByBeansXml(beans.getDecorators(), complete.getDuplicatedDecorators()); |
| checkDuplicatedByBeansXml(beans.getInterceptors(), complete.getDuplicatedInterceptors()); |
| } |
| |
| private void readBeans(final EjbModule ejbModule) throws OpenEJBException { |
| if (ejbModule.getBeans() != null) { |
| return; |
| } |
| |
| final Object raw = ejbModule.getAltDDs().get("beans.xml"); |
| final Source data = getSource(raw); |
| if (data != null) { |
| try { |
| final Beans beans = readBeans(data.get()); |
| checkDuplicatedByBeansXml(beans, beans); |
| if (UrlSource.class.isInstance(data)) { |
| beans.setUri(UrlSource.class.cast(data).getUrl().toExternalForm()); |
| } else { |
| beans.setUri("jar:file://" + ejbModule.getModuleId() + "!/META-INF/beans.xml"); |
| } |
| ejbModule.setBeans(beans); |
| } catch (final IOException e) { |
| throw new OpenEJBException(e); |
| } |
| } else if (raw instanceof Beans) { |
| ejbModule.setBeans((Beans) raw); |
| } else if (List.class.isInstance(raw)) { |
| final CompositeBeans compositeBeans = new CompositeBeans(); |
| final List list = List.class.cast(raw); |
| if (!list.isEmpty()) { |
| for (final Object o : list) { |
| try { |
| final UrlSource urlSource = UrlSource.class.cast(o); |
| mergeBeansXml(compositeBeans, readBeans(urlSource.get()), urlSource.getUrl()); |
| } catch (final IOException e) { |
| throw new OpenEJBException(e); |
| } |
| } |
| ejbModule.setBeans(compositeBeans); |
| } |
| } |
| } |
| |
| private static Beans mergeBeansXml(final CompositeBeans current, final Beans beans, final URL url) { |
| current.mergeClasses(url, beans); |
| current.getScan().getExclude().addAll(beans.getScan().getExclude()); |
| |
| // check is done here since later we lost the data of the origin |
| ReadDescriptors.checkDuplicatedByBeansXml(beans, current); |
| |
| String beanDiscoveryMode = beans.getBeanDiscoveryMode(); |
| if (beanDiscoveryMode == null) { |
| beanDiscoveryMode = "ALL"; |
| } |
| else if ("ALL".equalsIgnoreCase(beanDiscoveryMode) && beans.isTrim()) { |
| beanDiscoveryMode = "TRIM"; |
| } |
| |
| current.getDiscoveryByUrl().put(url, beanDiscoveryMode); |
| return current; |
| } |
| |
| // package scoped for testing |
| void readCmpOrm(final EjbModule ejbModule) throws OpenEJBException { |
| final Object data = ejbModule.getAltDDs().get("openejb-cmp-orm.xml"); |
| if (data != null && !(data instanceof EntityMappings)) { |
| if (data instanceof URL) { |
| final URL url = (URL) data; |
| try { |
| final EntityMappings entitymappings = (EntityMappings) JaxbJavaee.unmarshal(EntityMappings.class, IO.read(url)); |
| ejbModule.getAltDDs().put("openejb-cmp-orm.xml", entitymappings); |
| } catch (final SAXException e) { |
| throw new OpenEJBException("Cannot parse the openejb-cmp-orm.xml file: " + url.toExternalForm(), e); |
| } catch (final JAXBException e) { |
| throw new OpenEJBException("Cannot unmarshall the openejb-cmp-orm.xml file: " + url.toExternalForm(), e); |
| } catch (final IOException e) { |
| throw new OpenEJBException("Cannot read the openejb-cmp-orm.xml file: " + url.toExternalForm(), e); |
| } catch (final Exception e) { |
| throw new OpenEJBException("Encountered unknown error parsing the openejb-cmp-orm.xml file: " + url.toExternalForm(), e); |
| } |
| } |
| } |
| } |
| |
| private void readConnector(final ConnectorModule connectorModule, final AppModule appModule) throws OpenEJBException { |
| if (connectorModule.getConnector() != null) { |
| return; |
| } |
| |
| final Object data = connectorModule.getAltDDs().get("ra.xml"); |
| if (data instanceof Connector) { |
| connectorModule.setConnector((Connector) data); |
| } else if (data instanceof URL) { |
| final URL url = (URL) data; |
| final Connector connector = readConnector(url); |
| connectorModule.setConnector(connector); |
| } else { |
| DeploymentLoader.LOGGER.debug("No ra.xml found assuming annotated beans present: " + appModule.getJarLocation() + ", module: " + connectorModule.getModuleId()); |
| connectorModule.setConnector(new Connector()); |
| } |
| } |
| |
| private void readWebApp(final WebModule webModule, final AppModule appModule) throws OpenEJBException { |
| if (webModule.getWebApp() != null) { |
| mergeWebFragments(webModule); |
| return; |
| } |
| |
| final Object data = webModule.getAltDDs().get("web.xml"); |
| if (data instanceof WebApp) { |
| webModule.setWebApp((WebApp) data); |
| } else if (data instanceof URL) { |
| final URL url = (URL) data; |
| final WebApp webApp = readWebApp(url); |
| webModule.setWebApp(webApp); |
| } else { |
| DeploymentLoader.LOGGER.debug("No web.xml found assuming annotated beans present: " + appModule.getJarLocation() + ", module: " + webModule.getModuleId()); |
| webModule.setWebApp(new WebApp()); |
| } |
| |
| mergeWebFragments(webModule); |
| } |
| |
| private void mergeWebFragments(final WebModule webModule) { |
| // web-fragment.xml, to get jndi entries to merge, other stuff is done by tomcat ATM |
| final Collection<URL> urls = Collection.class.cast(webModule.getAltDDs().get("web-fragment.xml")); |
| if (urls != null) { |
| for (final URL rawUrl : urls) { |
| if (rawUrl != null) { |
| final Source url = getSource(rawUrl); |
| try { |
| final WebFragment webFragment = WebFragment.class.cast(JaxbJavaee.unmarshal(WebFragment.class, url.get(), false)); |
| |
| // in tomcat if the env entry is already don't override it |
| mergeOnlyMissingEntries(webModule.getWebApp().getPersistenceContextRefMap(), webFragment.getPersistenceContextRef()); |
| mergeOnlyMissingEntries(webModule.getWebApp().getPersistenceUnitRefMap(), webFragment.getPersistenceUnitRef()); |
| mergeOnlyMissingEntries(webModule.getWebApp().getMessageDestinationRefMap(), webFragment.getMessageDestinationRef()); |
| mergeOnlyMissingEntries(webModule.getWebApp().getDataSourceMap(), webFragment.getDataSource()); |
| mergeOnlyMissingEntries(webModule.getWebApp().getJMSConnectionFactoriesMap(), webFragment.getJMSConnectionFactories()); |
| mergeOnlyMissingEntries(webModule.getWebApp().getEjbLocalRefMap(), webFragment.getEjbLocalRef()); |
| mergeOnlyMissingEntries(webModule.getWebApp().getEjbRefMap(), webFragment.getEjbRef()); |
| mergeOnlyMissingEntries(webModule.getWebApp().getServiceRefMap(), webFragment.getServiceRef()); |
| mergeOnlyMissingEntries(webModule.getWebApp().getEnvEntryMap(), webFragment.getEnvEntry()); |
| mergeOnlyMissingEntries(webModule.getWebApp().getResourceEnvRefMap(), webFragment.getResourceEnvRef()); |
| mergeOnlyMissingEntries(webModule.getWebApp().getResourceRefMap(), webFragment.getResourceRef()); |
| } catch (final Exception e) { |
| logger.warning("can't read " + url.toString(), e); |
| } |
| } |
| } |
| } |
| } |
| |
| private static <A extends Keyable<String>> void mergeOnlyMissingEntries(final Map<String, A> existing, final Collection<A> news) { |
| for (final A entry : news) { |
| final String key = entry.getKey(); |
| if (!existing.containsKey(key)) { |
| existing.put(key, entry); |
| } |
| } |
| } |
| |
| public static ApplicationClient readApplicationClient(final URL url) throws OpenEJBException { |
| final ApplicationClient applicationClient; |
| try { |
| applicationClient = ApplicationClientXml.unmarshal(url); |
| } catch (final SAXException e) { |
| throw new OpenEJBException("Cannot parse the application-client.xml file: " + url.toExternalForm(), e); |
| } catch (final JAXBException e) { |
| throw new OpenEJBException("Cannot unmarshall the application-client.xml file: " + url.toExternalForm(), e); |
| } catch (final IOException e) { |
| throw new OpenEJBException("Cannot read the application-client.xml file: " + url.toExternalForm(), e); |
| } catch (final Exception e) { |
| throw new OpenEJBException("Encountered unknown error parsing the application-client.xml file: " + url.toExternalForm(), e); |
| } |
| return applicationClient; |
| } |
| |
| public static EjbJar readEjbJar(final InputStream is) throws OpenEJBException { |
| try { |
| final String content = IO.slurp(is); |
| if (isEmptyEjbJar(new ByteArrayInputStream(content.getBytes()))) { |
| final String id = getId(new ByteArrayInputStream(content.getBytes())); |
| return new EjbJar(id); |
| } |
| return EjbJarXml.unmarshal(new ByteArrayInputStream(content.getBytes())); |
| } catch (final SAXException e) { |
| throw new OpenEJBException("Cannot parse the ejb-jar.xml", e); // file: " + url.toExternalForm(), e); |
| } catch (final IOException e) { |
| throw new OpenEJBException("Cannot read the ejb-jar.xml", e); // file: " + url.toExternalForm(), e); |
| } catch (final Exception e) { |
| throw new OpenEJBException("Encountered error parsing the ejb-jar.xml", e); // file: " + url.toExternalForm(), e); |
| } |
| } |
| |
| public static Beans readBeans(final InputStream inputStream) throws OpenEJBException { |
| try { |
| final String content = IO.slurp(inputStream).trim(); |
| if (content.length() == 0) { // otherwise we want to read <beans /> attributes |
| final Beans beans = new Beans(); |
| beans.setBeanDiscoveryMode("ALL"); // backward compatibility |
| return beans; |
| } |
| return (Beans) JaxbJavaee.unmarshalJavaee(Beans.class, new ByteArrayInputStream(content.getBytes())); |
| } catch (final SAXException e) { |
| throw new OpenEJBException("Cannot parse the beans.xml", e);// file: " + url.toExternalForm(), e); |
| } catch (final JAXBException e) { |
| e.printStackTrace(); |
| throw new OpenEJBException("Cannot unmarshall the beans.xml", e);// file: " + url.toExternalForm(), e); |
| } catch (final IOException e) { |
| throw new OpenEJBException("Cannot read the beans.xml", e);// file: " + url.toExternalForm(), e); |
| } catch (final Exception e) { |
| throw new OpenEJBException("Encountered unknown error parsing the beans.xml", e);// file: " + url.toExternalForm(), e); |
| } |
| } |
| |
| private static boolean isEmptyEjbJar(final InputStream is) throws IOException, ParserConfigurationException, SAXException { |
| return isEmpty(is, "ejb-jar"); |
| } |
| |
| private static boolean isEmpty(final InputStream is, final String rootElement) throws IOException, ParserConfigurationException, SAXException { |
| final LengthInputStream in = new LengthInputStream(is); |
| final InputSource inputSource = new InputSource(in); |
| |
| final SAXParser parser; |
| |
| final Thread thread = Thread.currentThread(); |
| final ClassLoader original = thread.getContextClassLoader(); |
| thread.setContextClassLoader(Saxs.class.getClassLoader()); |
| try { |
| parser = Saxs.namespaceAwareFactory().newSAXParser(); |
| } finally { |
| thread.setContextClassLoader(original); |
| } |
| |
| try { |
| parser.parse(inputSource, new DefaultHandler() { |
| public void startElement(final String uri, final String localName, final String qName, final Attributes att) throws SAXException { |
| if (!localName.equals(rootElement)) { |
| throw new SAXException(localName); |
| } |
| } |
| |
| public InputSource resolveEntity(final String publicId, final String systemId) throws IOException, SAXException { |
| return new InputSource(new ByteArrayInputStream(new byte[0])); |
| } |
| }); |
| return true; |
| } catch (final SAXException e) { |
| return in.getLength() == 0; |
| } |
| } |
| |
| private static String getId(final InputStream is) { |
| final String[] id = {null}; |
| |
| try { |
| final LengthInputStream in = new LengthInputStream(is); |
| final InputSource inputSource = new InputSource(in); |
| |
| final SAXParser parser = Saxs.namespaceAwareFactory().newSAXParser(); |
| |
| parser.parse(inputSource, new DefaultHandler() { |
| public void startElement(final String uri, final String localName, final String qName, final Attributes att) throws SAXException { |
| id[0] = att.getValue("id"); |
| } |
| |
| public InputSource resolveEntity(final String publicId, final String systemId) throws IOException, SAXException { |
| return new InputSource(new ByteArrayInputStream(new byte[0])); |
| } |
| }); |
| } catch (final Exception e) { |
| // no-op |
| } |
| |
| return id[0]; |
| } |
| |
| public static Webservices readWebservices(final URL url) throws OpenEJBException { |
| try { |
| return WebservicesXml.unmarshal(url); |
| } catch (final SAXException e) { |
| throw new OpenEJBException("Cannot parse the webservices.xml file: " + url.toExternalForm(), e); |
| } catch (final JAXBException e) { |
| throw new OpenEJBException("Cannot unmarshall the webservices.xml file: " + url.toExternalForm(), e); |
| } catch (final IOException e) { |
| throw new OpenEJBException("Cannot read the webservices.xml file: " + url.toExternalForm(), e); |
| } catch (final Exception e) { |
| throw new OpenEJBException("Encountered unknown error parsing the webservices.xml file: " + url.toExternalForm(), e); |
| } |
| } |
| |
| public static HandlerChains readHandlerChains(final URL url) throws OpenEJBException { |
| try { |
| return HandlerChainsXml.unmarshal(url); |
| } catch (final SAXException e) { |
| throw new OpenEJBException("Cannot parse the webservices.xml file: " + url.toExternalForm(), e); |
| } catch (final JAXBException e) { |
| throw new OpenEJBException("Cannot unmarshall the webservices.xml file: " + url.toExternalForm(), e); |
| } catch (final IOException e) { |
| throw new OpenEJBException("Cannot read the webservices.xml file: " + url.toExternalForm(), e); |
| } catch (final Exception e) { |
| throw new OpenEJBException("Encountered unknown error parsing the webservices.xml file: " + url.toExternalForm(), e); |
| } |
| } |
| |
| public static JavaWsdlMapping readJaxrpcMapping(final URL url) throws OpenEJBException { |
| final JavaWsdlMapping wsdlMapping; |
| try { |
| wsdlMapping = (JavaWsdlMapping) JaxbJavaee.unmarshalJavaee(JavaWsdlMapping.class, IO.read(url)); |
| } catch (final SAXException e) { |
| throw new OpenEJBException("Cannot parse the JaxRPC mapping file: " + url.toExternalForm(), e); |
| } catch (final JAXBException e) { |
| throw new OpenEJBException("Cannot unmarshall the JaxRPC mapping file: " + url.toExternalForm(), e); |
| } catch (final IOException e) { |
| throw new OpenEJBException("Cannot read the JaxRPC mapping file: " + url.toExternalForm(), e); |
| } catch (final Exception e) { |
| throw new OpenEJBException("Encountered unknown error parsing the JaxRPC mapping file: " + url.toExternalForm(), e); |
| } |
| return wsdlMapping; |
| } |
| |
| public static Connector readConnector(final URL url) throws OpenEJBException { |
| Connector connector; |
| try { |
| connector = (Connector) JaxbJavaee.unmarshalJavaee(Connector.class, IO.read(url)); |
| } catch (final JAXBException e) { |
| try { |
| final Connector10 connector10 = (Connector10) JaxbJavaee.unmarshalJavaee(Connector10.class, IO.read(url)); |
| connector = Connector.newConnector(connector10); |
| } catch (final ParserConfigurationException | SAXException e1) { |
| throw new OpenEJBException("Cannot parse the ra.xml file: " + url.toExternalForm(), e); |
| } catch (final JAXBException e1) { |
| throw new OpenEJBException("Cannot unmarshall the ra.xml file: " + url.toExternalForm(), e); |
| } catch (final IOException e1) { |
| throw new OpenEJBException("Cannot read the ra.xml file: " + url.toExternalForm(), e); |
| } |
| } catch (final SAXException e) { |
| throw new OpenEJBException("Cannot parse the ra.xml file: " + url.toExternalForm(), e); |
| } catch (final IOException e) { |
| throw new OpenEJBException("Cannot read the ra.xml file: " + url.toExternalForm(), e); |
| } catch (final Exception e) { |
| throw new OpenEJBException("Encountered unknown error parsing the ra.xml file: " + url.toExternalForm(), e); |
| } |
| return connector; |
| } |
| |
| public static WebApp readWebApp(final URL url) throws OpenEJBException { |
| final WebApp webApp; |
| try { |
| webApp = WebXml.unmarshal(url); |
| } catch (final SAXException e) { |
| throw new OpenEJBException("Cannot parse the web.xml file: " + url.toExternalForm(), e); |
| } catch (final JAXBException e) { |
| throw new OpenEJBException("Cannot unmarshall the web.xml file: " + url.toExternalForm(), e); |
| } catch (final IOException e) { |
| throw new OpenEJBException("Cannot read the web.xml file: " + url.toExternalForm(), e); |
| } catch (final Exception e) { |
| throw new OpenEJBException("Encountered unknown error parsing the web.xml file: " + url.toExternalForm(), e); |
| } |
| return webApp; |
| } |
| |
| public static TldTaglib readTldTaglib(final URL url) throws OpenEJBException { |
| // TOMEE-164 Optimization on reading built-in tld files |
| if (url.getPath().contains("jstl-1.2.jar") || ((url.getPath().contains("taglibs-standard-") || url.getPath().contains("taglibs-shade-") && url.getPath().contains(".jar!")))) { |
| return SKIP_TAGLIB; |
| } |
| if (url.getPath().contains("myfaces-impl")) { // we should return SKIP_TAGLIB too |
| final TldTaglib taglib = new TldTaglib(); |
| final Listener listener = new Listener(); |
| listener.setListenerClass("org.apache.myfaces.webapp.StartupServletContextListener"); |
| taglib.getListener().add(listener); |
| return taglib; |
| } |
| |
| try { |
| return TldTaglibXml.unmarshal(url); |
| } catch (final SAXException e) { |
| final String message = "Cannot parse the JSP tag library definition file: " + url.toExternalForm(); |
| logger.warning(message); |
| logger.debug(message, e); |
| } catch (final JAXBException e) { |
| final String message = "Cannot unmarshall the JSP tag library definition file: " + url.toExternalForm(); |
| logger.warning(message); |
| logger.debug(message, e); |
| } catch (final IOException e) { |
| final String message = "Cannot read the JSP tag library definition file: " + url.toExternalForm(); |
| logger.warning(message); |
| logger.debug(message, e); |
| } catch (final Exception e) { |
| final String message = "Encountered unknown error parsing the JSP tag library definition file: " + url.toExternalForm(); |
| logger.warning(message); |
| logger.debug(message, e); |
| } |
| return SKIP_TAGLIB; |
| } |
| |
| public static FacesConfig readFacesConfig(final URL url) throws OpenEJBException { |
| try { |
| final Source src = getSource(url); |
| if (src == null) { |
| return new FacesConfig(); |
| } |
| |
| final String content = IO.slurp(src.get()); |
| if (isEmpty(new ByteArrayInputStream(content.getBytes()), "faces-config")) { |
| return new FacesConfig(); |
| } |
| return FacesConfigXml.unmarshal(new ByteArrayInputStream(content.getBytes())); |
| } catch (final SAXException e) { |
| throw new OpenEJBException("Cannot parse the faces configuration file: " + url.toExternalForm(), e); |
| } catch (final JAXBException e) { |
| throw new OpenEJBException("Cannot unmarshall the faces configuration file: " + url.toExternalForm(), e); |
| } catch (final IOException e) { |
| throw new OpenEJBException("Cannot read the faces configuration file: " + url.toExternalForm(), e); |
| } catch (final Exception e) { |
| throw new OpenEJBException("Encountered unknown error parsing the faces configuration file: " + url.toExternalForm(), e); |
| } |
| } |
| |
| private static Source getSource(final Object o) { |
| if (o instanceof URL) { |
| return new UrlSource((URL) o); |
| } |
| |
| if (o instanceof Source) { |
| return (Source) o; |
| } |
| |
| if (o instanceof String) { |
| return new StringSource((String) o); |
| } |
| |
| return null; |
| } |
| |
| public interface Source { |
| InputStream get() throws IOException; |
| } |
| |
| public static class UrlSource implements Source { |
| private final URL url; |
| |
| public UrlSource(final URL url) { |
| this.url = url; |
| } |
| |
| @Override |
| public InputStream get() throws IOException { |
| return IO.read(url); |
| } |
| |
| public URL getUrl() { |
| return url; |
| } |
| |
| @Override |
| public String toString() { |
| return "UrlSource{url=" + url + '}'; |
| } |
| } |
| |
| public static class StringSource implements Source { |
| private final byte[] bytes; |
| private final String toString; |
| |
| public StringSource(final String content) { |
| toString = content; |
| bytes = content.getBytes(); |
| } |
| |
| @Override |
| public InputStream get() throws IOException { |
| return new ByteArrayInputStream(bytes); |
| } |
| |
| @Override |
| public String toString() { |
| return "StringSource{content=" + toString + '}'; |
| } |
| } |
| } |