Github user neykov commented on a diff in the pull request:

    https://github.com/apache/incubator-brooklyn/pull/617#discussion_r30787423
  
    --- Diff: 
core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java ---
    @@ -0,0 +1,380 @@
    +/*
    + * 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 brooklyn.catalog.internal;
    +
    +import java.io.File;
    +import java.util.Collection;
    +import java.util.List;
    +
    +import org.slf4j.Logger;
    +import org.slf4j.LoggerFactory;
    +
    +import brooklyn.catalog.CatalogItem;
    +import brooklyn.config.BrooklynServerConfig;
    +import brooklyn.management.ManagementContext;
    +import brooklyn.management.ManagementContextInjectable;
    +import brooklyn.management.internal.ManagementContextInternal;
    +import brooklyn.util.ResourceUtils;
    +import brooklyn.util.collections.MutableList;
    +import brooklyn.util.exceptions.Exceptions;
    +import brooklyn.util.exceptions.FatalRuntimeException;
    +import brooklyn.util.exceptions.RuntimeInterruptedException;
    +import brooklyn.util.flags.TypeCoercions;
    +import brooklyn.util.guava.Maybe;
    +import brooklyn.util.os.Os;
    +import brooklyn.util.text.Strings;
    +
    +import com.google.common.annotations.Beta;
    +import com.google.common.base.Function;
    +import com.google.common.base.Preconditions;
    +import com.google.common.collect.ImmutableList;
    +import com.google.common.collect.Iterables;
    +
    +@Beta
    +public class CatalogInitialization implements ManagementContextInjectable {
    +
    +    /*
    +
    +    A1) if not persisting, go to B1
    +    A2) if --catalog-reset, delete persisted catalog items
    +    A3) if there is a persisted catalog (and it wasn't not deleted by A2), 
read it and go to C1
    +    A4) go to B1
    +
    +    B1) look for --catalog-initial, if so read it, then go to C1
    +    B2) look for BrooklynServerConfig.BROOKLYN_CATALOG_URL, if so, read 
it, supporting YAML or XML (warning if XML), then go to C1
    +    B3) look for ~/.brooklyn/catalog.bom, if exists, read it then go to C1
    +    B4) look for ~/.brooklyn/brooklyn.xml, if exists, warn, read it then 
go to C1
    +    B5) read all classpath://brooklyn/default.catalog.bom items, if they 
exist (and for now they will)
    +    B6) go to C1
    +
    +    C1) if --catalog-add, read and add those items
    +
    +    D1) if persisting, read the rest of the persisted items (entities etc)
    +
    +     */
    +
    +    private static final Logger log = 
LoggerFactory.getLogger(CatalogInitialization.class);
    +    
    +    private String initialUri;
    +    private boolean reset;
    +    private String additionsUri;
    +    private boolean force;
    +
    +    private boolean disallowLocal = false;
    +    private List<Function<CatalogInitialization, Void>> callbacks = 
MutableList.of();
    +    private boolean hasRunBestEffort = false, hasRunOfficial = false, 
