http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java deleted file mode 100644 index 5639945..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.creation; - -import java.util.Set; - -import org.apache.brooklyn.api.entity.Application; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; -import org.apache.brooklyn.api.policy.Policy; -import org.apache.brooklyn.api.typereg.RegisteredType; -import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext; -import org.apache.brooklyn.camp.CampPlatform; -import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator; -import org.apache.brooklyn.camp.spi.AssemblyTemplate; -import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator; -import org.apache.brooklyn.core.catalog.internal.CatalogUtils; -import org.apache.brooklyn.core.mgmt.EntityManagementUtils; -import org.apache.brooklyn.core.typereg.RegisteredTypes; -import org.apache.brooklyn.util.collections.MutableSet; -import org.apache.brooklyn.util.text.Strings; - -import com.google.common.collect.ImmutableSet; - -class CampResolver { - - private ManagementContext mgmt; - private RegisteredType type; - private RegisteredTypeLoadingContext context; - - // TODO we have a few different modes, detailed below; this logic should be moved to the new transformer - // and allow specifying which modes are permitted to be in effect? -// /** whether to allow parsing of the 'full' syntax for applications, -// * where items are wrapped in a "services:" block, and if the wrapper is an application, -// * to promote it */ -// boolean allowApplicationFullSyntax = true; -// -// /** whether to allow parsing of the legacy 'full' syntax, -// * where a non-application items are wrapped: -// * <li> in a "services:" block for entities, -// * <li> in a "brooklyn.locations" or "brooklyn.policies" block for locations and policies */ -// boolean allowLegacyFullSyntax = true; -// -// /** whether to allow parsing of the type syntax, where an item is a map with a "type:" field, -// * i.e. not wrapped in any "services:" or "brooklyn.{locations,policies}" block */ -// boolean allowTypeSyntax = true; - - public CampResolver(ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext context) { - this.mgmt = mgmt; - this.type = type; - this.context = context; - } - - public AbstractBrooklynObjectSpec<?, ?> createSpec() { - // TODO new-style approach: - // AbstractBrooklynObjectSpec<?, ?> spec = RegisteredTypes.newSpecInstance(mgmt, /* 'type' key */); - // spec.configure(keysAndValues); - return createSpecFromFull(mgmt, type, context.getExpectedJavaSuperType(), context.getAlreadyEncounteredTypes(), context.getLoader()); - } - - static AbstractBrooklynObjectSpec<?, ?> createSpecFromFull(ManagementContext mgmt, RegisteredType item, Class<?> expectedType, Set<String> parentEncounteredTypes, BrooklynClassLoadingContext loaderO) { - // for this method, a prefix "services" or "brooklyn.{location,policies}" is required at the root; - // we now prefer items to come in "{ type: .. }" format, except for application roots which - // should have a "services: [ ... ]" block (and which may subsequently be unwrapped) - BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item, loaderO); - - Set<String> encounteredTypes; - // symbolicName could be null if coming from the catalog parser where it tries to load before knowing the id - if (item.getSymbolicName() != null) { - encounteredTypes = ImmutableSet.<String>builder() - .addAll(parentEncounteredTypes) - .add(item.getSymbolicName()) - .build(); - } else { - encounteredTypes = parentEncounteredTypes; - } - - AbstractBrooklynObjectSpec<?, ?> spec; - String planYaml = RegisteredTypes.getImplementationDataStringForSpec(item); - MutableSet<Object> supers = MutableSet.copyOf(item.getSuperTypes()); - supers.addIfNotNull(expectedType); - if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Policy.class)) { - spec = CampInternalUtils.createPolicySpec(planYaml, loader, encounteredTypes); - } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Location.class)) { - spec = CampInternalUtils.createLocationSpec(planYaml, loader, encounteredTypes); - } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Application.class)) { - spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, true); - } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Entity.class)) { - spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, false); - } else { - throw new IllegalStateException("Cannot detect spec type from "+item.getSuperTypes()+" for "+item+"\n"+planYaml); - } - if (expectedType!=null && !expectedType.isAssignableFrom(spec.getType())) { - throw new IllegalStateException("Creating spec from "+item+", got "+spec.getType()+" which is incompatible with expected "+expectedType); - } - - ((AbstractBrooklynObjectSpec<?, ?>)spec).catalogItemIdIfNotNull(item.getId()); - - if (Strings.isBlank( ((AbstractBrooklynObjectSpec<?, ?>)spec).getDisplayName() )) - ((AbstractBrooklynObjectSpec<?, ?>)spec).displayName(item.getDisplayName()); - - return spec; - } - - private static EntitySpec<?> createEntitySpecFromServicesBlock(String plan, BrooklynClassLoadingContext loader, Set<String> encounteredTypes, boolean isApplication) { - CampPlatform camp = CampInternalUtils.getCampPlatform(loader.getManagementContext()); - - AssemblyTemplate at = CampInternalUtils.registerDeploymentPlan(plan, loader, camp); - AssemblyTemplateInstantiator instantiator = CampInternalUtils.getInstantiator(at); - if (instantiator instanceof AssemblyTemplateSpecInstantiator) { - EntitySpec<? extends Application> appSpec = ((AssemblyTemplateSpecInstantiator)instantiator).createApplicationSpec(at, camp, loader, encounteredTypes); - - // above will unwrap but only if it's an Application (and it's permitted); - // but it doesn't know whether we need an App or if an Entity is okay - if (!isApplication) return EntityManagementUtils.unwrapEntity(appSpec); - // if we need an App then definitely *don't* unwrap here because - // the instantiator will have done that, and it knows if the plan - // specified a wrapped app explicitly (whereas we don't easily know that here!) - return appSpec; - - } else { - throw new IllegalStateException("Unable to instantiate YAML; invalid type or parameters in plan:\n"+plan); - } - - } - -} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java deleted file mode 100644 index 01b721a..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.creation; - -import java.util.Set; - -import org.apache.brooklyn.api.catalog.CatalogItem; -import org.apache.brooklyn.api.entity.Application; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; -import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; -import org.apache.brooklyn.camp.CampPlatform; -import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys; -import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator; -import org.apache.brooklyn.camp.spi.AssemblyTemplate; -import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator; -import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext; -import org.apache.brooklyn.core.plan.PlanNotRecognizedException; -import org.apache.brooklyn.core.plan.PlanToSpecTransformer; -import org.apache.brooklyn.core.typereg.RegisteredTypes; -import org.apache.brooklyn.util.collections.MutableSet; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Deprecated /** @deprecated since 0.9.0 use CampTypePlanTransformer */ -public class CampToSpecTransformer implements PlanToSpecTransformer { - - public static final String YAML_CAMP_PLAN_TYPE = "org.apache.brooklyn.camp/yaml"; - - private static final Logger log = LoggerFactory.getLogger(CampToSpecTransformer.class); - - private ManagementContext mgmt; - - @Override - public String getShortDescription() { - return "Brooklyn OASIS CAMP interpreter"; - } - - @Override - public boolean accepts(String mime) { - return YAML_CAMP_PLAN_TYPE.equals(mime); - } - - @Override - public EntitySpec<? extends Application> createApplicationSpec(String plan) { - try { - CampPlatform camp = CampInternalUtils.getCampPlatform(mgmt); - BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt); - AssemblyTemplate at = CampInternalUtils.registerDeploymentPlan(plan, loader, camp); - AssemblyTemplateInstantiator instantiator = CampInternalUtils.getInstantiator(at); - if (instantiator instanceof AssemblyTemplateSpecInstantiator) { - return ((AssemblyTemplateSpecInstantiator) instantiator).createApplicationSpec(at, camp, loader, MutableSet.<String>of()); - } else { - // The unknown instantiator can create the app (Assembly), but not a spec. - // Currently, all brooklyn plans should produce the above. - if (at.getPlatformComponentTemplates()==null || at.getPlatformComponentTemplates().isEmpty()) { - if (at.getCustomAttributes().containsKey(BrooklynCampReservedKeys.BROOKLYN_CATALOG)) - throw new IllegalArgumentException("Unrecognized application blueprint format: expected an application, not a brooklyn.catalog"); - throw new PlanNotRecognizedException("Unrecognized application blueprint format: no services defined"); - } - // map this (expected) error to a nicer message - throw new PlanNotRecognizedException("Unrecognized application blueprint format"); - } - } catch (Exception e) { - // TODO how do we figure out that the plan is not supported vs. invalid to wrap in a PlanNotRecognizedException? - if (log.isDebugEnabled()) - log.debug("Failed to create entity from CAMP spec:\n" + plan, e); - throw Exceptions.propagate(e); - } - } - - @SuppressWarnings({ "unchecked" }) - @Override - public <T, SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(CatalogItem<T, SpecT> item, Set<String> encounteredTypes) { - // Ignore old-style java type catalog items - there is a different (deprecated) transformer for that - if (item.getPlanYaml() == null) { - throw new PlanNotRecognizedException("Old style catalog item " + item + " not supported."); - } - if (encounteredTypes.contains(item.getSymbolicName())) { - throw new IllegalStateException("Already encountered types " + encounteredTypes + " must not contain catalog item being resolver " + item.getSymbolicName()); - } - - // Not really clear what should happen to the top-level attributes, ignored until a good use case appears. - return (SpecT) CampResolver.createSpecFromFull(mgmt, RegisteredTypes.of(item), item.getCatalogItemJavaType(), encounteredTypes, null); - } - - @Override - public void setManagementContext(ManagementContext mgmt) { - this.mgmt = mgmt; - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java deleted file mode 100644 index afeba41..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.creation; - -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; -import org.apache.brooklyn.api.typereg.RegisteredType; -import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan; -import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext; -import org.apache.brooklyn.core.typereg.AbstractFormatSpecificTypeImplementationPlan; -import org.apache.brooklyn.core.typereg.AbstractTypePlanTransformer; -import org.apache.brooklyn.core.typereg.BasicTypeImplementationPlan; -import org.apache.brooklyn.core.typereg.RegisteredTypes; -import org.apache.brooklyn.util.guava.Maybe; - -import com.google.common.collect.ImmutableList; - -public class CampTypePlanTransformer extends AbstractTypePlanTransformer { - - private static final List<String> FORMATS = ImmutableList.of("brooklyn-camp"); - // TODO any use in having these formats? if not, remove. Nov 2015. - // , "camp", "brooklyn"); - - public static final String FORMAT = FORMATS.get(0); - - public CampTypePlanTransformer() { - super(FORMAT, "OASIS CAMP / Brooklyn", "The Apache Brooklyn implementation of the OASIS CAMP blueprint plan format and extensions"); - } - - @Override - protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeLoadingContext context) { - Maybe<Map<?,?>> plan = RegisteredTypes.getAsYamlMap(planData); - if (plan.isAbsent()) return 0; - if (plan.get().containsKey("services")) return 0.8; - if (plan.get().containsKey("type")) return 0.4; - // TODO these should become legacy - if (plan.get().containsKey("brooklyn.locations")) return 0.7; - if (plan.get().containsKey("brooklyn.policies")) return 0.7; - return 0; - } - - @Override - protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeLoadingContext context) { - if (FORMATS.contains(planFormat.toLowerCase())) return 0.9; - return 0; - } - - @Override - protected AbstractBrooklynObjectSpec<?, ?> createSpec(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception { - // TODO cache - return new CampResolver(mgmt, type, context).createSpec(); - } - - @Override - protected Object createBean(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception { - // beans not supported by this? - return null; - } - - @Override - public double scoreForTypeDefinition(String formatCode, Object catalogData) { - // TODO catalog parsing - return 0; - } - - @Override - public List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData) { - // TODO catalog parsing - return null; - } - - public static class CampTypeImplementationPlan extends AbstractFormatSpecificTypeImplementationPlan<String> { - public CampTypeImplementationPlan(TypeImplementationPlan otherPlan) { - super(FORMATS.get(0), String.class, otherPlan); - } - public CampTypeImplementationPlan(String planData) { - this(new BasicTypeImplementationPlan(FORMATS.get(0), planData)); - } - } -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/EntitySpecConfiguration.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/EntitySpecConfiguration.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/EntitySpecConfiguration.java deleted file mode 100644 index 5714523..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/EntitySpecConfiguration.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.creation; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Map; - -import org.apache.brooklyn.api.entity.EntitySpec; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Maps; - -/** - * Captures the {@link EntitySpec} configuration defined in YAML. - * - * This class does not parse that output; it just stores it. - */ -public class EntitySpecConfiguration { - - @SuppressWarnings("unused") - private static final Logger LOG = LoggerFactory.getLogger(EntitySpecConfiguration.class); - - private Map<String, Object> specConfiguration; - - public EntitySpecConfiguration(Map<String, ?> specConfiguration) { - this.specConfiguration = Maps.newHashMap(checkNotNull(specConfiguration, "specConfiguration")); - } - - public Map<String, Object> getSpecConfiguration() { - return specConfiguration; - } - - /** - * Allows BrooklynComponentTemplateResolver to traverse the configuration and resolve any entity specs - */ - public void setSpecConfiguration(Map<String, Object> specConfiguration) { - this.specConfiguration = specConfiguration; - } -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java deleted file mode 100644 index 83f907b..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.creation.service; - -import javax.annotation.Nullable; - -import org.apache.brooklyn.api.catalog.CatalogItem; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver; -import org.apache.brooklyn.camp.spi.PlatformComponentTemplate; -import org.apache.brooklyn.core.catalog.internal.CatalogUtils; -import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider; -import org.apache.brooklyn.core.resolve.entity.AbstractEntitySpecResolver; -import org.apache.brooklyn.util.text.Strings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code brooklyn:} - * to Brooklyn {@link EntitySpec} instances. - * - * @deprecated since 0.9.0, use {@link AbstractEntitySpecResolver} instead - */ -@Deprecated -public class BrooklynServiceTypeResolver implements ServiceTypeResolver { - - @SuppressWarnings("unused") - private static final Logger LOG = LoggerFactory.getLogger(ServiceTypeResolver.class); - - public BrooklynServiceTypeResolver() { - } - - @Override - public String getTypePrefix() { return DEFAULT_TYPE_PREFIX; } - - @Override - public String getBrooklynType(String serviceType) { - return Strings.removeFromStart(serviceType, getTypePrefix() + ":").trim(); - } - - @Nullable - @Override - public CatalogItem<Entity,EntitySpec<?>> getCatalogItem(BrooklynComponentTemplateResolver resolver, String serviceType) { - String type = getBrooklynType(serviceType); - if (type != null) { - return getCatalogItemImpl(resolver.getManagementContext(), type); - } else { - return null; - } - } - - @Override - public <T extends Entity> void decorateSpec(BrooklynComponentTemplateResolver resolver, EntitySpec<T> spec) { - } - - protected CatalogItem<Entity,EntitySpec<?>> getCatalogItemImpl(ManagementContext mgmt, String brooklynType) { - brooklynType = DeserializingClassRenamesProvider.findMappedName(brooklynType); - return CatalogUtils.getCatalogItemOptionalVersion(mgmt, Entity.class, brooklynType); - } -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CampServiceSpecResolver.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CampServiceSpecResolver.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CampServiceSpecResolver.java deleted file mode 100644 index 091a4f4..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CampServiceSpecResolver.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.creation.service; - -import java.util.List; - -import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.core.resolve.entity.DelegatingEntitySpecResolver; -import org.apache.brooklyn.core.resolve.entity.EntitySpecResolver; - -import com.google.common.collect.ImmutableList; - -public class CampServiceSpecResolver extends DelegatingEntitySpecResolver { - - public CampServiceSpecResolver(ManagementContext mgmt, List<EntitySpecResolver> overridingResolvers) { - super(getCampResolvers(mgmt, overridingResolvers)); - } - - private static List<EntitySpecResolver> getCampResolvers(ManagementContext mgmt, List<EntitySpecResolver> overridingResolvers) { - List<EntitySpecResolver> resolvers = ImmutableList.<EntitySpecResolver>builder() - .addAll(overridingResolvers) - .addAll(getRegisteredResolvers()) - .add(new UrlServiceSpecResolver()) - .build(); - for (EntitySpecResolver resolver : resolvers) { - resolver.setManagementContext(mgmt); - } - return resolvers; - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java deleted file mode 100644 index 14f855a..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.creation.service; - -import java.util.ServiceLoader; - -import org.apache.brooklyn.api.catalog.CatalogItem; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver; -import org.apache.brooklyn.core.resolve.entity.EntitySpecResolver; - -/** - * Resolves and decorates {@link EntitySpec entity specifications} based on the {@code serviceType} in a template. - * <p> - * The {@link #getTypePrefix()} method returns a string that should match the beginning of the - * service type. The resolver implementation will use the rest of the service type information - * to create and decorate an approprate {@link EntitySpec entity}. - * <p> - * The resolvers are loaded using the {@link ServiceLoader} mechanism, allowing external libraries - * to add extra service type implementations that will be picked up at runtime. - * - * @see BrooklynServiceTypeResolver - * @see ChefServiceTypeResolver - * - * @deprecated since 0.9.0, {@link EntitySpecResolver} instead. - */ -@Deprecated -public interface ServiceTypeResolver { - - String DEFAULT_TYPE_PREFIX = "brooklyn"; - - /** - * The service type prefix the resolver is responsible for. - */ - String getTypePrefix(); - - /** - * The name of the Java type that Brooklyn will instantiate to create the - * service. This can be generated from parts of the service type information - * or may be a fixed value. - */ - String getBrooklynType(String serviceType); - - /** - * Returns the {@link CatalogItem} if there is one for the given type. - * <p> - * If no type, callers should fall back to default classloading. - */ - CatalogItem<Entity, EntitySpec<?>> getCatalogItem(BrooklynComponentTemplateResolver resolver, String serviceType); - - /** - * Takes the provided {@link EntitySpec} and decorates it appropriately for the service type. - * <p> - * This includes setting configuration and adding policies, enrichers and initializers. - * - * @see BrooklynServiceTypeResolver#decorateSpec(BrooklynComponentTemplateResolver, EntitySpec) - */ - <T extends Entity> void decorateSpec(BrooklynComponentTemplateResolver resolver, EntitySpec<T> spec); - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java deleted file mode 100644 index d4cf6e9..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.creation.service; - -import java.util.Set; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; -import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver; -import org.apache.brooklyn.core.resolve.entity.AbstractEntitySpecResolver; -import org.apache.brooklyn.core.resolve.entity.EntitySpecResolver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Splitter; - -@SuppressWarnings("deprecation") -public class ServiceTypeResolverAdaptor extends AbstractEntitySpecResolver { - private static final Logger log = LoggerFactory.getLogger(ServiceTypeResolverAdaptor.class); - private ServiceTypeResolver serviceTypeResolver; - private BrooklynComponentTemplateResolver resolver; - - public ServiceTypeResolverAdaptor(BrooklynComponentTemplateResolver resolver, ServiceTypeResolver serviceTypeResolver) { - super(serviceTypeResolver.getTypePrefix()); - this.serviceTypeResolver = serviceTypeResolver; - this.resolver = resolver; - } - - @Override - public boolean accepts(String type, BrooklynClassLoadingContext loader) { - if (type.indexOf(':') != -1) { - String prefix = Splitter.on(":").splitToList(type).get(0); - return prefix.equals(serviceTypeResolver.getTypePrefix()); - } else { - return false; - } - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - public EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) { - // Assume this is interface! Only known implementation is DockerServiceTypeResolver. - String brooklynType = serviceTypeResolver.getBrooklynType(type); - Class<? extends Entity> javaType = loader.loadClass(brooklynType, Entity.class); - if (!javaType.isInterface()) { - log.warn("Using " + ServiceTypeResolver.class.getSimpleName() + " with a non-interface type - this usage is not supported. Use " + EntitySpecResolver.class.getSimpleName() + " instead."); - } - EntitySpec<?> spec = EntitySpec.create((Class)javaType); - serviceTypeResolver.decorateSpec(resolver, spec); - return spec; - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java deleted file mode 100644 index 62f079f..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.creation.service; - -import java.util.Set; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; -import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants; -import org.apache.brooklyn.camp.brooklyn.spi.creation.CampTypePlanTransformer; -import org.apache.brooklyn.core.resolve.entity.EntitySpecResolver; -import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts; -import org.apache.brooklyn.core.typereg.RegisteredTypes; -import org.apache.brooklyn.util.collections.MutableSet; -import org.apache.brooklyn.util.core.ResourceUtils; -import org.apache.brooklyn.util.net.Urls; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** Specific to CAMP because linked plans are assumed to be CAMP format. No type discovery available. */ -public class UrlServiceSpecResolver implements EntitySpecResolver { - private static final Logger log = LoggerFactory.getLogger(UrlServiceSpecResolver.class); - - @Override - public String getName() { - return "url"; - } - - @Override - public boolean accepts(String type, BrooklynClassLoadingContext loader) { - String protocol = Urls.getProtocol(type); - return protocol != null && - BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST.contains(protocol); - } - - @Override - public EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) { - String yaml; - try { - yaml = ResourceUtils.create(this).getResourceAsString(type); - } catch (Exception e) { - log.warn("AssemblyTemplate type " + type + " looks like a URL that can't be fetched.", e); - return null; - } - if (encounteredTypes.contains(type)) { - throw new IllegalStateException("URL " + type + " is self referential."); - } - - // Referenced specs are expected to be CAMP format as well. - // TODO somehow specify to allow full syntax for services - EntitySpec<?> item = loader.getManagementContext().getTypeRegistry().createSpecFromPlan( - CampTypePlanTransformer.FORMAT, - yaml, - RegisteredTypeLoadingContexts.loaderAlreadyEncountered(loader, encounteredTypes, type), - EntitySpec.class); - return item; - } - - @Override - public void setManagementContext(ManagementContext managementContext) { - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslDeferredSupplier.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslDeferredSupplier.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslDeferredSupplier.java deleted file mode 100644 index 48a0283..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslDeferredSupplier.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.dsl; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.util.concurrent.locks.ReentrantLock; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.mgmt.ExecutionContext; -import org.apache.brooklyn.api.mgmt.Task; -import org.apache.brooklyn.api.mgmt.TaskFactory; -import org.apache.brooklyn.camp.spi.Assembly; -import org.apache.brooklyn.camp.spi.AssemblyTemplate; -import org.apache.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; -import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; -import org.apache.brooklyn.util.core.task.BasicExecutionContext; -import org.apache.brooklyn.util.core.task.DeferredSupplier; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** provide an object suitable to resolve chained invocations in a parsed YAML / Deployment Plan DSL, - * which also implements {@link DeferredSupplier} so that they can be resolved when needed - * (e.g. when entity-lookup and execution contexts are available). - * <p> - * implementations of this abstract class are expected to be immutable, - * as instances must support usage in multiple {@link Assembly} instances - * created from a single {@link AssemblyTemplate} - * <p> - * subclasses which return a deferred value are typically only - * resolvable in the context of a {@link Task} on an {@link Entity}; - * these should be only used as the value of a {@link ConfigKey} set in the YAML, - * and should not accessed until after the components / entities are created - * and are being started. - * (TODO the precise semantics of this are under development.) - * - * The threading model is that only one thread can call {@link #get()} at a time. An interruptible - * lock is obtained using {@link #lock} for the duration of that method. It is important to not - * use {@code synchronized} because that is not interruptible - if someone tries to get the value - * and interrupts after a short wait, then we must release the lock immediately and return. - * <p> - **/ -public abstract class BrooklynDslDeferredSupplier<T> implements DeferredSupplier<T>, TaskFactory<Task<T>>, Serializable { - - private static final long serialVersionUID = -8789624905412198233L; - - private static final Logger log = LoggerFactory.getLogger(BrooklynDslDeferredSupplier.class); - - /** - * Lock to be used, rather than {@code synchronized} blocks, for anything long-running. - * Use {@link #getLock()} rather than this field directly, to ensure it is reinitialised - * after rebinding. - * - * @see https://issues.apache.org/jira/browse/BROOKLYN-214 - */ - private transient ReentrantLock lock; - - // TODO json of this object should *be* this, not wrapped this ($brooklyn:literal is a bit of a hack, though it might work!) - @JsonInclude - @JsonProperty(value="$brooklyn:literal") - // currently marked transient because it's only needed for logging - private transient Object dsl = "(gone)"; - - public BrooklynDslDeferredSupplier() { - PlanInterpretationNode sourceNode = BrooklynDslInterpreter.currentNode(); - dsl = sourceNode!=null ? sourceNode.getOriginalValue() : null; - lock = new ReentrantLock(); - } - - /** returns the current entity; for use in implementations of {@link #get()} */ - protected final static EntityInternal entity() { - return (EntityInternal) BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); - } - - /** - * Returns the current management context; for use in implementations of {@link #get()} that are not associated - * with an entity. - */ - protected final static ManagementContextInternal managementContext() { - return (ManagementContextInternal) BrooklynTaskTags.getManagementContext(Tasks.current()); - } - - @Override - public final T get() { - try { - getLock().lockInterruptibly(); - } catch (InterruptedException e) { - throw Exceptions.propagate(e); - } - - try { - if (log.isDebugEnabled()) - log.debug("Queuing task to resolve "+dsl+", called by "+Tasks.current()); - - EntityInternal entity = (EntityInternal) BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); - ExecutionContext exec = - (entity != null) ? entity.getExecutionContext() - : BasicExecutionContext.getCurrentExecutionContext(); - if (exec == null) { - throw new IllegalStateException("No execution context available to resolve " + dsl); - } - - Task<T> task = newTask(); - T result = exec.submit(task).get(); - - if (log.isDebugEnabled()) - log.debug("Resolved "+result+" from "+dsl); - return result; - - } catch (Exception e) { - throw Exceptions.propagate(e); - } finally { - getLock().unlock(); - } - } - - // Use this method, rather than the direct field, to ensure it is initialised after rebinding. - protected ReentrantLock getLock() { - synchronized (this) { - if (lock == null) { - lock = new ReentrantLock(); - } - } - return lock; - } - - @Override - public abstract Task<T> newTask(); - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java deleted file mode 100644 index f43d33c..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.dsl; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon; -import org.apache.brooklyn.camp.brooklyn.spi.dsl.parse.DslParser; -import org.apache.brooklyn.camp.brooklyn.spi.dsl.parse.FunctionWithArgs; -import org.apache.brooklyn.camp.brooklyn.spi.dsl.parse.QuotedString; -import org.apache.brooklyn.camp.spi.resolve.PlanInterpreter; -import org.apache.brooklyn.camp.spi.resolve.PlanInterpreter.PlanInterpreterAdapter; -import org.apache.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode; -import org.apache.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode.Role; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.javalang.Reflections; -import org.apache.brooklyn.util.text.Strings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Optional; - -/** - * {@link PlanInterpreter} which understands the $brooklyn DSL - */ -public class BrooklynDslInterpreter extends PlanInterpreterAdapter { - - private static final Logger log = LoggerFactory.getLogger(BrooklynDslInterpreter.class); - - @Override - public boolean isInterestedIn(PlanInterpretationNode node) { - return node.matchesPrefix("$brooklyn:") || node.getNewValue() instanceof FunctionWithArgs; - } - - private static ThreadLocal<PlanInterpretationNode> currentNode = new ThreadLocal<PlanInterpretationNode>(); - /** returns the current node, stored in a thread-local, to populate the dsl field of {@link BrooklynDslDeferredSupplier} instances */ - public static PlanInterpretationNode currentNode() { - return currentNode.get(); - } - /** sets the current node */ - public static void currentNode(PlanInterpretationNode node) { - currentNode.set(node); - } - public static void currentNodeClear() { - currentNode.set(null); - } - - @Override - public void applyYamlPrimitive(PlanInterpretationNode node) { - String expression = node.getNewValue().toString(); - - try { - currentNode.set(node); - Object parsedNode = new DslParser(expression).parse(); - if ((parsedNode instanceof FunctionWithArgs) && ((FunctionWithArgs)parsedNode).getArgs()==null) { - if (node.getRoleInParent() == Role.MAP_KEY) { - node.setNewValue(parsedNode); - // will be handled later - } else { - throw new IllegalStateException("Invalid function-only expression '"+((FunctionWithArgs)parsedNode).getFunction()+"'"); - } - } else { - node.setNewValue( evaluate(parsedNode, true) ); - } - } catch (Exception e) { - log.warn("Error evaluating node (rethrowing) '"+expression+"': "+e); - Exceptions.propagateIfFatal(e); - throw new IllegalArgumentException("Error evaluating node '"+expression+"'", e); - } finally { - currentNodeClear(); - } - } - - @Override - public boolean applyMapEntry(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut, - PlanInterpretationNode key, PlanInterpretationNode value) { - if (key.getNewValue() instanceof FunctionWithArgs) { - try { - currentNode.set(node); - - FunctionWithArgs f = (FunctionWithArgs) key.getNewValue(); - if (f.getArgs()!=null) - throw new IllegalStateException("Invalid map key function "+f.getFunction()+"; should not have arguments if taking arguments from map"); - - // means evaluation acts on values - List<Object> args = new ArrayList<Object>(); - if (value.getNewValue() instanceof Iterable<?>) { - for (Object vi: (Iterable<?>)value.getNewValue()) - args.add(vi); - } else { - args.add(value.getNewValue()); - } - - try { - // TODO in future we should support functions of the form 'Maps.clear', 'Maps.reset', 'Maps.remove', etc; - // default approach only supported if mapIn has single item and mapOut is empty - if (mapIn.size()!=1) - throw new IllegalStateException("Map-entry DSL syntax only supported with single item in map, not "+mapIn); - if (mapOut.size()!=0) - throw new IllegalStateException("Map-entry DSL syntax only supported with empty output map-so-far, not "+mapOut); - - node.setNewValue( evaluate(new FunctionWithArgs(f.getFunction(), args), false) ); - return false; - } catch (Exception e) { - log.warn("Error evaluating map-entry (rethrowing) '"+f.getFunction()+args+"': "+e); - Exceptions.propagateIfFatal(e); - throw new IllegalArgumentException("Error evaluating map-entry '"+f.getFunction()+args+"'", e); - } - - } finally { - currentNodeClear(); - } - } - return super.applyMapEntry(node, mapIn, mapOut, key, value); - } - - public Object evaluate(Object f, boolean deepEvaluation) { - if (f instanceof FunctionWithArgs) { - return evaluateOn(BrooklynDslCommon.class, (FunctionWithArgs) f, deepEvaluation); - } - - if (f instanceof List) { - Object o = BrooklynDslCommon.class; - for (Object i: (List<?>)f) { - o = evaluateOn( o, (FunctionWithArgs)i, deepEvaluation ); - } - return o; - } - - if (f instanceof QuotedString) { - return ((QuotedString)f).unwrapped(); - } - - throw new IllegalArgumentException("Unexpected element in parse tree: '"+f+"' (type "+(f!=null ? f.getClass() : null)+")"); - } - - public Object evaluateOn(Object o, FunctionWithArgs f, boolean deepEvaluation) { - if (f.getArgs()==null) - throw new IllegalStateException("Invalid function-only expression '"+f.getFunction()+"'"); - - Class<?> clazz; - if (o instanceof Class) { - clazz = (Class<?>)o; - } else { - clazz = o.getClass(); - } - if (!(clazz.getPackage().getName().startsWith(BrooklynDslCommon.class.getPackage().getName()))) - throw new IllegalArgumentException("Not permitted to invoke function on '"+clazz+"' (outside allowed package scope)"); - - String fn = f.getFunction(); - fn = Strings.removeFromStart(fn, "$brooklyn:"); - if (fn.startsWith("function.")) { - // If the function name starts with 'function.', then we look for the function in BrooklynDslCommon.Functions - // As all functions in BrooklynDslCommon.Functions are static, we don't need to worry whether a class - // or an instance was passed into this method - o = BrooklynDslCommon.Functions.class; - fn = Strings.removeFromStart(fn, "function."); - } - try { - List<Object> args = new ArrayList<>(); - for (Object arg: f.getArgs()) { - args.add( deepEvaluation ? evaluate(arg, true) : arg ); - } - Optional<Object> v = Reflections.invokeMethodWithArgs(o, fn, args); - if (v.isPresent()) return v.get(); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - throw Exceptions.propagate(new InvocationTargetException(e, "Error invoking '"+fn+"' on '"+o+"'")); - } - - throw new IllegalArgumentException("No such function '"+fn+"' on "+o); - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java deleted file mode 100644 index f75b0f9..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.dsl; - -import org.apache.brooklyn.util.core.task.DeferredSupplier; - -import com.google.common.collect.Iterables; - -public class DslUtils { - - /** true iff none of the args are deferred / tasks */ - public static boolean resolved(Iterable<Object> args) { - return resolved(Iterables.toArray(args, Object.class)); - } - - /** true iff none of the args are deferred / tasks */ - public static boolean resolved(final Object... args) { - boolean allResolved = true; - for (Object arg: args) { - if (arg instanceof DeferredSupplier<?>) { - allResolved = false; - break; - } - } - return allResolved; - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java deleted file mode 100644 index 88a1f1d..0000000 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * 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.brooklyn.camp.brooklyn.spi.dsl.methods; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; - -import javax.annotation.Nullable; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.mgmt.Task; -import org.apache.brooklyn.api.mgmt.TaskAdaptable; -import org.apache.brooklyn.api.mgmt.TaskFactory; -import org.apache.brooklyn.api.objs.Configurable; -import org.apache.brooklyn.api.sensor.Sensor; -import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys; -import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator; -import org.apache.brooklyn.camp.brooklyn.spi.creation.EntitySpecConfiguration; -import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier; -import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslUtils; -import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope; -import org.apache.brooklyn.core.config.external.ExternalConfigSupplier; -import org.apache.brooklyn.core.entity.EntityDynamicType; -import org.apache.brooklyn.core.mgmt.internal.ExternalConfigSupplierRegistry; -import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; -import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider; -import org.apache.brooklyn.core.sensor.DependentConfiguration; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.core.flags.ClassCoercionException; -import org.apache.brooklyn.util.core.flags.FlagUtils; -import org.apache.brooklyn.util.core.flags.TypeCoercions; -import org.apache.brooklyn.util.core.task.DeferredSupplier; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.javalang.Reflections; -import org.apache.brooklyn.util.text.StringEscapes.JavaStringEscapes; -import org.apache.brooklyn.util.text.Strings; -import org.apache.commons.beanutils.BeanUtils; - -import com.google.common.base.Function; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; - -/** static import functions which can be used in `$brooklyn:xxx` contexts */ -public class BrooklynDslCommon { - - // Access specific entities - - public static DslComponent entity(String id) { - return new DslComponent(Scope.GLOBAL, id); - } - public static DslComponent parent() { - return new DslComponent(Scope.PARENT, null); - } - public static DslComponent child(String id) { - return new DslComponent(Scope.CHILD, id); - } - public static DslComponent sibling(String id) { - return new DslComponent(Scope.SIBLING, id); - } - public static DslComponent descendant(String id) { - return new DslComponent(Scope.DESCENDANT, id); - } - public static DslComponent ancestor(String id) { - return new DslComponent(Scope.ANCESTOR, id); - } - public static DslComponent root() { - return new DslComponent(Scope.ROOT, null); - } - public static DslComponent scopeRoot() { - return new DslComponent(Scope.SCOPE_ROOT, null); - } - // prefer the syntax above to the below now, but not deprecating the below - public static DslComponent component(String id) { - return component("global", id); - } - public static DslComponent component(String scope, String id) { - if (!DslComponent.Scope.isValid(scope)) { - throw new IllegalArgumentException(scope + " is not a valid scope"); - } - return new DslComponent(DslComponent.Scope.fromString(scope), id); - } - - // Access things on entities - - public static BrooklynDslDeferredSupplier<?> config(String keyName) { - return new DslComponent(Scope.THIS, "").config(keyName); - } - - public static BrooklynDslDeferredSupplier<?> attributeWhenReady(String sensorName) { - return new DslComponent(Scope.THIS, "").attributeWhenReady(sensorName); - } - - /** Returns a {@link Sensor}, looking up the sensor on the context if available and using that, - * or else defining an untyped (Object) sensor */ - public static BrooklynDslDeferredSupplier<Sensor<?>> sensor(String sensorName) { - return new DslComponent(Scope.THIS, "").sensor(sensorName); - } - - /** Returns a {@link Sensor} declared on the type (e.g. entity class) declared in the first argument. */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static Sensor<?> sensor(String clazzName, String sensorName) { - try { - // TODO Should use catalog's classloader, rather than Class.forName; how to get that? Should we return a future?! - String mappedClazzName = DeserializingClassRenamesProvider.findMappedName(clazzName); - Class<?> clazz = Class.forName(mappedClazzName); - - Sensor<?> sensor; - if (Entity.class.isAssignableFrom(clazz)) { - sensor = new EntityDynamicType((Class<? extends Entity>) clazz).getSensor(sensorName); - } else { - // Some non-entity classes (e.g. ServiceRestarter policy) declare sensors that other - // entities/policies/enrichers may wish to reference. - Map<String,Sensor<?>> sensors = EntityDynamicType.findSensors((Class)clazz, null); - sensor = sensors.get(sensorName); - } - if (sensor == null) { - // TODO could extend API to return a sensor of the given type; useful but makes API ambiguous in theory (unlikely in practise, but still...) - throw new IllegalArgumentException("Sensor " + sensorName + " not found on class " + clazzName); - } - return sensor; - } catch (ClassNotFoundException e) { - throw Exceptions.propagate(e); - } - } - - // Build complex things - - public static EntitySpecConfiguration entitySpec(Map<String, Object> arguments) { - return new EntitySpecConfiguration(arguments); - } - - /** - * Return an instance of the specified class with its fields set according - * to the {@link Map} or a {@link BrooklynDslDeferredSupplier} if the arguments are not - * yet fully resolved. - */ - @SuppressWarnings("unchecked") - public static Object object(Map<String, Object> arguments) { - ConfigBag config = ConfigBag.newInstance(arguments); - String typeName = BrooklynYamlTypeInstantiator.InstantiatorFromKey.extractTypeName("object", config).orNull(); - Map<String,Object> objectFields = (Map<String, Object>) config.getStringKeyMaybe("object.fields").or(MutableMap.of()); - Map<String,Object> brooklynConfig = (Map<String, Object>) config.getStringKeyMaybe(BrooklynCampReservedKeys.BROOKLYN_CONFIG).or(MutableMap.of()); - try { - // TODO Should use catalog's classloader, rather than Class.forName; how to get that? Should we return a future?! - String mappedTypeName = DeserializingClassRenamesProvider.findMappedName(typeName); - Class<?> type = Class.forName(mappedTypeName); - - if (!Reflections.hasNoArgConstructor(type)) { - throw new IllegalStateException(String.format("Cannot construct %s bean: No public no-arg constructor available", type)); - } - if ((objectFields.isEmpty() || DslUtils.resolved(objectFields.values())) && - (brooklynConfig.isEmpty() || DslUtils.resolved(brooklynConfig.values()))) { - return DslObject.create(type, objectFields, brooklynConfig); - } else { - return new DslObject(type, objectFields, brooklynConfig); - } - } catch (ClassNotFoundException e) { - throw Exceptions.propagate(e); - } - } - - // String manipulation - - /** Return the expression as a literal string without any further parsing. */ - public static Object literal(Object expression) { - return expression; - } - - /** - * Returns a formatted string or a {@link BrooklynDslDeferredSupplier} if the arguments - * are not yet fully resolved. - */ - public static Object formatString(final String pattern, final Object...args) { - if (DslUtils.resolved(args)) { - // if all args are resolved, apply the format string now - return String.format(pattern, args); - } else { - return new DslFormatString(pattern, args); - } - } - - public static Object regexReplacement(final Object source, final Object pattern, final Object replacement) { - if (DslUtils.resolved(Arrays.asList(source, pattern, replacement))) { - return (new Functions.RegexReplacer(String.valueOf(pattern), String.valueOf(replacement))).apply(String.valueOf(source)); - } else { - return new DslRegexReplacement(source, pattern, replacement); - } - } - - /** - * Deferred execution of String formatting. - * - * @see DependentConfiguration#formatString(String, Object...) - */ - protected static class DslFormatString extends BrooklynDslDeferredSupplier<String> { - - private static final long serialVersionUID = -4849297712650560863L; - - private String pattern; - private Object[] args; - - public DslFormatString(String pattern, Object ...args) { - this.pattern = pattern; - this.args = args; - } - - @Override - public Task<String> newTask() { - return DependentConfiguration.formatString(pattern, args); - } - - @Override - public String toString() { - return "$brooklyn:formatString("+ - JavaStringEscapes.wrapJavaString(pattern)+ - (args==null || args.length==0 ? "" : ","+Strings.join(args, ","))+")"; - } - } - - - - protected static class DslRegexReplacement extends BrooklynDslDeferredSupplier<String> { - - private Object source; - private Object pattern; - private Object replacement; - - public DslRegexReplacement(Object source, Object pattern, Object replacement) { - this.pattern = pattern; - this.replacement = replacement; - this.source = source; - } - - @Override - public Task<String> newTask() { - return DependentConfiguration.regexReplacement(source, pattern, replacement); - } - - @Override - public String toString() { - return String.format("$brooklyn:regexReplace(%s:%s:%s)",source, pattern, replacement); - } - } - - /** @deprecated since 0.7.0; use {@link DslFormatString} */ - @SuppressWarnings("serial") - @Deprecated - protected static class FormatString extends DslFormatString { - public FormatString(String pattern, Object[] args) { - super(pattern, args); - } - } - - /** Deferred execution of Object creation. */ - protected static class DslObject extends BrooklynDslDeferredSupplier<Object> { - - private static final long serialVersionUID = 8878388748085419L; - - private Class<?> type; - private Map<String,Object> fields, config; - - public DslObject(Class<?> type, Map<String,Object> fields, Map<String,Object> config) { - this.type = type; - this.fields = MutableMap.copyOf(fields); - this.config = MutableMap.copyOf(config); - } - - @SuppressWarnings("unchecked") - @Override - public Task<Object> newTask() { - List<TaskAdaptable<Object>> tasks = Lists.newLinkedList(); - for (Object value : Iterables.concat(fields.values(), config.values())) { - if (value instanceof TaskAdaptable) { - tasks.add((TaskAdaptable<Object>) value); - } else if (value instanceof TaskFactory) { - tasks.add(((TaskFactory<TaskAdaptable<Object>>) value).newTask()); - } - } - Map<String,?> flags = MutableMap.<String,String>of("displayName", "building '"+type+"' with "+tasks.size()+" task"+(tasks.size()!=1?"s":"")); - return DependentConfiguration.transformMultiple(flags, new Function<List<Object>, Object>() { - @Override - public Object apply(List<Object> input) { - Iterator<Object> values = input.iterator(); - for (String name : fields.keySet()) { - Object value = fields.get(name); - if (value instanceof TaskAdaptable || value instanceof TaskFactory) { - fields.put(name, values.next()); - } else if (value instanceof DeferredSupplier) { - fields.put(name, ((DeferredSupplier<?>) value).get()); - } - } - for (String name : config.keySet()) { - Object value = config.get(name); - if (value instanceof TaskAdaptable || value instanceof TaskFactory) { - config.put(name, values.next()); - } else if (value instanceof DeferredSupplier) { - config.put(name, ((DeferredSupplier<?>) value).get()); - } - } - return create(type, fields, config); - } - }, tasks); - } - - public static <T> T create(Class<T> type, Map<String,?> fields, Map<String,?> config) { - try { - T bean; - try { - bean = (T) TypeCoercions.coerce(fields, type); - } catch (ClassCoercionException ex) { - bean = Reflections.invokeConstructorWithArgs(type).get(); - BeanUtils.populate(bean, fields); - } - if (bean instanceof Configurable && config.size() > 0) { - ConfigBag brooklyn = ConfigBag.newInstance(config); - FlagUtils.setFieldsFromFlags(bean, brooklyn); - FlagUtils.setAllConfigKeys((Configurable) bean, brooklyn, true); - } - return bean; - } catch (Exception e) { - throw Exceptions.propagate(e); - } - } - - @Override - public String toString() { - return "$brooklyn:object(\""+type.getName()+"\")"; - } - } - - /** - * Defers to management context's {@link ExternalConfigSupplierRegistry} to resolve values at runtime. - * The name of the appropriate {@link ExternalConfigSupplier} is captured, along with the key of - * the desired config value. - */ - public static DslExternal external(final String providerName, final String key) { - return new DslExternal(providerName, key); - } - protected final static class DslExternal extends BrooklynDslDeferredSupplier<Object> { - private static final long serialVersionUID = -3860334240490397057L; - private final String providerName; - private final String key; - - public DslExternal(String providerName, String key) { - this.providerName = providerName; - this.key = key; - } - - @Override - public Task<Object> newTask() { - return Tasks.<Object>builder() - .displayName("resolving external configuration: '" + key + "' from provider '" + providerName + "'") - .dynamic(false) - .body(new Callable<Object>() { - @Override - public Object call() throws Exception { - ManagementContextInternal managementContext = DslExternal.managementContext(); - return managementContext.getExternalConfigProviderRegistry().getConfig(providerName, key); - } - }) - .build(); - } - - @Override - public String toString() { - return "$brooklyn:external("+providerName+", "+key+")"; - } - } - - public static class Functions { - public static Object regexReplacement(final Object pattern, final Object replacement) { - if (DslUtils.resolved(pattern, replacement)) { - return new RegexReplacer(String.valueOf(pattern), String.valueOf(replacement)); - } else { - return new DslRegexReplacer(pattern, replacement); - } - } - - public static class RegexReplacer implements Function<String, String> { - private final String pattern; - private final String replacement; - - public RegexReplacer(String pattern, String replacement) { - this.pattern = pattern; - this.replacement = replacement; - } - - @Nullable - @Override - public String apply(@Nullable String s) { - return s == null ? null : Strings.replaceAllRegex(s, pattern, replacement); - } - } - - protected static class DslRegexReplacer extends BrooklynDslDeferredSupplier<Function<String, String>> { - - private Object pattern; - private Object replacement; - - public DslRegexReplacer(Object pattern, Object replacement) { - this.pattern = pattern; - this.replacement = replacement; - } - - @Override - public Task<Function<String, String>> newTask() { - return DependentConfiguration.regexReplacement(pattern, replacement); - } - - @Override - public String toString() { - return String.format("$brooklyn:regexReplace(%s:%s)", pattern, replacement); - } - } - } - -}
