/* * Copyright 2008-2011 the original author or authors. * * 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 org.kaleidofoundry.core.config; import static org.kaleidofoundry.core.env.model.EnvironmentConstants.KALEIDO_PERSISTENT_UNIT_NAME; import java.io.Serializable; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map.Entry; import java.util.Set; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import javax.persistence.PersistenceException; import javax.persistence.Query; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; import javax.ws.rs.core.UriInfo; import javax.xml.bind.annotation.XmlElementWrapper; import org.kaleidofoundry.core.config.model.ConfigurationModel; import org.kaleidofoundry.core.config.model.ConfigurationModelConstants.Query_FindAllConfiguration; import org.kaleidofoundry.core.config.model.ConfigurationModelConstants.Query_FindConfigurationByName; import org.kaleidofoundry.core.config.model.ConfigurationModelConstants.Query_FindConfigurationByText; import org.kaleidofoundry.core.config.model.ConfigurationModelConstants.Query_FindPropertyByName; import org.kaleidofoundry.core.config.model.ConfigurationProperty; import org.kaleidofoundry.core.config.model.FireChangesReport; import org.kaleidofoundry.core.lang.annotation.Task; import org.kaleidofoundry.core.lang.annotation.TaskLabel; import org.kaleidofoundry.core.lang.annotation.Tasks; import org.kaleidofoundry.core.persistence.UnmanagedEntityManagerFactory; import org.kaleidofoundry.core.store.ResourceException; import org.kaleidofoundry.core.util.StringHelper; /** * Configuration controller is used to expose configuration management.<br/> * With it you can manage the configuration model and its properties <br/> * It is exposed as a RESTful service or as an EJB managed bean.<br/> * <br/> * <p> * <h4>RESTful API urls :</h4> * <table border="1"> * <tr> * <td>Action</td> * <td>Url</td> * <td>Filter parameter / Remarks</td> * </tr> * <tr> * <td>GET</td> * <td>/configurations/</td> * <td>"text" is filter to search by name, url, description</td> * </tr> * <tr> * <td>GET|DELETE</td> * <td>/configurations/{config}/</td> * <td> </td> * </tr> * <tr> * <td>GET</td> * <td>/configurations/{config}/keys</td> * <td>"text" is a filter to search keys containing this token</td> * </tr> * <tr> * <td>GET|PUT</td> * <td>/configurations/{config}/{property}</td> * <td>for {property} use the java propety syntax like "application.version"</td> * </tr> * <tr> * <td>GET|PUT|DELETE</td> * <td>/configurations/{config}/property/{property}</td> * <td>for {property} use the java propety syntax like "application.version"</td> * </tr> * <tr> * <td>GET</td> * <td>/configurations/properties</td> * <td>"config" is a filter on the configuration name | "text" is a filter on name / description</td> * </tr> * </table> * <p> * TODO refactor following actions PUT {config}/register (Refactor some rest actions url: rest url is resources not action)<br/> * PUT {config}/unregister <br/> * GET {config}/registered<br/> * GET {config}/fireChanges<br/> * PUT {config}/store<br/> * PUT {config}/load<br/> * PUT {config}/unload<br/> * PUT {config}/reload<br/> * GET {config}/loaded<br/> * </p> * </p> <h4>RESTful resources :</h4> * <p> * <ul> * <li>jee5 : http://blogs.sun.com/enterprisetechtips/entry/implementing_restful_web_services_in</li> * <li>jee6 : http://java.sun.com/developer/technicalArticles/WebServices/jax-rs/index.html</li> * <li>jax-rs 1.0 : http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features</li> * <li>htpp : http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html</li> * </ul> * </p> * * @author jraduget * @see Configuration * @see ConfigurationProperty */ @Stateless(mappedName = "ejb/configurations/manager") @Path("/configurations/") @Tasks(tasks = { @Task(labels = TaskLabel.Defect, comment = "restore 'implements ConfigurationController which cause a bug' - I open a GF3.x bug for this : GLASSFISH-16199"), @Task(labels = TaskLabel.Documentation, comment = "Refactor some rest actions url: rest url is resources not action") }) public class ConfigurationController { /** injected and used to handle security context */ @Context SecurityContext securityContext; /** injected and used to handle URIs */ @Context UriInfo uriInfo; /** injected entity manager */ @PersistenceContext(unitName = KALEIDO_PERSISTENT_UNIT_NAME) EntityManager em; // ### Property management methods ############################################################################################ public ConfigurationController() { try { // em will be injected by by java ee container or if not by aspectj if (em == null) { em = UnmanagedEntityManagerFactory.currentEntityManager(KALEIDO_PERSISTENT_UNIT_NAME); } } catch (PersistenceException pe) { em = null; } } /** * get the property value as a string * * @param config configuration name identifier * @param property * @return the raw property value * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model * @throws PropertyNotFoundException if property can't be found in configuration * @throws ConfigurationException if configuration is not yet loaded */ @GET @Path("/{config}/{property}") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public String getPropertyValue(final @PathParam("config") String config, final @PathParam("property") String property) { try { String value = getRegisteredConfiguration(config).getString(property); if (value == null) { throw new PropertyNotFoundException(config, property); } return value; } catch (ConfigurationNotFoundException cne) { return getProperty(config, property).getValue(String.class); } } /** * get the raw property value * * @param config configuration name identifier * @param property * @param type * @return the property value (converted as type T) * @throws ConfigurationNotFoundException * @throws PropertyNotFoundException * @param <T> */ public <T extends Serializable> T getPropertyValue(final String config, final String property, final Class<T> type) { try { T value = getRegisteredConfiguration(config).getProperty(property, type); if (value == null) { throw new PropertyNotFoundException(config, property); } return value; } catch (ConfigurationNotFoundException cne) { return getProperty(config, property).getValue(type); } } /** * set / define / change the value of a property (but do not persist it. Call {@link #store(String)} to persist its value) * * @param config configuration name identifier * @param property * @param value the new value to set * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model * @throws PropertyNotFoundException if property can't be found in configuration meta model. Call * {@link #putProperty(String, ConfigurationProperty)} to set a new one * @throws ConfigurationException if configuration is not yet loaded */ @PUT @Path("/{config}/{property}") public void setPropertyValue(final @PathParam("config") String config, @PathParam("property") final String property, @QueryParam("value") final String value) { setPropertyValue(config, property, value, String.class); } /** * set / define / change the value of a property (but do not persist it. Call {@link #store(String)} to persist its value) * * @param config configuration name identifier * @param property * @param value the new value to set * @param type the type of the value * @return the old property value * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model * @throws PropertyNotFoundException if property can't be found in configuration meta model. Call * {@link #putProperty(String, ConfigurationProperty)} to set a new one * @throws ConfigurationException if configuration is not yet loaded * @param <T> */ public <T extends Serializable> T setPropertyValue(final String config, final String property, final T value, final Class<T> type) { boolean foundConfiguration = false; boolean foundConfigurationProperty = false; T oldValue = null; // get registered configuration and set the property value try { Configuration configuration = getRegisteredConfiguration(config); oldValue = configuration.getProperty(property, type); configuration.setProperty(property, value); foundConfiguration = true; foundConfigurationProperty = true; } catch (ConfigurationNotFoundException cne) { } if (em != null && !foundConfigurationProperty) { // get model configuration and set the property value try { ConfigurationProperty configurationProperty = findConfigurationPropertyByName(config, property, true); if (!foundConfigurationProperty) { oldValue = configurationProperty.getValue(type); } configurationProperty.setValue(value); em.merge(configurationProperty); em.flush(); foundConfigurationProperty = true; } catch (ConfigurationNotFoundException cnfe) { if (!foundConfiguration) { throw cnfe; } } } if (!foundConfigurationProperty) { throw new PropertyNotFoundException(config, property); } // check that property exists in the model return oldValue; } /** * get the property * * @param config configuration name identifier * @param property * @return the raw property value * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model * @throws PropertyNotFoundException if property can't be found in configuration * @throws ConfigurationException if configuration is not yet loaded */ @GET @Path("/{config}/property/{property}") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public ConfigurationProperty getProperty(final @PathParam("config") String config, final @PathParam("property") String property) { ConfigurationException ce; try { // first, check that property exists in the model return findConfigurationPropertyByName(config, property, true); } catch (ConfigurationNotFoundException cnfe) { ce = cnfe; } catch (PropertyNotFoundException pne) { ce = pne; } // second, build a non persistent one with the given information try { ConfigurationProperty cp = getRegisteredProperty(config, property, true); ConfigurationModel cm = getModel(config); cp.getConfigurations().add(cm); return cp; } catch (ConfigurationNotFoundException cnfe) { if (ce instanceof PropertyNotFoundException) { throw ce; } else { throw cnfe; } } } /** * define and persist a new property in the configuration meta model * * @param config configuration name identifier * @param property * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model * @throws ConfigurationException */ @PUT @Path("/{config}/property") @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public void putProperty(final @PathParam("config") String config, final ConfigurationProperty property) { ConfigurationProperty currentProperty = findConfigurationPropertyByName(config, property.getName(), false); // meta data update if (em != null) { ConfigurationModel configurationModel = getModel(config); // if it is a new property creation if (currentProperty == null) { if (configurationModel.getProperties().contains(property)) { configurationModel.getProperties().remove(property); } configurationModel.getProperties().add(property); property.getConfigurations().add(configurationModel); em.persist(property); } // if it is an update property else { // configurationModel.getProperties().add(currentProperty); // currentProperty.getConfigurations().add(configurationModel); currentProperty.setName(property.getName()); currentProperty.setType(property.getType()); currentProperty.setValue(property.getValue()); currentProperty.setDescription(property.getDescription()); em.merge(currentProperty); } em.merge(configurationModel); em.flush(); } } /** * remove the property from the configuration * * @param config configuration name identifier * @param property * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model * @throws PropertyNotFoundException if property can't be found in configuration * @throws ConfigurationException if configuration is not yet loaded */ @DELETE @Path("/{config}/property/{property}") public void removeProperty(final @PathParam("config") String config, @PathParam("property") final String property) { boolean foundConfiguration = false; boolean foundConfigurationProperty = false; if (em != null) { ConfigurationModel configurationModel = findConfigurationModelByName(config, false); if (configurationModel != null) { foundConfiguration = true; ConfigurationProperty configurationProperty = configurationModel.getPropertiesByName().get(property); if (configurationProperty != null) { foundConfigurationProperty = true; // remove it from meta data database configurationModel.getProperties().remove(configurationProperty); em.merge(configurationModel); em.remove(em.merge(configurationProperty)); em.flush(); } } } try { Configuration configuration = getRegisteredConfiguration(config); // check if property exists if (!foundConfigurationProperty && !configuration.containsKey(property)) { throw new PropertyNotFoundException(config, property); } // remove it from registered configuration configuration.removeProperty(property); } catch (ConfigurationNotFoundException cnfe) { if (!foundConfiguration) { throw cnfe; } if (!foundConfigurationProperty) { throw new PropertyNotFoundException(config, property); } } } /** * @param config configuration name identifier * @return a set (clone) of all the declared property keys <br/> * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model */ public Set<ConfigurationProperty> getProperties(final String config) { return getModel(config).getProperties(); } /** * finding configuration properties by using a text search in the fields {@link ConfigurationProperty#getName()}, * {@link ConfigurationProperty#getDescription()}, {@link ConfigurationProperty#getLabels()}, {@link ConfigurationProperty#getValue()} * * @param config configuration name identifier (not mandatory) * @param text text token to search * @return list of configuration properties matching the text argument */ @GET @Path("/properties") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public List<ConfigurationProperty> findProperties(final @QueryParam("config") String config, @QueryParam("text") final String text) { final List<ConfigurationProperty> properties = new ArrayList<ConfigurationProperty>(); boolean foundConfiguration = false; // if a config argument is defined if (!StringHelper.isEmpty(config)) { // first attempt in the configuration model if (em != null) { ConfigurationModel model = findConfigurationModelByName(config, false); if (model != null) { foundConfiguration = true; for (ConfigurationProperty p : model.getProperties()) { properties.add(p); } } } // second attempt in the registered configurations, if a config argument is defined if (!foundConfiguration) { Configuration configuration = getRegisteredConfiguration(config); for (String key : getRegisteredConfiguration(config).keySet()) { properties.add(newConfigurationProperty(configuration, key)); } } } // if no config argument is given, we collect all persistent and registered properties else { // properties from configuration model (and registry) for (ConfigurationModel model : findModel(null)) { for (ConfigurationProperty p : model.getProperties()) { properties.add(p); } } } // filter properties using text on : name, labels, description and value final List<ConfigurationProperty> filterProperties = new ArrayList<ConfigurationProperty>(); if (!StringHelper.isEmpty(text)) { for (ConfigurationProperty property : properties) { String normalizePrefix = AbstractConfiguration.normalizeKey(text); if (!StringHelper.isEmpty(property.getName()) && property.getName().contains(normalizePrefix)) { filterProperties.add(property); } else if (property.getDescription() != null && property.getDescription().contains(text)) { filterProperties.add(property); } else if (String.valueOf(property.getValue()).contains(text)) { filterProperties.add(property); } else if (property.getLabels() != null && property.getLabels().contains(text)) { filterProperties.add(property); } } } else { filterProperties.addAll(properties); } return filterProperties; } /** * @param config * @param text text token to search * @return properties keys of the configuration * @throws ConfigurationNotFoundException */ @GET @Path("/{config}/keys") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response keys(@PathParam("config") final String config, @QueryParam("text") final String text) throws ConfigurationNotFoundException { Set<String> result = keySet(config); return Response.ok(result).build(); } /** * <p> * For the top class properties example in {@link PropertiesConfiguration} : * * <pre> * * configurationManager.keySet("appConfig") = {"//application/name", "//application/version", "//application/description", "//application/date", "//application/librairies", "application.modules.sales", ...} * </pre> * * </p> * * @param config configuration name identifier * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model * @return a set (clone) of all the declared property keys <br/> */ public Set<String> keySet(final String config) throws ConfigurationNotFoundException { Set<String> result = new HashSet<String>(); for (ConfigurationProperty prop : getProperties(config)) { result.add(prop.getName()); } return result; } /** * For the top class properties example in {@link PropertiesConfiguration} : * * <pre> * configurationManager.keySet("appConfig", "application.modules")= {"application.modules.sales=Sales","application.modules.sales.version=1.1.0","application.modules.marketing=Market.","application.modules.netbusiness="} * </pre> * * @param config configuration name identifier * @param text text key filtering * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model * @return a set (clone) of all declared property keys filtered by prefix argument */ public Set<String> keySet(final String config, final String prefix) throws ConfigurationNotFoundException { Set<String> result = new HashSet<String>(); for (ConfigurationProperty prop : findProperties(config, prefix)) { result.add(prop.getName()); } return result; } /** * @param config configuration name identifier * @param property property key to find * @return <code>true</code>if key exists, <code>false</code> otherwise * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model */ public boolean containsKey(final String config, final String property) { return keySet(config, null).contains(property); } // ### Configuration management methods ####################################################################################### /** * get configuration model by its name * * @param config configuration name identifier * @return the requested configuration * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model * @throws ConfigurationException */ @GET @Path("{config}/") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public ConfigurationModel getModel(final @PathParam("config") String config) throws ConfigurationNotFoundException, IllegalStateException { ConfigurationModel configurationModel = findConfigurationModelByName(config, false); if (em == null || configurationModel == null) { Configuration configuration = getRegisteredConfiguration(config); configurationModel = new ConfigurationModel(config, configuration.getResourceUri()); configurationModel.setLoaded(configuration.isLoaded()); configurationModel.setUpdateable(configuration.isUpdateable()); configurationModel.setStorable(configuration.isStorable()); for (String key : configuration.keySet()) { ConfigurationProperty property = newConfigurationProperty(configuration, key); property.getConfigurations().add(configurationModel); configurationModel.getProperties().add(property); } } return configurationModel; } /** * finding configurations by using a text search in the fields {@link ConfigurationModel#getName()}, * {@link ConfigurationModel#getDescription()}, {@link ConfigurationModel#getLabels()} * * @param text * @return list of configuration properties matching the text argument */ @GET @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @XmlElementWrapper(name = "configurations") @SuppressWarnings("unchecked") public List<ConfigurationModel> findModel(final @QueryParam("text") String text) { Set<ConfigurationModel> configurationModels = new HashSet<ConfigurationModel>(); // first check in the database model if (em != null) { final Query query; if (!StringHelper.isEmpty(text)) { // JPA 1.x for jee5 compatibility query = em.createQuery(Query_FindConfigurationByText.Jql); query.setParameter(Query_FindConfigurationByText.Parameter_Text, "%" + text + "%"); } else { query = em.createQuery(Query_FindAllConfiguration.Jql); } try { configurationModels.addAll(query.getResultList()); } catch (NoResultException nre) { } } // second check in memory registry for (Entry<String, Configuration> entry : ConfigurationFactory.getRegistry().entrySet()) { if (StringHelper.isEmpty(text) || entry.getValue().getName().contains(text) || entry.getValue().getResourceUri().contains(text)) { configurationModels.add(getModel(entry.getKey())); } } return new ArrayList<ConfigurationModel>(configurationModels); } /** * does configuration model exists * * @param config * @return <code>true|false</code> */ public boolean exists(final String config) { return findConfigurationModelByName(config, false) != null; } /** * remove configuration model by its name (but does not unregister it) * * @param config configuration name identifier * @throws ConfigurationNotFoundException * @throws ConfigurationException */ @DELETE @Path("{config}") public void removeModel(@PathParam("config") final String config) { ConfigurationModel configurationModel = findConfigurationModelByName(config, true); if (em != null) { // remove orphan properties for (ConfigurationProperty cp : configurationModel.getProperties()) { if (cp.getConfigurations().size() == 1) { em.remove(cp); } } // clean current configuration properties configurationModel.getProperties().clear(); // remove configuration and flush all changes em.remove(configurationModel); em.flush(); } } /** * register a configuration with the given name * * @param config configuration name identifier * @param resourceURI configuration resource uri */ @PUT @Path("{config}/register") public void register(final @PathParam("config") String config, final @QueryParam("resourceURI") String resourceURI) { ConfigurationFactory.provides(config, resourceURI); } /** * unregister the configuration with the given name * * @param config configuration name identifier */ @PUT @Path("{config}/unregister") public void unregister(final @PathParam("config") String config) throws ResourceException { ConfigurationFactory.unregister(config); } /** * does following configuration have been registered * * @param config * @return <code>true|false</code> */ public boolean isRegistered(final String config) { return ConfigurationFactory.isRegistered(config); } @GET @Path("{config}/registered") @Produces({ MediaType.TEXT_PLAIN }) public Response isRegisteredForRest(final @PathParam("config") String config) { return Response.ok(Boolean.valueOf(isRegistered(config)).toString()).build(); } /** * fire all the last configuration changes to the registered class instances * * @return number of configurations changes which have been fired * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model */ @GET @Path("{config}/fireChanges") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public FireChangesReport fireChanges(@PathParam("config") final String config) { return getRegisteredConfiguration(config).fireConfigurationChangesEvents(); } /** * store the changes made to the configuration * * @param config configuration name identifier * @see Configuration#store() * @throws ResourceException * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model */ @PUT @Path("{config}/store") public void store(@PathParam("config") final String config) throws ResourceException { // store configuration resource file Configuration configuration = getRegisteredConfiguration(config); configuration.store(); // store configuration model if (em != null) { ConfigurationModel model = findConfigurationModelByName(config, false); if (model != null) { for (String name : configuration.keySet()) { ConfigurationProperty property = model.getPropertiesByName().get(name); if (property != null) { property.setValue(configuration.getProperty(name)); em.merge(property); } } } em.flush(); } } /** * load the configuration * * @param config configuration name identifier * @throws ResourceException * @see Configuration#load() * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model */ @PUT @Path("{config}/load") public void load(@PathParam("config") final String config) throws ResourceException { getRegisteredConfiguration(config).load(); } /** * unload the configuration * * @param config configuration name identifier * @throws ResourceException * @see Configuration#unload() * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model */ @PUT @Path("{config}/unload") public void unload(@PathParam("config") final String config) throws ResourceException { getRegisteredConfiguration(config).unload(); } /** * reload the configuration * * @param config configuration name identifier * @throws ResourceException * @see Configuration#reload() * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model */ @PUT @Path("{config}/reload") public void reload(@PathParam("config") final String config) throws ResourceException { getRegisteredConfiguration(config).reload(); } /** * @param config configuration name identifier * @return <code>true|false</code> * @throws ConfigurationNotFoundException if configuration can't be found in registry or in database model */ public boolean isLoaded(final String config) throws ConfigurationNotFoundException { return getRegisteredConfiguration(config).isLoaded(); } @GET @Path("{config}/loaded") @Produces({ MediaType.TEXT_PLAIN }) public Response isLoadedForRest(final @PathParam("config") String config) { return Response.ok(Boolean.valueOf(isLoaded(config)).toString()).build(); } // ** private / protected part *********************************************************************************************** /** * @param configName * @return the given configuration search by name * @throws ConfigurationNotFoundException if configuration can't be found in current registry * @throws ConfigurationException if configuration is not loaded */ protected Configuration getRegisteredConfiguration(final String configName) throws ConfigurationNotFoundException { Configuration config = ConfigurationFactory.getRegistry().get(configName); if (config == null) { throw new ConfigurationNotFoundException(configName); } else { return config; } } /** * @param configName * @param propertyName * @param checkPropExists * @return configuration property * @throws ConfigurationNotFoundException * @throws PropertyNotFoundException if checkPropExists is true and if configuration property can't be found in current registry */ protected ConfigurationProperty getRegisteredProperty(final String configName, final String propertyName, final boolean checkPropExists) throws ConfigurationNotFoundException, PropertyNotFoundException { Configuration configuration = getRegisteredConfiguration(configName); if (checkPropExists) { if (!configuration.containsKey(propertyName)) { throw new PropertyNotFoundException(configName, propertyName); } } return newConfigurationProperty(configuration, propertyName); } /** * @param config * @param checkConfigExists * @return configuration meta data * @throws ConfigurationNotFoundException if checkConfigExists is true and if configuration can't be found in current registry */ protected ConfigurationModel findConfigurationModelByName(final String config, final boolean checkConfigExists) throws ConfigurationNotFoundException { ConfigurationModel configurationModel = null; // first check in the database model if (em != null) { // JPA 1.x for jee5 compatibility Query query = em.createQuery(Query_FindConfigurationByName.Jql); query.setParameter(Query_FindConfigurationByName.Parameter_ConfigurationName, config); try { configurationModel = (ConfigurationModel) query.getSingleResult(); } catch (NoResultException nre) { configurationModel = null; } } if (checkConfigExists) { if (configurationModel == null) { throw new ConfigurationNotFoundException(config); } } return configurationModel; } /** * @param config * @param propertyName * @param checkPropExists * @return property meta data * @throws ConfigurationNotFoundException * @throws PropertyNotFoundException */ protected ConfigurationProperty findConfigurationPropertyByName(final String config, final String propertyName, final boolean checkPropExists) throws ConfigurationNotFoundException, PropertyNotFoundException { // check that configuration is registered or have been persist try { getRegisteredConfiguration(config); } catch (ConfigurationNotFoundException cnfe) { findConfigurationModelByName(config, true); } ConfigurationProperty property = null; // first check in the database model if (em != null) { // JPA 1.x for jee5 compatibility Query query = em.createQuery(Query_FindPropertyByName.Jql); query.setParameter(Query_FindPropertyByName.Parameter_Name, AbstractConfiguration.normalizeKey(propertyName)); query.setParameter(Query_FindPropertyByName.Parameter_ConfigurationName, config); try { property = (ConfigurationProperty) query.getSingleResult(); } catch (NoResultException nre) { } } if (property == null && checkPropExists) { throw new PropertyNotFoundException(config, propertyName); } return property; } private ConfigurationProperty newConfigurationProperty(final Configuration configuration, final String propertyName) { Serializable value = configuration.getProperty(propertyName); Class<?> type = value != null ? value.getClass() : null; return new ConfigurationProperty(propertyName, configuration.getProperty(propertyName), type, DefaultDescription); } /** default property description for a non persistent database property */ public static final String DefaultDescription = "<no persistent property description>"; }