001// Copyright 2011, 2014 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007// http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.internal.jpa;
016
017import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
018import org.apache.tapestry5.jpa.TapestryPersistenceUnitInfo;
019import org.xml.sax.Attributes;
020import org.xml.sax.ContentHandler;
021import org.xml.sax.Locator;
022import org.xml.sax.SAXException;
023
024import javax.persistence.SharedCacheMode;
025import javax.persistence.ValidationMode;
026import javax.persistence.spi.PersistenceUnitTransactionType;
027
028import java.util.Arrays;
029import java.util.Collections;
030import java.util.List;
031import java.util.Set;
032
033public class PersistenceContentHandler implements ContentHandler
034{
035    private static final List<String> NAMESPACE_URIS = Arrays.asList(
036                new String[]{"http://java.sun.com/xml/ns/persistence", "http://xmlns.jcp.org/xml/ns/persistence"});
037    private static final String ELEMENT_PERSISTENCE_UNIT = "persistence-unit";
038    private static final String ELEMENT_PROVIDER = "provider";
039    private static final String ELEMENT_JTA_DATA_SOURCE = "jta-data-source";
040    private static final String ELEMENT_NON_JTA_DATA_SOURCE = "non-jta-data-source";
041    private static final String ELEMENT_MAPPING_FILE = "mapping-file";
042    private static final String ELEMENT_JAR_FILE = "jar-file";
043    private static final String ELEMENT_CLASS = "class";
044    private static final String ELEMENT_EXCLUDE_UNLISTED_CLASSES = "exclude-unlisted-classes";
045    private static final String ELEMENT_CACHING = "shared-cache-mode";
046    private static final String ELEMENT_VALIDATION_MODE = "validation-mode";
047    private static final String ELEMENT_PROPERTY = "property";
048    private static final String ATTRIBUTE_NAME = "name";
049    private static final String ATTRIBUTE_VALUE = "value";
050    private static final String ATTRIBUTE_VERSION = "value";
051    private static final String ATTRIBUTE_TRANSACTION_TYPE = "transaction-type";
052
053    private final List<TapestryPersistenceUnitInfo> persistenceUnits = CollectionFactory.newList();
054    private PersistenceUnitInfoImpl persistenceUnitInfo;
055    private StringBuilder characters;
056
057    public List<TapestryPersistenceUnitInfo> getPersistenceUnits()
058    {
059        return persistenceUnits;
060    }
061
062    @Override
063    public void setDocumentLocator(final Locator locator)
064    {
065    }
066
067    @Override
068    public void startDocument() throws SAXException
069    {
070    }
071
072    @Override
073    public void endDocument() throws SAXException
074    {
075    }
076
077    @Override
078    public void startPrefixMapping(final String prefix, final String uri) throws SAXException
079    {
080    }
081
082    @Override
083    public void endPrefixMapping(final String prefix) throws SAXException
084    {
085    }
086
087    @Override
088    public void startElement(final String namespaceURI, final String localName, final String qName,
089                             final Attributes atts) throws SAXException
090    {
091        if (NAMESPACE_URIS.contains(namespaceURI))
092        {
093            if (ELEMENT_PERSISTENCE_UNIT.equals(localName))
094            {
095                persistenceUnitInfo = new PersistenceUnitInfoImpl(atts.getValue(ATTRIBUTE_NAME));
096                persistenceUnitInfo
097                        .setPersistenceXMLSchemaVersion(atts.getValue(ATTRIBUTE_VERSION));
098
099                final String transactionType = atts.getValue(ATTRIBUTE_TRANSACTION_TYPE);
100
101                if (transactionType != null)
102                {
103                    persistenceUnitInfo.transactionType(PersistenceUnitTransactionType
104                            .valueOf(transactionType));
105                }
106            } else if (ELEMENT_PROPERTY.equals(localName))
107            {
108                final String name = atts.getValue(ATTRIBUTE_NAME);
109                final String value = atts.getValue(ATTRIBUTE_VALUE);
110                persistenceUnitInfo.getProperties().setProperty(name, value);
111            }
112        }
113    }
114
115    @Override
116    public void endElement(final String namespaceURI, final String localName, final String qName)
117            throws SAXException
118    {
119
120        final String string = characters.toString().trim();
121        characters = null;
122
123        if (NAMESPACE_URIS.contains(namespaceURI))
124        {
125            if (ELEMENT_PROVIDER.equals(localName))
126            {
127                persistenceUnitInfo.persistenceProviderClassName(string);
128            }
129            else if (ELEMENT_CLASS.equals(localName))
130            {
131                persistenceUnitInfo.addManagedClassName(string);
132            }
133            else if (ELEMENT_CACHING.equals(localName))
134            {
135                persistenceUnitInfo.sharedCacheMode(toEnum(SharedCacheMode.class, string));
136            }
137            else if (ELEMENT_VALIDATION_MODE.equals(localName))
138            {
139                persistenceUnitInfo.validationMode(toEnum(ValidationMode.class, string));
140            }
141            else if (ELEMENT_MAPPING_FILE.equals(localName))
142            {
143                persistenceUnitInfo.addMappingFileName(string);
144            }
145            else if (ELEMENT_JAR_FILE.equals(localName))
146            {
147                persistenceUnitInfo.addJarFileUrl(string);
148            }
149            else if (ELEMENT_NON_JTA_DATA_SOURCE.equals(localName))
150            {
151                persistenceUnitInfo.nonJtaDataSource(string);
152            }
153            else if (ELEMENT_JTA_DATA_SOURCE.equals(localName))
154            {
155                persistenceUnitInfo.jtaDataSource(string);
156            }
157            else if (ELEMENT_PERSISTENCE_UNIT.equals(localName))
158            {
159                if (persistenceUnitInfo != null)
160                {
161                    persistenceUnits.add(persistenceUnitInfo);
162                    persistenceUnitInfo = null;
163                }
164            } else if (ELEMENT_EXCLUDE_UNLISTED_CLASSES.equals(localName))
165            {
166                persistenceUnitInfo.excludeUnlistedClasses(Boolean.valueOf(string));
167            }
168        }
169    }
170
171    @Override
172    public void characters(final char[] ch, final int start, final int length) throws SAXException
173    {
174        final String s = new String(ch, start, length);
175
176        if (characters == null)
177        {
178            characters = new StringBuilder(s);
179        } else
180        {
181            characters.append(s);
182        }
183
184    }
185
186    @Override
187    public void ignorableWhitespace(final char[] ch, final int start, final int length)
188            throws SAXException
189    {
190    }
191
192    @Override
193    public void processingInstruction(final String target, final String data) throws SAXException
194    {
195    }
196
197    @Override
198    public void skippedEntity(final String name) throws SAXException
199    {
200    }
201
202    private <T extends Enum<T>> T toEnum(final Class<T> enumType, final String value)
203    {
204        return Enum.valueOf(enumType, value);
205    }
206}