Java tutorial
/* * Copyright 2010 Impetus Infotech. * * Licensed 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 com.impetus.kundera.ejb; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import javax.persistence.PersistenceException; import javax.persistence.spi.PersistenceUnitTransactionType; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXParseException; /** * Class that loads persistence.xml files * * @author animesh.kumar * */ public final class PersistenceXmlLoader { /** The log. */ private static Log log = LogFactory.getLog(PersistenceXmlLoader.class); /** * Instantiates a new persistence xml loader. */ private PersistenceXmlLoader() { } /** * Gets the document. * * @param configURL * the config url * @return the document * @throws Exception * the exception */ private static Document getDocument(URL configURL) throws Exception { InputStream is = null; if (configURL != null) { URLConnection conn = configURL.openConnection(); conn.setUseCaches(false); // avoid JAR locking on Windows and Tomcat is = conn.getInputStream(); } if (is == null) { throw new IOException("Failed to obtain InputStream from url: " + configURL); } DocumentBuilderFactory docBuilderFactory = null; docBuilderFactory = DocumentBuilderFactory.newInstance(); docBuilderFactory.setValidating(true); docBuilderFactory.setNamespaceAware(true); try { // otherwise Xerces fails in validation docBuilderFactory.setAttribute("http://apache.org/xml/features/validation/schema", true); } catch (IllegalArgumentException e) { docBuilderFactory.setValidating(false); docBuilderFactory.setNamespaceAware(false); } InputSource source = new InputSource(is); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); // docBuilder.setEntityResolver( resolver ); List errors = new ArrayList(); docBuilder.setErrorHandler(new ErrorLogger("XML InputStream", errors)); Document doc = docBuilder.parse(source); if (errors.size() != 0) { throw new PersistenceException("invalid persistence.xml", (Throwable) errors.get(0)); } is.close(); //Close input Stream return doc; } /** * Find persistence units. * * @param url * the url * @return the list * @throws Exception * the exception */ public static List<PersistenceMetadata> findPersistenceUnits(URL url) throws Exception { return findPersistenceUnits(url, PersistenceUnitTransactionType.JTA); } /** * Find persistence units. * * @param url * the url * @param defaultTransactionType * the default transaction type * @return the list * @throws Exception * the exception */ public static List<PersistenceMetadata> findPersistenceUnits(URL url, PersistenceUnitTransactionType defaultTransactionType) throws Exception { Document doc = getDocument(url); Element top = doc.getDocumentElement(); NodeList children = top.getChildNodes(); ArrayList<PersistenceMetadata> units = new ArrayList<PersistenceMetadata>(); for (int i = 0; i < children.getLength(); i++) { if (children.item(i).getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) children.item(i); String tag = element.getTagName(); // look for "persistence-unit" element if (tag.equals("persistence-unit")) { PersistenceMetadata metadata = parsePersistenceUnit(element); units.add(metadata); } } } return units; } /** * Parses the persistence unit. * * @param top * the top * @return the persistence metadata * @throws Exception * the exception */ private static PersistenceMetadata parsePersistenceUnit(Element top) throws Exception { PersistenceMetadata metadata = new PersistenceMetadata(); String puName = top.getAttribute("name"); if (!isEmpty(puName)) { log.trace("Persistent Unit name from persistence.xml: " + puName); metadata.setName(puName); } NodeList children = top.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { if (children.item(i).getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) children.item(i); String tag = element.getTagName(); if (tag.equals("provider")) { metadata.setProvider(getElementContent(element)); } else if (tag.equals("properties")) { NodeList props = element.getChildNodes(); for (int j = 0; j < props.getLength(); j++) { if (props.item(j).getNodeType() == Node.ELEMENT_NODE) { Element propElement = (Element) props.item(j); // if element is not "property" then skip if (!"property".equals(propElement.getTagName())) { continue; } String propName = propElement.getAttribute("name").trim(); String propValue = propElement.getAttribute("value").trim(); if (isEmpty(propValue)) { propValue = getElementContent(propElement, ""); } metadata.getProps().put(propName, propValue); } } } // Kundera doesn't support "class", "jar-file" and "excluded-unlisted-classes" for now.. but will someday. // let's parse it for now. else if (tag.equals("class")) { metadata.getClasses().add(getElementContent(element)); } else if (tag.equals("jar-file")) { metadata.getJarFiles().add(getElementContent(element)); } else if (tag.equals("exclude-unlisted-classes")) { metadata.setExcludeUnlistedClasses(true); } } } PersistenceUnitTransactionType transactionType = getTransactionType(top.getAttribute("transaction-type")); if (transactionType != null) { metadata.setTransactionType(transactionType); } return metadata; } /** * Gets the transaction type. * * @param elementContent * the element content * @return the transaction type */ public static PersistenceUnitTransactionType getTransactionType(String elementContent) { if (elementContent == null || elementContent.isEmpty()) { return null; } else if (elementContent.equalsIgnoreCase("JTA")) { return PersistenceUnitTransactionType.JTA; } else if (elementContent.equalsIgnoreCase("RESOURCE_LOCAL")) { return PersistenceUnitTransactionType.RESOURCE_LOCAL; } else { throw new PersistenceException("Unknown TransactionType: " + elementContent); } } /** * The Class ErrorLogger. */ public static class ErrorLogger implements ErrorHandler { /** The file. */ private String file; /** The errors. */ private List errors; /** * Instantiates a new error logger. * * @param file * the file * @param errors * the errors */ ErrorLogger(String file, List errors) { this.file = file; this.errors = errors; } /* @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException) */ public void error(SAXParseException error) { log.error("Error parsing XML: " + file + '(' + error.getLineNumber() + ") " + error.getMessage()); errors.add(error); } /* @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException) */ public void fatalError(SAXParseException error) { log.error("Error parsing XML: " + file + '(' + error.getLineNumber() + ") " + error.getMessage()); errors.add(error); } /* @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException) */ public void warning(SAXParseException warn) { log.warn("Warning parsing XML: " + file + '(' + warn.getLineNumber() + ") " + warn.getMessage()); } } /** * Checks if is empty. * * @param str * the str * @return true, if is empty */ private static boolean isEmpty(String str) { return null == str || str.isEmpty(); } /** * Gets the element content. * * @param element * the element * @return the element content * @throws Exception * the exception */ public static String getElementContent(final Element element) throws Exception { return getElementContent(element, null); } /** * Get the content of the given element. * * @param element * The element to get the content for. * @param defaultStr * The default to return when there is no content. * @return The content of the element or the default. * @throws Exception * the exception */ private static String getElementContent(Element element, String defaultStr) throws Exception { if (element == null) { return defaultStr; } NodeList children = element.getChildNodes(); StringBuilder result = new StringBuilder(""); for (int i = 0; i < children.getLength(); i++) { if (children.item(i).getNodeType() == Node.TEXT_NODE || children.item(i).getNodeType() == Node.CDATA_SECTION_NODE) { result.append(children.item(i).getNodeValue()); } } return result.toString().trim(); } }