/** * Publication of feature statuses through JMX. * * @return map of features. */ @ManagedAttribute(description = "Returns states of every features of the store") public Map<String, Boolean> getFeaturesStatus() { Map<String, Boolean> mapsOfBool = new HashMap<String, Boolean>(); Map<String, Feature> mapsOfFeat = getFf4j().getFeatures(); if (mapsOfFeat != null && !mapsOfFeat.isEmpty()) { for (Entry<String, Feature> feat : mapsOfFeat.entrySet()) { mapsOfBool.put(feat.getKey(), feat.getValue().isEnable()); } } return mapsOfBool; }
private void autoWiredFeature(Object bean, Field field) { // Find the required and name parameters FF4JFeature annFeature = field.getAnnotation(FF4JFeature.class); String annValue = annFeature.value(); String featureName = field.getName(); if (annValue != null && !"".equals(annValue)) { featureName = annValue; } Feature feature = readFeature(field, featureName, annFeature.required()); if (feature != null) { if (Feature.class.isAssignableFrom(field.getType())) { injectValue(field, bean, featureName, feature); } else if (Boolean.class.isAssignableFrom(field.getType())) { injectValue(field, bean, featureName, Boolean.valueOf(feature.isEnable())); } else if (boolean.class.isAssignableFrom(field.getType())) { injectValue(field, bean, featureName, feature.isEnable()); } else { throw new IllegalArgumentException("Field annotated with @FF4JFeature" + " must inherit from org.ff4j.Feature or be boolean " + field.getType() + " [class=" + bean.getClass().getName() + ", field=" + field.getName() + "]"); } } }
private String createUpdateCoreFeature(Feature fp) { StringBuilder cypherUpdate = new StringBuilder("MATCH (f:" + FF4jNeo4jLabels.FF4J_FEATURE + " { uid:'"); cypherUpdate.append(fp.getUid()); cypherUpdate.append("' }) "); cypherUpdate.append("SET f.enable = " + fp.isEnable()); if (fp.getDescription() != null && fp.getDescription().length() > 0) { cypherUpdate.append(", f.description = '"); cypherUpdate.append(fp.getDescription()); cypherUpdate.append("'"); } if (fp.getPermissions() != null && fp.getPermissions().size() > 0) { cypherUpdate.append(", f.roles = ["); boolean first = true; for(String role : fp.getPermissions()) { if (!first) { cypherUpdate.append(","); } cypherUpdate.append("'" + role + "'"); first = false; } cypherUpdate.append("]"); } else { // AS role is null cypherUpdate.append(", f.roles = []"); } cypherUpdate.append(";"); return cypherUpdate.toString(); }
private String createQueryNewCoreFeature(Feature fp) { StringBuilder cypherCreate = new StringBuilder("CREATE ("); cypherCreate.append("f:" + FF4jNeo4jLabels.FF4J_FEATURE + " { uid :'"); cypherCreate.append(fp.getUid()); cypherCreate.append("', enable:"); cypherCreate.append(fp.isEnable()); if (fp.getDescription() != null && fp.getDescription().length() > 0) { cypherCreate.append(", description:'"); cypherCreate.append(fp.getDescription()); cypherCreate.append("'"); } if (fp.getPermissions() != null && fp.getPermissions().size() > 0) { cypherCreate.append(", roles: ["); boolean first = true; for(String role : fp.getPermissions()) { if (!first) { cypherCreate.append(","); } cypherCreate.append("'" + role + "'"); first = false; } cypherCreate.append("]"); } cypherCreate.append("});"); return cypherCreate.toString(); }
sb.append(MessageFormat.format(XML_FEATURE, feat.getUid(), feat.getDescription(), feat.isEnable()));
/** * Return status of all the features to calculate. * * @param currentStore * current store for features * @return current statuses for stores */ private Map<String, Boolean> getFeaturesStatus(FeatureStore currentStore, FlippingExecutionContext executionContext) { Map<String, Boolean> bools = new HashMap<String, Boolean>(); List<Feature> listOfFlip = new ArrayList<Feature>(); listOfFlip.addAll(currentStore.readAll().values()); for (Feature fp : listOfFlip) { if (fp.isEnable() && null != fp.getFlippingStrategy() && !(fp.getFlippingStrategy() instanceof ExpressionFlipStrategy)) { bools.put(fp.getUid(), fp.getFlippingStrategy().evaluate(fp.getUid(), currentStore, executionContext)); } else { bools.put(fp.getUid(), fp.isEnable()); } } return bools; }
Feature fp = new Feature(featureId, old.isEnable());
/** * Chack that feature is disabled in current store. * * @param featureName * target featureName * @return current object */ public final AssertFf4j assertThatFeatureIsDisabled(String featureName) { assertThatFeatureExist(featureName); Assert.assertFalse("'" + featureName + "' must be disabled", ff4j.getFeatureStore().read(featureName).isEnable()); waitSomeSeconds(); return this; }
/** * Chack that feature is enabled in current store. * * @param featureName * target featureName * @return current object */ public final AssertFf4j assertThatFeatureIsEnabled(String featureName) { assertThatFeatureExist(featureName); Assert.assertTrue(ff4j.getFeatureStore().read(featureName).isEnable()); waitSomeSeconds(); return this; }
private void createCoreFeature(Feature fp) { // Transaction wraps the method, could pipe several sql queries String strategyColumn = null; String expressionColumn = null; if (fp.getFlippingStrategy() != null) { strategyColumn = fp.getFlippingStrategy().getClass().getName(); expressionColumn = MappingUtil.fromMap(fp.getFlippingStrategy().getInitParams()); } getJdbcTemplate().update(getQueryBuilder().createFeature(), fp.getUid(), fp.isEnable() ? 1 : 0, fp.getDescription(), strategyColumn, expressionColumn, fp.getGroup()); }
put.addColumn(B_FEATURES_CF_CORE, B_FEAT_DESCRIPTION, desc); put.addColumn(B_FEATURES_CF_CORE, B_FEAT_ENABLE, Bytes.toBytes(fp.isEnable()));
/** {@inheritDoc} */ @Override public void create(Feature fp) { assertFeatureNotNull(fp); assertFeatureNotExist(fp.getUid()); // Convert map<String, Property> to map<String, String>, structure in DB Map < String, String > mapOfProperties = new HashMap<String, String>(); if (fp.getCustomProperties() != null && !fp.getCustomProperties().isEmpty()) { for (Map.Entry<String, Property<?>> customP : fp.getCustomProperties().entrySet()) { if (customP.getValue() != null) { mapOfProperties.put(customP.getKey(), customP.getValue().toJson()); } } } conn.getSession().execute(getBuilder().cqlCreateFeature(), fp.getUid(), fp.isEnable() ? 1 : 0, fp.getDescription(), JsonUtils.flippingStrategyAsJson(fp.getFlippingStrategy()), fp.getGroup(), fp.getPermissions(), mapOfProperties); }
public FeatureApiBean(Feature f) { this.uid = f.getUid(); this.enable = f.isEnable(); this.description = f.getDescription(); this.group = f.getGroup(); this.permissions = new ArrayList<String>(f.getPermissions()); if (f.getFlippingStrategy() != null) { this.flippingStrategy = new FlippingStrategyApiBean(f.getFlippingStrategy()); } if (f.getCustomProperties() != null) { for (Property<?> ap1 : f.getCustomProperties().values()) { customProperties.put(ap1.getName(), new PropertyApiBean(ap1)); } } }
/** * Overriding strategy on feature. * * @param featureID * feature unique identifier. * @param executionContext * current execution context * @return */ public boolean checkOveridingStrategy(String featureID, FlippingStrategy strats, FlippingExecutionContext executionContext) { Feature fp = getFeature(featureID); boolean flipped = fp.isEnable() && isAllowed(fp); if (strats != null) { flipped = flipped && strats.evaluate(featureID, getFeatureStore(), executionContext); } publishCheck(featureID, flipped); return flipped; }
/** * Copy constructor. * * @param f * * target feature */ public FeatureApiBean(Feature f) { this.uid = f.getUid(); this.enable = f.isEnable(); this.description = f.getDescription(); this.group = f.getGroup(); this.permissions = new ArrayList<String>(f.getPermissions()); if (f.getFlippingStrategy() != null) { this.flippingStrategy = new FlippingStrategyApiBean(f.getFlippingStrategy()); } if (f.getCustomProperties() != null) { for (Property<?> ap1 : f.getCustomProperties().values()) { customProperties.put(ap1.getName(), new PropertyApiBean(ap1)); } } }
/** * Elegant way to ask for flipping. * * @param featureID * feature unique identifier. * @param executionContext * current execution context * @return current feature status */ public boolean check(String featureID, FlippingExecutionContext executionContext) { Feature fp = getFeature(featureID); boolean flipped = fp.isEnable(); // If authorization manager provided, apply security filter if (flipped && getAuthorizationsManager() != null) { flipped = isAllowed(fp); } // If custom strategy has been defined, delegate flipping to if (flipped && fp.getFlippingStrategy() != null) { flipped = fp.getFlippingStrategy().evaluate(featureID, getFeatureStore(), executionContext); } // Update current context currentExecutionContext.set(executionContext); // Any access is logged into audit system publishCheck(featureID, flipped); return flipped; }
/** * Copy constructor. * * @param f * current feature */ public Feature(final Feature f) { this(f.getUid(), f.isEnable(), f.getDescription(), f.getGroup()); this.permissions.addAll(f.getPermissions()); // Flipping Strategy if (f.getFlippingStrategy() != null) { this.flippingStrategy = MappingUtil.instanceFlippingStrategy(f.getUid(), f.getFlippingStrategy().getClass().getName(), f.getFlippingStrategy().getInitParams()); } // Custom Properties if (f.getCustomProperties() != null && !f.getCustomProperties().isEmpty()) { for(Property<?> p : f.getCustomProperties().values()) { Property<?> targetProp = PropertyFactory.createProperty( p.getName(), p.getType(), p.asString(), p.getDescription(), null); if (p.getFixedValues() != null) { for(Object o : p.getFixedValues()) { targetProp.add2FixedValueFromString(o.toString()); } } this.getCustomProperties().put(targetProp.getName(), targetProp); } } }
/** * Allow to update feature. * * @param featureId */ private void updateFeature(HttpServletRequest req, String featureId) { Feature old = ff4j.getFeatureStore().read(featureId); // Core Feature fp = new Feature(featureId, old.isEnable()); fp.setPermissions(old.getPermissions()); fp.setCustomProperties(old.getCustomProperties()); fp.setFlippingStrategy(buildFlippingStrategy(req, fp.getUid())); // Description final String featureDesc = req.getParameter(DESCRIPTION); if (Util.hasLength(featureDesc)) { fp.setDescription(featureDesc); } // GroupName final String groupName = req.getParameter(GROUPNAME); if (Util.hasLength(groupName)) { fp.setGroup(groupName); } // Creation ff4j.getFeatureStore().update(fp); }
@Override public Document toStore(Feature feature) { String strategyColumn = null; String expressionColumn = null; if (feature.getFlippingStrategy() != null) { strategyColumn = feature.getFlippingStrategy().getClass().getName(); expressionColumn = MappingUtil.fromMap(feature.getFlippingStrategy().getInitParams()); } String customProperties = null; if (feature.getCustomProperties() != null) { customProperties = JsonUtils.customPropertiesAsJson(feature.getCustomProperties()); } return new FeatureDocumentBuilder().addFeatUid(feature.getUid()).// addEnable(feature.isEnable()).// addDescription(feature.getDescription()).// addGroupName(feature.getGroup()).// addStrategy(strategyColumn).// addExpression(expressionColumn).// addCustomProperties(customProperties). // addRoles(feature.getPermissions()).build(); }
/** * Convert {@link Feature} to {@link DBObject}. * * @param feature * target feature. * @return document in mongo db */ public DBObject toDBObject(Feature feature) { String strategyColumn = null; String expressionColumn = null; if (feature.getFlippingStrategy() != null) { strategyColumn = feature.getFlippingStrategy().getClass().getName(); expressionColumn = MappingUtil.fromMap(feature.getFlippingStrategy().getInitParams()); } String customProperties = null; if (feature.getCustomProperties() != null) { customProperties = JsonUtils.customPropertiesAsJson(feature.getCustomProperties()); } return new FeatureDBObjectBuilder().addFeatUid(feature.getUid()).// addEnable(feature.isEnable()).// addDescription(feature.getDescription()).// addGroupName(feature.getGroup()).// addStrategy(strategyColumn).// addExpression(expressionColumn).// addCustomProperties(customProperties). addRoles(feature.getPermissions()).build(); }