/** * */ package org.geoserver.hibernate.dao; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.logging.Level; import javax.annotation.PostConstruct; import javax.management.InstanceAlreadyExistsException; import javax.management.MBeanRegistrationException; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import javax.persistence.Query; import org.geoserver.catalog.Catalog; import org.geoserver.catalog.LayerGroupInfo; import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.MapInfo; import org.geoserver.catalog.NamespaceInfo; import org.geoserver.catalog.ResourceInfo; import org.geoserver.catalog.StoreInfo; import org.geoserver.catalog.StyleInfo; import org.geoserver.catalog.WorkspaceInfo; import org.geoserver.catalog.hibernate.beans.LayerGroupInfoImplHb; import org.geoserver.catalog.hibernate.beans.LayerInfoImplHb; import org.geoserver.catalog.impl.MapInfoImpl; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.jmx.StatisticsService; import org.geoserver.catalog.impl.NamespaceInfoImpl; import org.geoserver.catalog.impl.StyleInfoImpl; import org.geoserver.catalog.impl.WorkspaceInfoImpl; import org.geoserver.hibernate.HibMapper; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; /** * */ @Repository @Transactional public class CatalogDAOImpl extends AbstractDAOImpl implements CatalogDAO { private boolean statsEnabled = false; public CatalogDAOImpl() { super(); } /** * @see Catalog#getDefaultNamespace() */ public NamespaceInfoImpl getDefaultNamespace() { Query query = buildQuery("from ", NamespaceInfoImpl.class, " where default = ", param(Boolean.TRUE)); return (NamespaceInfoImpl) first(query); } /** * */ public <T extends StoreInfo> T getStore(String id, Class<T> clazz) { Query query = buildQuery("from ", clazz, " where id = ", param(id)); return (T) first(query); } /** * */ @Deprecated public <T extends StoreInfo> T getStoreByName(String name, Class<T> clazz) { Query query = buildQuery("from ", clazz, " where name = ", param(name)); return (T) first(query); } public <T extends StoreInfo> List<T> getStoresByName(String name, Class<T> clazz) { Query query = buildQuery("from ", clazz, " where name = ", param(name)); return query.getResultList(); } public <T extends StoreInfo> T getStoreByName(WorkspaceInfo workspace, String name, Class<T> clazz) { Query query = buildQuery("from ", clazz, " where name = ", param(name), " and workspace = ", param(workspace)); return (T) first(query); } /** * */ public <T extends ResourceInfo> T getResource(String id, Class<T> clazz) { Query query = buildQuery("from ", clazz, " where id = ", param(id)); return (T) first(query); } /** * */ public <T extends ResourceInfo> T getResourceByName(String ns, String name, Class<T> clazz) { Query query = buildQuery("from ", clazz, " r where name = ", param(name), " and r.namespace.prefix = ", param(ns)); return (T) first(query); } public <T extends ResourceInfo> List<T> getResourcesByName(String name, Class<T> clazz) { Query query = buildQuery("from ", clazz, " r where name = ", param(name)); return query.getResultList(); } public <T extends ResourceInfo> T getResourceByStore(StoreInfo store, String name, Class<T> clazz) { Query query = buildQuery("from ", clazz, " r where name = ", param(name), " and r.store = ", param(store)); return (T) first(query); } public <T extends ResourceInfo> List<T> getResourcesByStore(StoreInfo store, Class<T> clazz) { Query query = buildQuery("from ", clazz, " r where r.store = ", param(store)); return query.getResultList(); } /** */ public LayerInfo getLayer(String id) { Query query = buildQuery("from ", LayerInfoImplHb.class, " where id = ", param(id)); return (LayerInfo) first(query); } /** * */ public LayerInfo getLayerByName(String name) { Query query = buildQuery("from ", LayerInfoImplHb.class, " where name = ", param(name)); LayerInfo layer = (LayerInfo) first(query); return layer; } public LayerInfo getLayerByName(String nsprefix, String name) { Query query = buildQuery("from ", LayerInfoImplHb.class, " l where l.name = ", param(name), " and l.resource.namespace.prefix = ", param(nsprefix)); return (LayerInfo) first(query); } public List<LayerInfo> getLayersByResourceId(String resid) { Query query = buildQuery("from ", LayerInfoImplHb.class, " where resource.id = ", param(resid)); return (List<LayerInfo>) query.getResultList(); } /** */ public <T extends StoreInfo> List<T> getStores(Class<T> clazz) { return (List<T>) list(clazz); } /** */ public <T extends ResourceInfo> List<T> getResources(Class<T> clazz) { return (List<T>) list(clazz); } /** */ public <T extends ResourceInfo> List<T> getResourcesByNamespace(NamespaceInfo namespace, Class<T> clazz) { Query query = buildQuery("select r from ", clazz, " r, ", NamespaceInfoImpl.class, " n", " where r.namespace = n and n.prefix = ", param(namespace.getPrefix())); return query.getResultList(); } /** * */ public MapInfo getMap(String id) { Query query = buildQuery("from ", MapInfoImpl.class, " where id = ", param(id)); return (MapInfo) first(query); } /** * */ public MapInfo getMapByName(String name) { Query query = buildQuery("from ", MapInfoImpl.class, " where name = ", param(name)); return (MapInfo) first(query); } /** * */ public List<MapInfo> getMaps() { return (List<MapInfo>) list(MapInfoImpl.class); } /** * */ public List<LayerInfo> getLayers() { // long t0 = System.currentTimeMillis(); List<LayerInfo> ret = (List<LayerInfo>) list(LayerInfoImplHb.class); // long t1 = System.currentTimeMillis(); // LOGGER.warning("getLayers -> " + (t1-t0)+ " ms : # " + ret.size()); return ret; } /** * */ public StyleInfo getStyle(String id) { Query query = buildQuery("from ", StyleInfoImpl.class, " where id = ", param(id)); return (StyleInfo) first(query); } /** * */ public StyleInfo getStyleByName(String name) { Query query = buildQuery("from ", StyleInfoImpl.class, " where name = ", param(name)); return (StyleInfo) first(query); } /** * */ public List<StyleInfo> getStyles() { return (List<StyleInfo>) list(StyleInfoImpl.class); } /** * */ public NamespaceInfoImpl getNamespace(String id) { Query query = buildQuery("from ", NamespaceInfoImpl.class, " where id = ", param(id)); return (NamespaceInfoImpl) first(query); } /** * */ public NamespaceInfoImpl getNamespaceByPrefix(String prefix) { Query query = buildQuery("from ", NamespaceInfoImpl.class, " where prefix = ", param(prefix)); return (NamespaceInfoImpl) first(query); } /** * */ public NamespaceInfo getNamespaceByURI(String uri) { Query query = buildQuery("from ", NamespaceInfoImpl.class, " where URI = ", param(uri)); return (NamespaceInfoImpl) first(query); } /** * */ public List<NamespaceInfo> getNamespaces() { return (List<NamespaceInfo>) list(NamespaceInfoImpl.class); } /** */ public WorkspaceInfoImpl getDefaultWorkspace() { Query query = buildQuery("from ", WorkspaceInfoImpl.class, " where default = ", param(Boolean.TRUE)); return (WorkspaceInfoImpl) first(query); } /** */ public List<LayerGroupInfo> getLayerGroups() { return (List<LayerGroupInfo>) list(LayerGroupInfoImplHb.class); } public LayerGroupInfo getLayerGroup(String id) { Query query = buildQuery("from ", LayerGroupInfoImplHb.class, " where id = ", param(id)); return (LayerGroupInfo) first(query); } public LayerGroupInfo getLayerGroupByName(String name) { Query query = buildQuery("from ", LayerGroupInfoImplHb.class, " where name = ", param(name)); return (LayerGroupInfo) first(query); } /** */ public <T extends StoreInfo> List<T> getStoresByWorkspace(WorkspaceInfo workspace, Class<T> clazz) { Query query = buildQuery("from ", clazz, " where workspace = ", param(workspace)); return query.getResultList(); } /** * */ public WorkspaceInfo getWorkspace(String id) { return (WorkspaceInfo) first(buildQuery("from ", WorkspaceInfo.class, " where id = ", param(id))); } /** * */ public WorkspaceInfo getWorkspaceByName(String name) { WorkspaceInfo ws = (WorkspaceInfo) first(buildQuery("from ", WorkspaceInfo.class, " where name = ", param(name))); return ws; } /** * */ public List<WorkspaceInfo> getWorkspaces() { return (List<WorkspaceInfo>) list(WorkspaceInfo.class); } public void save(StoreInfo entity) { super.save(entity); } public void delete(StoreInfo entity) { super.delete(entity); } public StoreInfo update(StoreInfo entity) { return super.merge(entity); } public void save(ResourceInfo entity) { super.save(entity); entityManager.flush(); // TODO useless?? entityManager.refresh(entity); // TODO useless?? } public void delete(ResourceInfo entity) { super.delete(entity); } public ResourceInfo update(ResourceInfo entity) { return super.merge(entity); } public void save(NamespaceInfo entity) { super.save(entity); } public void delete(NamespaceInfo entity) { super.delete(entity); entityManager.flush();// TODO useless?? } public NamespaceInfo update(NamespaceInfo entity) { return super.merge(entity); } public void save(LayerInfo entity) { // FIXME we are replacing some referenced object here because hib would recognized original // ones as unattached. if (entity.getResource().getId() != null) { Query query = buildQuery("from ", entity.getResource().getClass(), " where id = ", param(entity.getResource().getId())); ResourceInfo ri = (ResourceInfo) first(query); entity.setResource(ri); } // FIXME we are replacing some referenced object here because hib would recognized original // ones as unattached. if (entity.getDefaultStyle() != null) { Query query = buildQuery("from ", StyleInfo.class, " where id = ", param(entity.getDefaultStyle().getId())); StyleInfo style = (StyleInfo) first(query); entity.setDefaultStyle(style); } super.save(entity); } public void delete(LayerInfo entity) { super.delete(entity); } public LayerInfo update(LayerInfo entity) { if (entity.getDefaultStyle() != null && entity.getDefaultStyle().getId() != null) { LOGGER.info("Refreshing style in layer " + entity + " --> style id: " + entity.getDefaultStyle().getId()); StyleInfo style = (StyleInfo)entityManager.find(HibMapper.mapHibernableClass(StyleInfo.class), entity.getDefaultStyle().getId()); entity.setDefaultStyle(style); } return super.merge(entity); } public void save(MapInfo entity) { super.save(entity); } public void delete(MapInfo entity) { super.delete(entity); } public MapInfo update(MapInfo entity) { return super.merge(entity); } public void save(StyleInfo entity) { super.save(entity); } public void delete(StyleInfo entity) { super.delete(entity); } public StyleInfo update(StyleInfo entity) { return super.merge(entity); } public void save(LayerGroupInfo entity) { super.save(entity); } public void delete(LayerGroupInfo entity) { super.delete(entity); } public LayerGroupInfo update(LayerGroupInfo entity) { // OK, it's really ugly. // TODO: should be rewritten // Backup choosen layers/styles List l = new ArrayList(entity.getLayers()); List s = new ArrayList(entity.getStyles()); // LOGGER.info("LG(1 start): " + entity); // clearing layers/styles: the list will be set empty ((LayerGroupInfoImplHb) entity).getGroupedLayers().clear(); entity.getLayers().clear(); entity.getStyles().clear(); entity = super.merge(entity); // LOGGER.info("LG(cleared): " + entity); // really cleaning the db records entityManager.flush(); // LOGGER.info("LG(2 merged):" + entity); // restoring user list and backend list ((LayerGroupInfoImplHb) entity).setLayers(l); ((LayerGroupInfoImplHb) entity).setStyles(s); ((LayerGroupInfoImplHb) entity).preupdate(); // layers/styles are saved in fields not handled by hib, so the update could be not triggered automatically // LOGGER.info("LG(3 restored):" + entity); // merging the data: set the id into GroupedLayers entity = entityManager.merge(entity); // LOGGER.info("LG(4 merge):" + entity); // flush the whole changes. amen. entityManager.flush(); // LOGGER.info("LG(5 flush):" + entity); return entity; } public void save(WorkspaceInfo entity) { super.save(entity); entityManager.flush();// TODO useless?? entityManager.refresh(entity);// TODO useless?? } public void delete(WorkspaceInfo entity) { super.delete(entity); } public WorkspaceInfo update(WorkspaceInfo entity) { return super.merge(entity); } @PostConstruct protected void postProcess() { if (!isStatsEnabled()) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Statistics JMX bean is disabled."); } return; } if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Setting up statistics JMX bean"); } // make it a bit mroe generic final Object delegate = entityManager.getDelegate(); if (!(delegate instanceof Session)) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Unable to register statistics JMX bean"); } return; } //register the hibernate statistics service as an mbean final org.hibernate.Session session = (Session) delegate; final SessionFactory sessionFactory = session.getSessionFactory(); //build the ObjectName you want final Hashtable<String, String> tb = new Hashtable<String, String>(); tb.put("type", "statistics"); tb.put("sessionFactory", "GeoServer-Hib Statistics"); ObjectName on = null; try { on = new ObjectName("hibernate", tb); } catch (MalformedObjectNameException e) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.log(Level.INFO, "Unable to register statistics JMX bean", e); } return; } catch (NullPointerException e) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.log(Level.INFO, "Unable to register statistics JMX bean", e); } return; } StatisticsService stats = new StatisticsService(); stats.setSessionFactory(sessionFactory); try { if (on != null) { ManagementFactory.getPlatformMBeanServer().registerMBean(stats, on); } } catch (InstanceAlreadyExistsException e) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.log(Level.INFO, "Unable to register statistics JMX bean", e); } return; } catch (MBeanRegistrationException e) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.log(Level.INFO, "Unable to register statistics JMX bean", e); } return; } catch (NotCompliantMBeanException e) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.log(Level.INFO, "Unable to register statistics JMX bean", e); } return; } } public boolean isStatsEnabled() { return statsEnabled; } public void setStatsEnabled(boolean statsEnabled) { this.statsEnabled = statsEnabled; } }