001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.configuration;
029
030import java.io.File;
031
032import javax.xml.parsers.DocumentBuilder;
033import javax.xml.parsers.DocumentBuilderFactory;
034import javax.xml.transform.Transformer;
035import javax.xml.transform.TransformerFactory;
036import javax.xml.transform.dom.DOMSource;
037import javax.xml.transform.stream.StreamResult;
038
039import org.w3c.dom.Document;
040import org.w3c.dom.Element;
041import org.w3c.dom.NodeList;
042
043/**
044 * Persistence configuration class.<p>
045 *
046 * This class allow to be managed (reading and writing) JPA  persistence.xml configuration file.<p>
047 *
048 * @since 8.0.0
049 */
050public class CmsPersistenceUnitConfiguration {
051
052    /** Attribute name for connection settings for Apache OpenJPA & DBCP. */
053    public static final String ATTR_CONNECTION_PROPERTIES = "openjpa.ConnectionProperties";
054
055    /** Attribute name for connection settings. */
056    public static final String ATTR_GENERATE_SCHEMA = "openjpa.jdbc.SynchronizeMappings";
057
058    /** Attribute name for connection settings. */
059    public static final String ATTR_GENERATE_SCHEMA_VALUE = "buildSchema(ForeignKeys=true)";
060
061    /** Attribute name for attribute "name" of property. */
062    public static final String ATTR_NAME = "name";
063
064    /** Attribute name for attribute "value" of property. */
065    public static final String ATTR_VALUE = "value";
066
067    /** Tag constant. */
068    public static final String TAG_PERSISTENCE_UNIT = "persistence-unit";
069
070    /** Tag constant. */
071    public static final String TAG_PROPERTIES = "properties";
072
073    /** Tag constant. */
074    public static final String TAG_PROPERTY = "property";
075
076    /** DOM document. */
077    private Document m_document;
078
079    /** Configuration file name (usually it's persistence.xml file. */
080    private String m_fileName;
081
082    /** DOM element represents persistence node/element. */
083    private Element m_persistenceUnit;
084
085    /** Persistence unit name to be configured. */
086    private String m_persistenceUnitName;
087
088    /** List of nodes/elements with specific configuration parameters for particular JPA implementation. */
089    private NodeList m_properties;
090
091    /** Property element. */
092    private Element m_propertiesElement;
093
094    /**
095     * Public constructor which initialize the object.<p>
096     *
097     * @param unitName persistence unit name to be managed
098     * @param fileName configuration file name
099     */
100    public CmsPersistenceUnitConfiguration(String unitName, String fileName) {
101
102        m_fileName = new String(fileName);
103        m_persistenceUnitName = unitName;
104        m_document = readDocument(m_fileName);
105        m_persistenceUnit = getPersistenceUnit(m_document.getDocumentElement());
106        m_propertiesElement = (Element)m_persistenceUnit.getElementsByTagName(TAG_PROPERTIES).item(0);
107        refreshProperties();
108    }
109
110    /**
111     * Returns a property value for the given property name.<p>
112     *
113     * @param name the name of the property
114     * @param defaultValue the default value if there was no property configured with the given name
115     *
116     * @return a property value for the given property name
117     */
118    public String getPropertyValue(String name, String defaultValue) {
119
120        Element el = null;
121        for (int i = 0; i < m_properties.getLength(); i++) {
122            el = (Element)m_properties.item(i);
123            if (name.equalsIgnoreCase(el.getAttribute(ATTR_NAME))) {
124                return el.getAttribute(ATTR_VALUE);
125            }
126        }
127        return defaultValue;
128    }
129
130    /**
131     * Removes property with given name.<p>
132     *
133     * @param name value of the name attribute
134     */
135    public void removeProperty(String name) {
136
137        Element el = null;
138        for (int i = 0; i < m_properties.getLength(); i++) {
139            el = (Element)m_properties.item(i);
140            if (name.equalsIgnoreCase(el.getAttribute(ATTR_NAME))) {
141                m_propertiesElement.removeChild(el);
142                break;
143            }
144        }
145        refreshProperties();
146    }
147
148    /**
149     * Saves the original configuration file.<p>
150     */
151    public void save() {
152
153        save(m_fileName);
154    }
155
156    /**
157     * Sets property value with given name and value.<p>
158     *
159     * @param name value of the name attribute
160     * @param value value of the value attribute
161     */
162    public void setPropertyValue(String name, String value) {
163
164        boolean exist = false;
165
166        Element el = null;
167        for (int i = 0; i < m_properties.getLength(); i++) {
168            el = (Element)m_properties.item(i);
169            if (name.equalsIgnoreCase(el.getAttribute(ATTR_NAME))) {
170                el.setAttribute(ATTR_VALUE, value);
171                exist = true;
172                break;
173            }
174        }
175
176        if (!exist) {
177            addProperty(name, value);
178        }
179    }
180
181    /**
182     * Adds a property.<p>
183     *
184     * @param name the name of the property
185     * @param value the value for the property
186     */
187    private void addProperty(String name, String value) {
188
189        Element el = m_document.createElement(TAG_PROPERTY);
190        el.setAttribute(ATTR_NAME, name);
191        el.setAttribute(ATTR_VALUE, value);
192        m_propertiesElement.appendChild(el);
193        refreshProperties();
194    }
195
196    /**
197     * Returns DOM element of persistence unit with name represents by m_persistenceUnitName.<p>
198     *
199     * @param e document element of xml document
200     *
201     * @return element for given name or null value if it does not exist
202     */
203    private Element getPersistenceUnit(Element e) {
204
205        NodeList list = e.getElementsByTagName(TAG_PERSISTENCE_UNIT);
206        Element el = null;
207        for (int i = 0; i < list.getLength(); i++) {
208            el = (Element)list.item(i);
209            if (m_persistenceUnitName.equalsIgnoreCase(el.getAttribute(ATTR_NAME))) {
210                break;
211            }
212        }
213        return el;
214    }
215
216    /**
217     * Reads the configuration file.<p>
218     *
219     * @param fileName file name
220     *
221     * @return DOM model of configuration file
222     */
223    private Document readDocument(String fileName) {
224
225        Document doc = null;
226        try {
227            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
228            File f = new File(fileName);
229            doc = builder.parse(f);
230        } catch (Exception e) {
231            e.printStackTrace();
232        }
233        return doc;
234    }
235
236    /**
237     * Refreshes the list with all properties for particular persistence unit.<p>
238     */
239    private void refreshProperties() {
240
241        m_properties = m_propertiesElement.getElementsByTagName(TAG_PROPERTY);
242    }
243
244    /**
245     * Save the configuration to file.<p>
246     *
247     * @param fileName the full path with file name to the persistence.xml
248     */
249    private void save(String fileName) {
250
251        try {
252            Transformer transformer = TransformerFactory.newInstance().newTransformer();
253            DOMSource source = new DOMSource(m_document);
254            File file = new File(fileName);
255            StreamResult result = new StreamResult(file);
256            transformer.transform(source, result);
257        } catch (Exception e) {
258            e.printStackTrace();
259        }
260    }
261}