isPopulating = false;
    +    
    +    private ManagementContext managementContext;
    +    private boolean isStartingUp = false;
    +    private boolean failOnStartupErrors = false;
    +    
    +    private Object populatingCatalogMutex = new Object();
    +    
    +    public CatalogInitialization(String initialUri, boolean reset, String 
additionUri, boolean force) {
    +        this.initialUri = initialUri;
    +        this.reset = reset;
    +        this.additionsUri = additionUri;
    +        this.force = force;
    +    }
    +    
    +    public CatalogInitialization() {
    +        this(null, false, null, false);
    +    }
    +
    +    public void injectManagementContext(ManagementContext 
managementContext) {
    +        Preconditions.checkNotNull(managementContext, "management 
context");
    +        if (this.managementContext!=null && 
managementContext!=this.managementContext)
    +            throw new IllegalStateException("Cannot switch management 
context, from "+this.managementContext+" to "+managementContext);
    +        this.managementContext = managementContext;
    +    }
    +    
    +    /** Called by the framework to set true while starting up, and false 
afterwards,
    +     * in order to assist in appropriate logging and error handling. */
    +    public void setStartingUp(boolean isStartingUp) {
    +        this.isStartingUp = isStartingUp;
    +    }
    +
    +    public void setFailOnStartupErrors(boolean startupFailOnCatalogErrors) 
{
    +        this.failOnStartupErrors = startupFailOnCatalogErrors;
    +    }
    +
    +    public CatalogInitialization 
addPopulationCallback(Function<CatalogInitialization, Void> callback) {
    +        callbacks.add(callback);
    +        return this;
    +    }
    +    
    +    public ManagementContext getManagementContext() {
    +        return Preconditions.checkNotNull(managementContext, "management 
context has not been injected into "+this);
    +    }
    +
    +    public boolean isInitialResetRequested() {
    +        return reset;
    +    }
    +
    +    public boolean hasRunOfficial() { return hasRunOfficial; }
    +    public boolean hasRunIncludingBestEffort() { return hasRunOfficial || 
hasRunBestEffort; }
    +
    +    /** makes or updates the mgmt catalog, based on the settings in this 
class */
    +    public void populateCatalog(boolean needsInitial, 
Collection<CatalogItem<?, ?>> optionalItemsForResettingCatalog) {
    +        synchronized (populatingCatalogMutex) {
    +            try {
    +                isPopulating = true;
    +                BasicBrooklynCatalog catalog = (BasicBrooklynCatalog) 
managementContext.getCatalog();
    +                if (!catalog.getCatalog().isLoaded()) {
    +                    catalog.load();
    +                } else {
    +                    if (needsInitial && (hasRunOfficial || 
hasRunBestEffort)) {
    +                        // an indication that something caused it to load 
early; not severe, but unusual
    +                        log.warn("Catalog initialization has not properly 
run but management context has a catalog; re-populating, possibly overwriting 
items installed during earlier access (it may have been an early web request)");
    +                        
catalog.reset(ImmutableList.<CatalogItem<?,?>>of());
    +                    }
    +                }
    +                hasRunOfficial = true;
    +
    +                populateCatalogImpl(catalog, needsInitial, 
optionalItemsForResettingCatalog);
    +            } finally {
    +                hasRunOfficial = true;
    +                isPopulating = false;
    +            }
    +        }
    +    }
    +
    +    private void populateCatalogImpl(BasicBrooklynCatalog catalog, boolean 
needsInitial, Collection<CatalogItem<?, ?>> optionalItemsForResettingCatalog) {
    +        applyCatalogLoadMode();
    +        
    +        if (optionalItemsForResettingCatalog!=null) {
    +            catalog.reset(optionalItemsForResettingCatalog);
    +        }
    +        
    +        if (needsInitial) {
    +            populateInitial(catalog);
    +        }
    +        
    +        populateAdditions(catalog);
    +
    +        populateViaCallbacks(catalog);
    +    }
    +
    +    private enum PopulateMode { YAML, XML, AUTODETECT }
    +    
    +    protected void populateInitial(BasicBrooklynCatalog catalog) {
    +        if (disallowLocal) {
    +            if (!hasRunOfficial()) {
    +                log.debug("CLI initial catalog not being read with 
disallow-local mode set.");
    +            }
    +            return;
    +        }
    +
    +//        B1) look for --catalog-initial, if so read it, then go to C1
    +//        B2) look for BrooklynServerConfig.BROOKLYN_CATALOG_URL, if so, 
read it, supporting YAML or XML (warning if XML), then go to C1
    +//        B3) look for ~/.brooklyn/catalog.bom, if exists, read it then go 
to C1
    +//        B4) look for ~/.brooklyn/brooklyn.xml, if exists, warn, read it 
then go to C1
    +//        B5) read all classpath://brooklyn/default.catalog.bom items, if 
they exist (and for now they will)
    +//        B6) go to C1
    +
    +        if (initialUri!=null) {
    +            populateInitialFromUri(catalog, initialUri, 
PopulateMode.AUTODETECT);
    +            return;
    +        }
    +        
    +        String catalogUrl = 
managementContext.getConfig().getConfig(BrooklynServerConfig.BROOKLYN_CATALOG_URL);
    +        if (Strings.isNonBlank(catalogUrl)) {
    +            populateInitialFromUri(catalog, catalogUrl, 
PopulateMode.AUTODETECT);
    +            return;
    +        }
    +        
    +        catalogUrl = Os.mergePaths(BrooklynServerConfig.getMgmtBaseDir( 
managementContext.getConfig() ), "catalog.bom");
    +        if (new File(catalogUrl).exists()) {
    +            populateInitialFromUri(catalog, "file:"+catalogUrl, 
PopulateMode.YAML);
    +            return;
    +        }
    +        
    +        catalogUrl = Os.mergePaths(BrooklynServerConfig.getMgmtBaseDir( 
managementContext.getConfig() ), "catalog.xml");
    +        if (new File(catalogUrl).exists()) {
    +            populateInitialFromUri(catalog, "file:"+catalogUrl, 
PopulateMode.XML);
    +            return;
    +        }
    +
    +        // otherwise look for for classpath:/brooklyn/default.catalog.bom 
--
    +        // there is one on the classpath which says to scan, and provides 
a few templates;
    +        // if one is supplied by user in the conf/ dir that will override 
the item from the classpath
    +        // (TBD - we might want to scan for all such bom's?)
    +        
    +        catalogUrl = "classpath:/brooklyn/default.catalog.bom";
    +        if (new ResourceUtils(this).doesUrlExist(catalogUrl)) {
    +            populateInitialFromUri(catalog, catalogUrl, PopulateMode.YAML);
    +            return;
    +        }
    +        
    +        log.info("No catalog found on classpath or specified; catalog will 
not be initialized.");
    +        return;
    +    }
    +    
    +    private void populateInitialFromUri(BasicBrooklynCatalog catalog, 
String catalogUrl, PopulateMode mode) {
    +        log.debug("Loading initial catalog from {}", catalogUrl);
    +
    +        Exception problem = null;
    +        Object result = null;
    +        
    +        String contents = null;
    +        try {
    +            contents = new 
ResourceUtils(this).getResourceAsString(catalogUrl);
    +        } catch (Exception e) {
    +            Exceptions.propagateIfFatal(e);
    +            if (problem==null) problem = e;
    +        }
    +
    +        if (contents!=null && (mode==PopulateMode.YAML || 
mode==PopulateMode.AUTODETECT)) {
    +            // try YAML first
    +            try {
    +                catalog.reset(MutableList.<CatalogItem<?,?>>of());
    +                result = catalog.addItems(contents);
    +            } catch (Exception e) {
    +                Exceptions.propagateIfFatal(e);
    +                if (problem==null) problem = e;
    +            }
    +        }
    +        
    +        if (result==null && contents!=null && (mode==PopulateMode.XML || 
mode==PopulateMode.AUTODETECT)) {
    +            // then try XML
    +            try {
    +                populateInitialFromUriXml(catalog, catalogUrl, contents);
    +                // clear YAML problem
    +                problem = null;
    +            } catch (Exception e) {
    +                Exceptions.propagateIfFatal(e);
    +                if (problem==null) problem = e;
    +            }
    +        }
    +        
    +        if (result!=null) {
    +            log.debug("Loaded initial catalog from {}: {}", catalogUrl, 
result);
    +        }
    +        if (problem!=null) {
    +            log.warn("Error importing catalog from " + catalogUrl + ": " + 
problem, problem);
    +            // TODO inform mgmt of error
    +        }
    +
    +    }
    +
    +    // deprecated XML format
    +    @SuppressWarnings("deprecation")
    +    private void populateInitialFromUriXml(BasicBrooklynCatalog catalog, 
String catalogUrl, String contents) {
    +        CatalogDto dto = CatalogDto.newDtoFromXmlContents(contents, 
catalogUrl);
    +        if (dto!=null) {
    +            catalog.reset(dto);
    +        }
    +    }
    +
    +    boolean hasRunAdditions = false;
    +    protected void populateAdditions(BasicBrooklynCatalog catalog) {
    +        if (Strings.isNonBlank(additionsUri)) {
    +            if (disallowLocal) {
    +                if (!hasRunAdditions) {
    +                    log.warn("CLI additions supplied but not supported in 
disallow-local mode; ignoring.");
    +                }
    +                return;
    --- End diff --
    
    Same as above - if the user explicitly uses `--catalogAdd` on the command 
line, better to take precedence over deprecated configuration or fail with a 
descriptive message.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---

Reply via email to