| /* |
| * 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.assembler.classic; |
| |
| import org.apache.openejb.OpenEJBException; |
| import org.apache.openejb.OpenEJBRuntimeException; |
| import org.apache.openejb.api.internal.Internal; |
| import org.apache.openejb.api.jmx.Description; |
| import org.apache.openejb.api.jmx.MBean; |
| import org.apache.openejb.api.jmx.ManagedAttribute; |
| import org.apache.openejb.api.jmx.ManagedOperation; |
| import org.apache.openejb.jee.JAXBContextFactory; |
| import org.apache.openejb.jee.Persistence; |
| import org.apache.openejb.jee.PersistenceUnitCaching; |
| import org.apache.openejb.jee.PersistenceUnitValidationMode; |
| import org.apache.openejb.jpa.integration.JPAThreadContext; |
| import org.apache.openejb.loader.SystemInstance; |
| import org.apache.openejb.monitoring.DynamicMBeanWrapper; |
| import org.apache.openejb.monitoring.LocalMBeanServer; |
| import org.apache.openejb.monitoring.ObjectNameBuilder; |
| import org.apache.openejb.persistence.PersistenceUnitInfoImpl; |
| import org.apache.openejb.persistence.QueryLogEntityManager; |
| import org.apache.openejb.spi.ContainerSystem; |
| import org.apache.openejb.util.LogCategory; |
| import org.apache.openejb.util.Logger; |
| |
| import javax.management.MBeanServer; |
| import javax.management.ObjectName; |
| import javax.management.openmbean.TabularData; |
| import javax.naming.NamingException; |
| import javax.persistence.Cache; |
| import javax.persistence.EntityGraph; |
| import javax.persistence.EntityManager; |
| import javax.persistence.EntityManagerFactory; |
| import javax.persistence.PersistenceUnitUtil; |
| import javax.persistence.Query; |
| import javax.persistence.SharedCacheMode; |
| import javax.persistence.SynchronizationType; |
| import javax.persistence.ValidationMode; |
| import javax.persistence.criteria.CriteriaBuilder; |
| import javax.persistence.metamodel.Metamodel; |
| import javax.persistence.spi.PersistenceUnitInfo; |
| import javax.persistence.spi.PersistenceUnitTransactionType; |
| import javax.xml.bind.JAXBContext; |
| import javax.xml.bind.Marshaller; |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.InvalidObjectException; |
| import java.io.ObjectStreamException; |
| import java.io.Serializable; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.concurrent.TimeUnit; |
| |
| import static org.apache.openejb.monitoring.LocalMBeanServer.tabularData; |
| |
| @Internal |
| public class ReloadableEntityManagerFactory implements EntityManagerFactory, Serializable { |
| private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB, ReloadableEntityManagerFactory.class); |
| |
| public static final String JAVAX_PERSISTENCE_SHARED_CACHE_MODE = "javax.persistence.sharedCache.mode"; |
| public static final String JAVAX_PERSISTENCE_VALIDATION_MODE = "javax.persistence.validation.mode"; |
| public static final String JAVAX_PERSISTENCE_TRANSACTION_TYPE = "javax.persistence.transactionType"; |
| |
| public static final String OPENEJB_JPA_CRITERIA_LOG_JPQL = "openejb.jpa.criteria.log.jpql"; |
| public static final String OPENEJB_JPA_CRITERIA_LOG_JPQL_LEVEL = "openejb.jpa.criteria.log.jpql.level"; |
| |
| private final PersistenceUnitInfoImpl unitInfoImpl; |
| private ClassLoader classLoader; |
| private volatile EntityManagerFactory delegate; |
| private final EntityManagerFactoryCallable entityManagerFactoryCallable; |
| private ObjectName objectName; |
| |
| private final boolean logCriteriaJpql; |
| private final String logCriteriaJpqlLevel; |
| |
| public ReloadableEntityManagerFactory(final ClassLoader cl, final EntityManagerFactoryCallable callable, final PersistenceUnitInfoImpl unitInfo) { |
| classLoader = cl; |
| entityManagerFactoryCallable = callable; |
| unitInfoImpl = unitInfo; |
| final Properties properties = unitInfo.getProperties(); |
| logCriteriaJpql = logCriteriaQueryJpql(properties); |
| logCriteriaJpqlLevel = logCriteriaQueryJpqlLevel(properties); |
| |
| if (!callable.getUnitInfo().isLazilyInitialized()) { |
| createDelegate(); |
| } |
| } |
| |
| public void overrideClassLoader(final ClassLoader loader) { |
| classLoader = loader; |
| entityManagerFactoryCallable.overrideClassLoader(loader); |
| unitInfoImpl.setClassLoader(loader); |
| } |
| |
| public EntityManagerFactoryCallable getEntityManagerFactoryCallable() { |
| return entityManagerFactoryCallable; |
| } |
| |
| private EntityManagerFactory delegate() { |
| if (delegate == null) { |
| synchronized (this) { |
| if (delegate == null) { |
| createDelegate(); |
| } |
| } |
| } |
| return delegate; |
| } |
| |
| public void createDelegate() { |
| JPAThreadContext.infos.put("properties", entityManagerFactoryCallable.getUnitInfo().getProperties()); |
| final long start = System.nanoTime(); |
| try { |
| delegate = entityManagerFactoryCallable.call(); |
| } catch (final Exception e) { |
| throw new OpenEJBRuntimeException(e); |
| } finally { |
| final long time = TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS); |
| LOGGER.info("assembler.buildingPersistenceUnit", unitInfoImpl.getPersistenceUnitName(), unitInfoImpl.getPersistenceProviderClassName(), String.valueOf(time)); |
| if (LOGGER.isDebugEnabled()) { |
| for (final Map.Entry<Object, Object> entry : unitInfoImpl.getProperties().entrySet()) { |
| LOGGER.debug(entry.getKey() + "=" + entry.getValue()); |
| } |
| } |
| |
| JPAThreadContext.infos.clear(); |
| } |
| } |
| |
| private String logCriteriaQueryJpqlLevel(final Properties props) { |
| return SystemInstance.get().getOptions().get(OPENEJB_JPA_CRITERIA_LOG_JPQL_LEVEL, props.getProperty(OPENEJB_JPA_CRITERIA_LOG_JPQL_LEVEL, "INFO")); |
| } |
| |
| private boolean logCriteriaQueryJpql(final Properties prop) { |
| return SystemInstance.get().getOptions().get(OPENEJB_JPA_CRITERIA_LOG_JPQL, Boolean.parseBoolean(prop.getProperty(OPENEJB_JPA_CRITERIA_LOG_JPQL, "false"))) |
| || SystemInstance.get().getOptions().get(OPENEJB_JPA_CRITERIA_LOG_JPQL_LEVEL, prop.getProperty(OPENEJB_JPA_CRITERIA_LOG_JPQL_LEVEL, null)) != null; |
| } |
| |
| @Override |
| public EntityManager createEntityManager() { |
| EntityManager em; |
| try { |
| em = delegate().createEntityManager(); |
| } catch (final LinkageError le) { |
| em = delegate.createEntityManager(); |
| } |
| |
| if (logCriteriaJpql) { |
| return new QueryLogEntityManager(em, logCriteriaJpqlLevel); |
| } |
| return em; |
| } |
| |
| @Override |
| public EntityManager createEntityManager(final Map map) { |
| EntityManager em; |
| try { |
| em = delegate().createEntityManager(map); |
| } catch (final LinkageError le) { |
| em = delegate.createEntityManager(map); |
| } |
| |
| if (logCriteriaJpql) { |
| return new QueryLogEntityManager(em, logCriteriaJpqlLevel); |
| } |
| return em; |
| } |
| |
| @Override |
| public EntityManager createEntityManager(final SynchronizationType synchronizationType) { |
| EntityManager em; |
| try { |
| em = delegate().createEntityManager(synchronizationType); |
| } catch (final LinkageError le) { |
| em = delegate.createEntityManager(synchronizationType); |
| } |
| |
| if (logCriteriaJpql) { |
| return new QueryLogEntityManager(em, logCriteriaJpqlLevel); |
| } |
| return em; |
| } |
| |
| @Override |
| public EntityManager createEntityManager(final SynchronizationType synchronizationType, final Map map) { |
| EntityManager em; |
| try { |
| em = delegate().createEntityManager(synchronizationType, map); |
| } catch (final LinkageError le) { |
| em = delegate.createEntityManager(synchronizationType, map); |
| } |
| |
| if (logCriteriaJpql) { |
| return new QueryLogEntityManager(em, logCriteriaJpqlLevel); |
| } |
| return em; |
| } |
| |
| @Override |
| public <T> T unwrap(final Class<T> cls) { |
| if (cls.isAssignableFrom(getClass())) { |
| return cls.cast(this); |
| } |
| return delegate().unwrap(cls); |
| } |
| |
| @Override |
| public void addNamedQuery(final String name, final Query query) { |
| delegate().addNamedQuery(name, query); |
| } |
| |
| @Override |
| public <T> void addNamedEntityGraph(final String graphName, final EntityGraph<T> entityGraph) { |
| delegate().addNamedEntityGraph(graphName, entityGraph); |
| } |
| |
| @Override |
| public CriteriaBuilder getCriteriaBuilder() { |
| return delegate().getCriteriaBuilder(); |
| } |
| |
| @Override |
| public Metamodel getMetamodel() { |
| return delegate().getMetamodel(); |
| } |
| |
| @Override |
| public boolean isOpen() { |
| return delegate().isOpen(); |
| } |
| |
| @Override |
| public synchronized void close() { |
| if (delegate != null) { |
| delegate.close(); |
| } |
| } |
| |
| @Override |
| public Map<String, Object> getProperties() { |
| return delegate().getProperties(); |
| } |
| |
| @Override |
| public Cache getCache() { |
| return delegate().getCache(); |
| } |
| |
| @Override |
| public PersistenceUnitUtil getPersistenceUnitUtil() { |
| return delegate().getPersistenceUnitUtil(); |
| } |
| |
| public EntityManagerFactory getDelegate() { |
| return delegate(); |
| } |
| |
| public void register() throws OpenEJBException { |
| if (!LocalMBeanServer.isJMXActive()) { |
| return; |
| } |
| |
| final MBeanServer server = LocalMBeanServer.get(); |
| try { |
| generateObjectName(); |
| if (server.isRegistered(objectName)) { |
| server.unregisterMBean(objectName); |
| } |
| server.registerMBean(mBeanify(), objectName); |
| } catch (final Exception e) { |
| throw new OpenEJBException("can't register the mbean for the entity manager factory " + getPUname(), e); |
| } catch (final NoClassDefFoundError ncdfe) { |
| objectName = null; |
| LOGGER.error("can't register the mbean for the entity manager factory {0}", getPUname()); |
| } |
| } |
| |
| private ObjectName generateObjectName() { |
| final ObjectNameBuilder jmxName = new ObjectNameBuilder("openejb.management"); |
| jmxName.set("ObjectType", "persistence-unit"); |
| jmxName.set("PersistenceUnit", getPUname()); |
| objectName = jmxName.build(); |
| |
| final MBeanServer server = LocalMBeanServer.get(); |
| if (server.isRegistered(objectName)) { // if 2 pu have the same name...a bit uglier but unique |
| jmxName.set("PersistenceUnit", getPUname() + "(" + getId() + ")"); |
| objectName = jmxName.build(); |
| } |
| |
| return objectName; |
| } |
| |
| private String getPUname() { |
| return entityManagerFactoryCallable.getUnitInfo().getPersistenceUnitName(); |
| } |
| |
| private String getId() { |
| return entityManagerFactoryCallable.getUnitInfo().getId(); |
| } |
| |
| private Object mBeanify() { |
| return new DynamicMBeanWrapper(new JMXReloadableEntityManagerFactory(this)); |
| } |
| |
| public void unregister() throws OpenEJBException { |
| if (objectName != null) { |
| final MBeanServer server = LocalMBeanServer.get(); |
| try { |
| server.unregisterMBean(objectName); |
| } catch (final Exception e) { |
| throw new OpenEJBException("can't unregister the mbean for the entity manager factory " + getPUname(), e); |
| } |
| } |
| } |
| |
| // only this method is synchronized since we want to avoid locks on other methods. |
| // it is just to avoid problems due to the "double click syndrom" |
| // |
| // Note: it uses the old unitInfo but properties can be modified (not managed classes, provider...) |
| public synchronized void reload() { |
| try { |
| createDelegate(); |
| } catch (final Exception e) { |
| LOGGER.error("can't replace EntityManagerFactory " + delegate, e); |
| } |
| } |
| |
| public synchronized void setSharedCacheMode(final SharedCacheMode mode) { |
| final PersistenceUnitInfoImpl info = entityManagerFactoryCallable.getUnitInfo(); |
| info.setSharedCacheMode(mode); |
| |
| final Properties properties = entityManagerFactoryCallable.getUnitInfo().getProperties(); |
| if (properties.containsKey(JAVAX_PERSISTENCE_SHARED_CACHE_MODE)) { |
| properties.setProperty(JAVAX_PERSISTENCE_SHARED_CACHE_MODE, mode.name()); |
| } |
| } |
| |
| public synchronized void setValidationMode(final ValidationMode mode) { |
| final PersistenceUnitInfoImpl info = entityManagerFactoryCallable.getUnitInfo(); |
| info.setValidationMode(mode); |
| |
| final Properties properties = entityManagerFactoryCallable.getUnitInfo().getProperties(); |
| if (properties.containsKey(JAVAX_PERSISTENCE_VALIDATION_MODE)) { |
| properties.setProperty(JAVAX_PERSISTENCE_VALIDATION_MODE, mode.name()); |
| } |
| } |
| |
| public synchronized void setProvider(final String providerRaw) { |
| final String provider = providerRaw.trim(); |
| final String newProvider; |
| switch (provider) { |
| case "hibernate": |
| newProvider = "org.hibernate.ejb.HibernatePersistence"; |
| break; |
| case "openjpa": |
| newProvider = "org.apache.openjpa.persistence.PersistenceProviderImpl"; |
| break; |
| case "eclipselink": |
| newProvider = "org.eclipse.persistence.jpa.PersistenceProvider"; |
| break; |
| case "toplink": |
| newProvider = "oracle.toplink.essentials.PersistenceProvider"; |
| break; |
| default: |
| newProvider = provider; |
| break; |
| } |
| |
| try { |
| classLoader.loadClass(newProvider); |
| entityManagerFactoryCallable.getUnitInfo().setPersistenceProviderClassName(newProvider); |
| } catch (final ClassNotFoundException e) { |
| LOGGER.error("can't load new provider " + newProvider, e); |
| } |
| } |
| |
| public synchronized void setTransactionType(final PersistenceUnitTransactionType type) { |
| final PersistenceUnitInfoImpl info = entityManagerFactoryCallable.getUnitInfo(); |
| info.setTransactionType(type); |
| |
| final Properties properties = entityManagerFactoryCallable.getUnitInfo().getProperties(); |
| if (properties.containsKey(JAVAX_PERSISTENCE_TRANSACTION_TYPE)) { |
| properties.setProperty(JAVAX_PERSISTENCE_TRANSACTION_TYPE, type.name()); |
| } |
| } |
| |
| public synchronized void setProperty(final String key, final String value) { |
| final PersistenceUnitInfoImpl unitInfo = entityManagerFactoryCallable.getUnitInfo(); |
| if (unitInfo.getProperties() == null) { |
| unitInfo.setProperties(new Properties()); |
| } |
| unitInfo.getProperties().setProperty(key, value); |
| } |
| |
| public synchronized void removeProperty(final String key) { |
| final PersistenceUnitInfoImpl unitInfo = entityManagerFactoryCallable.getUnitInfo(); |
| if (unitInfo.getProperties() != null) { |
| unitInfo.getProperties().remove(key); |
| } |
| } |
| |
| public Properties getUnitProperties() { |
| final PersistenceUnitInfoImpl unitInfo = entityManagerFactoryCallable.getUnitInfo(); |
| if (unitInfo.getProperties() != null) { |
| return unitInfo.getProperties(); |
| } |
| return new Properties(); |
| } |
| |
| public List<String> getMappingFiles() { |
| return entityManagerFactoryCallable.getUnitInfo().getMappingFileNames(); |
| } |
| |
| public void addMappingFile(final String file) { |
| if (new File(file).exists()) { |
| entityManagerFactoryCallable.getUnitInfo().addMappingFileName(file); |
| } else { |
| LOGGER.error("file " + file + " doesn't exists"); |
| } |
| } |
| |
| public void removeMappingFile(final String file) { |
| entityManagerFactoryCallable.getUnitInfo().getMappingFileNames().remove(file); |
| } |
| |
| public List<URL> getJarFileUrls() { |
| return entityManagerFactoryCallable.getUnitInfo().getJarFileUrls(); |
| } |
| |
| public void addJarFileUrls(final String file) { |
| if (new File(file).exists()) { // should we test real urls? |
| try { |
| entityManagerFactoryCallable.getUnitInfo().getJarFileUrls().add(new URL(file)); |
| } catch (final MalformedURLException e) { |
| LOGGER.error("url " + file + " is malformed"); |
| } |
| } else { |
| LOGGER.error("url " + file + " is not correct"); |
| } |
| } |
| |
| public void removeJarFileUrls(final String file) { |
| try { |
| entityManagerFactoryCallable.getUnitInfo().getJarFileUrls().remove(new URL(file)); |
| } catch (final MalformedURLException e) { |
| LOGGER.error("url " + file + " is malformed"); |
| } |
| } |
| |
| public List<String> getManagedClasses() { |
| return entityManagerFactoryCallable.getUnitInfo().getManagedClassNames(); |
| } |
| |
| public void addManagedClasses(final String clazz) { |
| entityManagerFactoryCallable.getUnitInfo().getManagedClassNames().add(clazz); |
| } |
| |
| public void removeManagedClasses(final String clazz) { |
| entityManagerFactoryCallable.getUnitInfo().getManagedClassNames().remove(clazz); |
| } |
| |
| public PersistenceUnitInfo info() { |
| return entityManagerFactoryCallable.getUnitInfo(); |
| } |
| |
| public void setExcludeUnlistedClasses(final boolean excludeUnlistedClasses) { |
| entityManagerFactoryCallable.getUnitInfo().setExcludeUnlistedClasses(excludeUnlistedClasses); |
| } |
| |
| public boolean getExcludeUnlistedClasses() { |
| return entityManagerFactoryCallable.getUnitInfo().excludeUnlistedClasses(); |
| } |
| |
| Object writeReplace() throws ObjectStreamException { |
| return new SerializableEm("java:" + Assembler.PERSISTENCE_UNIT_NAMING_CONTEXT + unitInfoImpl.getId()); |
| } |
| |
| @MBean |
| @Internal |
| @Description("represents a persistence unit managed by OpenEJB") |
| public static class JMXReloadableEntityManagerFactory { |
| private final ReloadableEntityManagerFactory reloadableEntityManagerFactory; |
| |
| public JMXReloadableEntityManagerFactory(final ReloadableEntityManagerFactory remf) { |
| reloadableEntityManagerFactory = remf; |
| } |
| |
| @ManagedOperation |
| @Description("recreate the entity manager factory using new properties") |
| public void reload() { |
| reloadableEntityManagerFactory.reload(); |
| } |
| |
| @ManagedOperation |
| @Description("change the current JPA provider") |
| public void setProvider(final String provider) { |
| reloadableEntityManagerFactory.setProvider(provider); |
| } |
| |
| @ManagedOperation |
| @Description("change the current transaction type") |
| public void setTransactionType(final String type) { |
| try { |
| final PersistenceUnitTransactionType tt = PersistenceUnitTransactionType.valueOf(type.toUpperCase()); |
| reloadableEntityManagerFactory.setTransactionType(tt); |
| } catch (final Exception iae) { |
| // ignored |
| } |
| } |
| |
| @ManagedOperation |
| @Description("create or modify a property of the persistence unit") |
| public void setProperty(final String key, final String value) { |
| reloadableEntityManagerFactory.setProperty(key, value); |
| } |
| |
| @ManagedOperation |
| @Description("remove a property of the persistence unit if it exists") |
| public void removeProperty(final String key) { |
| reloadableEntityManagerFactory.removeProperty(key); |
| } |
| |
| @ManagedOperation |
| @Description("add a mapping file") |
| public void addMappingFile(final String file) { |
| reloadableEntityManagerFactory.addMappingFile(file); |
| } |
| |
| @ManagedOperation |
| @Description("remove a mapping file") |
| public void removeMappingFile(final String file) { |
| reloadableEntityManagerFactory.removeMappingFile(file); |
| } |
| |
| @ManagedOperation |
| @Description("add a managed class") |
| public void addManagedClass(final String clazz) { |
| reloadableEntityManagerFactory.addManagedClasses(clazz); |
| } |
| |
| @ManagedOperation |
| @Description("remove a managed class") |
| public void removeManagedClass(final String clazz) { |
| reloadableEntityManagerFactory.removeManagedClasses(clazz); |
| } |
| |
| @ManagedOperation |
| @Description("add a jar file") |
| public void addJarFile(final String file) { |
| reloadableEntityManagerFactory.addJarFileUrls(file); |
| } |
| |
| @ManagedOperation |
| @Description("remove a jar file") |
| public void removeJarFile(final String file) { |
| reloadableEntityManagerFactory.removeJarFileUrls(file); |
| } |
| |
| @ManagedOperation |
| @Description("change the shared cache mode if possible (value is ok)") |
| public void setSharedCacheMode(final String value) { |
| try { |
| final String v = value.trim().toUpperCase(); |
| final SharedCacheMode mode = v.isEmpty() ? SharedCacheMode.UNSPECIFIED : SharedCacheMode.valueOf(v); |
| reloadableEntityManagerFactory.setSharedCacheMode(mode); |
| } catch (final Exception iae) { |
| // ignored |
| } |
| } |
| |
| @ManagedOperation |
| @Description("exclude or not unlisted entities") |
| public void setExcludeUnlistedClasses(final boolean value) { |
| reloadableEntityManagerFactory.setExcludeUnlistedClasses(value); |
| } |
| |
| @ManagedOperation |
| @Description("change the validation mode if possible (value is ok)") |
| public void setValidationMode(final String value) { |
| try { |
| final ValidationMode mode = ValidationMode.valueOf(value.trim().toUpperCase()); |
| reloadableEntityManagerFactory.setValidationMode(mode); |
| } catch (final Exception iae) { |
| LOGGER.warning("Can't set validation mode " + value, iae); |
| reloadableEntityManagerFactory.setProperty(JAVAX_PERSISTENCE_VALIDATION_MODE, value); |
| } |
| } |
| |
| @ManagedOperation |
| @Description("dump the current configuration for this persistence unit in a file") |
| public void dump(final String file) { |
| final PersistenceUnitInfoImpl info = reloadableEntityManagerFactory.entityManagerFactoryCallable.getUnitInfo(); |
| |
| final Persistence.PersistenceUnit pu = new Persistence.PersistenceUnit(); |
| pu.setJtaDataSource(info.getJtaDataSourceName()); |
| pu.setNonJtaDataSource(info.getNonJtaDataSourceName()); |
| pu.getClazz().addAll(info.getManagedClassNames()); |
| pu.getMappingFile().addAll(info.getMappingFileNames()); |
| pu.setName(info.getPersistenceUnitName()); |
| pu.setProvider(info.getPersistenceProviderClassName()); |
| pu.setTransactionType(info.getTransactionType().name()); |
| pu.setExcludeUnlistedClasses(info.excludeUnlistedClasses()); |
| pu.setSharedCacheMode(PersistenceUnitCaching.fromValue(info.getSharedCacheMode().name())); |
| pu.setValidationMode(PersistenceUnitValidationMode.fromValue(info.getValidationMode().name())); |
| for (final URL url : info.getJarFileUrls()) { |
| pu.getJarFile().add(url.toString()); |
| } |
| for (final String key : info.getProperties().stringPropertyNames()) { |
| final Persistence.PersistenceUnit.Properties.Property prop = new Persistence.PersistenceUnit.Properties.Property(); |
| prop.setName(key); |
| prop.setValue(info.getProperties().getProperty(key)); |
| if (pu.getProperties() == null) { |
| pu.setProperties(new Persistence.PersistenceUnit.Properties()); |
| } |
| pu.getProperties().getProperty().add(prop); |
| } |
| |
| final Persistence persistence = new Persistence(); |
| persistence.setVersion(info.getPersistenceXMLSchemaVersion()); |
| persistence.getPersistenceUnit().add(pu); |
| |
| try (final FileWriter writer = new FileWriter(file)) { |
| final JAXBContext jc = JAXBContextFactory.newInstance(Persistence.class); |
| final Marshaller marshaller = jc.createMarshaller(); |
| marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); |
| marshaller.marshal(persistence, writer); |
| } catch (final Exception e) { |
| LOGGER.error("can't dump pu " + reloadableEntityManagerFactory.getPUname() + " in file " + file, e); |
| } |
| } |
| |
| @ManagedAttribute |
| @Description("get exclude unlisted classes") |
| public boolean getExcludeUnlistedClasses() { |
| return reloadableEntityManagerFactory.getExcludeUnlistedClasses(); |
| } |
| |
| @ManagedAttribute |
| @Description("get all properties") |
| public TabularData getProperties() { |
| return tabularData("properties", "properties type", |
| "Property of " + reloadableEntityManagerFactory.getPUname(), |
| reloadableEntityManagerFactory.getUnitProperties()); |
| } |
| |
| @ManagedAttribute |
| @Description("get all mapping files") |
| public TabularData getMappingFiles() { |
| return buildTabularData("mappingfile", "mapping file type", |
| reloadableEntityManagerFactory.getMappingFiles(), Info.FILE); |
| } |
| |
| @ManagedAttribute |
| @Description("get all jar files") |
| public TabularData getJarFiles() { |
| return buildTabularData("jarfile", "jar file type", |
| reloadableEntityManagerFactory.getJarFileUrls(), Info.URL); |
| } |
| |
| @ManagedAttribute |
| @Description("get all managed classes") |
| public TabularData getManagedClasses() { |
| return buildTabularData("managedclass", "managed class type", |
| reloadableEntityManagerFactory.getManagedClasses(), Info.CLASS); |
| } |
| |
| private TabularData buildTabularData(final String typeName, final String typeDescription, final List<?> list, final Info info) { |
| final String[] names = new String[list.size()]; |
| final Object[] values = new Object[names.length]; |
| int i = 0; |
| for (final Object o : list) { |
| names[i] = o.toString(); |
| values[i++] = info.info(reloadableEntityManagerFactory.classLoader, o); |
| } |
| return tabularData(typeName, typeDescription, names, values); |
| } |
| |
| private enum Info { |
| URL, NONE, FILE, CLASS; |
| |
| public String info(final ClassLoader cl, final Object o) { |
| switch (this) { |
| case URL: |
| try { |
| if (((URL) o).openConnection().getContentLength() > 0) { |
| return "valid"; |
| } |
| } catch (final IOException e) { |
| // ignored |
| } |
| return "not valid"; |
| |
| case FILE: |
| final File file; |
| if (o instanceof String) { |
| file = new File((String) o); |
| } else if (o instanceof File) { |
| file = (File) o; |
| } else { |
| return "unknown"; |
| } |
| return "exist? " + file.exists(); |
| |
| case CLASS: |
| try { |
| cl.loadClass((String) o); |
| return "loaded"; |
| } catch (final ClassNotFoundException e) { |
| return "unloadable"; |
| } |
| |
| default: |
| return "-"; |
| } |
| } |
| } |
| } |
| |
| private static final class SerializableEm implements Serializable { |
| private final String jndiName; |
| |
| private SerializableEm(final String jndiName) { |
| this.jndiName = jndiName; |
| } |
| |
| Object readResolve() throws ObjectStreamException { |
| try { |
| return SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext().lookup(jndiName); |
| } catch (final NamingException e) { |
| throw new InvalidObjectException(e.getMessage()); |
| } |
| } |
| } |
| } |