All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ctoolkit.services.common.PropertyServiceBean Maven / Gradle / Ivy

There is a newer version: 0.36
Show newest version
/*
 * Copyright (c) 2017 Comvai, s.r.o. All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

package org.ctoolkit.services.common;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Text;
import com.google.appengine.api.memcache.jsr107cache.GCacheFactory;
import com.google.appengine.api.utils.SystemProperty;
import com.google.common.base.Strings;
import net.sf.jsr107cache.Cache;
import net.sf.jsr107cache.CacheException;
import net.sf.jsr107cache.CacheFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.util.HashMap;
import java.util.Map;

/**
 * Property service implementation of {@link PropertyService} for App Engine.
 * 

* If no configuration instance {@link PropertyConfig} is being provided in module, default behavior is: *

    *
  • Development: {@link #isDevelopmentEnvironment()} returns true
  • *
  • App Engine: {@link #isTestEnvironment()} returns true
  • *
* * @author Jozef Pohorelec * @author Aurel Medvegy */ class PropertyServiceBean implements PropertyService { private static final Logger logger = LoggerFactory.getLogger( PropertyServiceBean.class ); private static final String ENTITY_PROPERTY = "Property"; private static final String ENTITY_PROPERTY_VALUE = "value"; private static final String PROPERTY_CACHE_NAMESPACE = "ctoolkit_common_properties_cache_namespace"; private final CacheFactory factory; private DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService(); private Cache cache; private boolean isTestEnvironment = false; private boolean isProductionEnvironment = false; private boolean isDevelopmentEnvironment = false; @Inject PropertyServiceBean( CacheFactory factory, @Configuration Map configuration ) { this.factory = factory; cache = create( PROPERTY_CACHE_NAMESPACE ); String productionAppId = configuration.get( "service.property.appId.production" ); String testAppId = configuration.get( "service.property.appId.test" ); if ( SystemProperty.environment.value() == SystemProperty.Environment.Value.Production ) { // means running on the app engine environment under an applicationId isTestEnvironment = SystemProperty.applicationId.get().equals( testAppId ); if ( Strings.isNullOrEmpty( testAppId ) ) { // If testAppId is not being set and running on App Engine, we assume it is TEST environment. // Unless overridden by production AppId configuration isTestEnvironment = true; } isProductionEnvironment = !isTestEnvironment; isDevelopmentEnvironment = false; } if ( SystemProperty.environment.value() == SystemProperty.Environment.Value.Production ) { // means running on the app engine environment under an applicationId isProductionEnvironment = SystemProperty.applicationId.get().equals( productionAppId ); isTestEnvironment = !isProductionEnvironment; isDevelopmentEnvironment = false; } if ( SystemProperty.environment.value() == SystemProperty.Environment.Value.Development ) { // means running on the local app engine environment isDevelopmentEnvironment = true; isTestEnvironment = false; isProductionEnvironment = false; } logger.info( "Configured production environment: " + productionAppId ); logger.info( "Configured test environment: " + testAppId ); logger.info( "App Engine environment: " + SystemProperty.environment.value() ); logger.info( "App Engine application ID: " + SystemProperty.applicationId.get() ); } @Override public Cache create( @Nullable String namespace ) { Map properties = new HashMap<>(); if ( !Strings.isNullOrEmpty( namespace ) ) { properties.put( GCacheFactory.NAMESPACE, namespace ); } return create( properties ); } @Override public Cache create( @Nonnull Map config ) { try { return factory.createCache( config ); } catch ( CacheException e ) { logger.error( "Error occurred during creating cache instance, providing " + NonFunctionalCache.class.getSimpleName() + " instance instead.", e ); } return new NonFunctionalCache(); } @Override public String getString( String key ) { return getProperty( key, StringConverter.instance() ); } @Override public void setString( String key, String value ) { put( key, value ); } @Override public Double getDouble( String key ) { return getProperty( key, DoubleConverter.instance() ); } @Override public void setDouble( String key, Double value ) { put( key, value ); } @Override public Integer getInteger( String key ) { return getProperty( key, IntegerConverter.instance() ); } @Override public void setInteger( String key, Integer value ) { put( key, value ); } @Override public boolean isProductionEnvironment() { return isProductionEnvironment; } @Override public boolean isTestEnvironment() { return isTestEnvironment; } /** * This returns true as well if property is being overridden by * System.setProperty( "com.google.appengine.runtime.environment", "Development" ) * * @return true if current application is running in test environment or has that property set to 'Development' */ @Override public boolean isDevelopmentEnvironment() { return isDevelopmentEnvironment; } public String getAppSpotURL() { return getAppSpotURL( null ); } public String getAppSpotURL( String prefix ) { StringBuilder builder = new StringBuilder(); builder.append( "https://" ); if ( !Strings.isNullOrEmpty( prefix ) ) { builder.append( prefix ); builder.append( "-dot-" ); } builder.append( SystemProperty.applicationId.get() ); builder.append( ".appspot.com" ); logger.info( "AppSpot URL: " + builder ); return builder.toString(); } /** * Return typed property value from cache. If property is not cached, method will load value from data-store * and than puts it in to cache. * * @param key property key * @param converter property type converter * @param property value type * @return typed property value */ @SuppressWarnings( value = "unchecked" ) private T getProperty( String key, Converter converter ) { Object object = cache.get( key ); T property = null; // if property is cached return it if ( object != null ) { property = ( T ) object; } // else try to get it from data-store and cache it else { Entity entity = get( key ); if ( entity != null ) { property = converter.convert( entity.getProperty( ENTITY_PROPERTY_VALUE ) ); if ( property != null ) { cache.put( key, property ); } } } return property; } /** * Get property from data-store. If property for specified key does not exists, returns null. * * @param key property key * @return entity containing property object */ private Entity get( String key ) { try { return datastoreService.get( KeyFactory.createKey( ENTITY_PROPERTY, key ) ); } catch ( EntityNotFoundException e ) { logger.warn( "Property entity not found for key: " + key ); return null; } } /** * Put key-value pair to data-store, and cache it. * * @param key property key * @param value property value */ private void put( String key, Object value ) { Entity property = get( key ); if ( property == null ) { property = new Entity( ENTITY_PROPERTY, key ); } Object valueToStore; if ( value instanceof String && ( ( String ) value ).getBytes().length > 1500 ) { // Converted to App Engine native text as limit to store short string is up to 1500 bytes, then throws exception valueToStore = new Text( value.toString() ); } else { valueToStore = value; } property.setProperty( ENTITY_PROPERTY_VALUE, valueToStore ); // put property entity to data-store datastoreService.put( property ); // cache property cache.put( key, value ); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy