/** * Copyright 2011-2017 Asakusa Framework Team. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.asakusafw.yaess.core; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.TreeMap; import com.asakusafw.yaess.core.util.PropertiesUtil; /** * Profile services for YAESS. * @since 0.2.3 */ public class YaessProfile { /** * The qualifier delimiter for each property keys. */ public static final char QUALIFIER = '.'; /** * The key prefix of core profile. * This profile must describes {@link CoreProfile} service. */ public static final String PREFIX_CORE = "core"; /** * The key prefix of monitor profile. * This profile must describes {@link ExecutionMonitorProvider} service. */ public static final String PREFIX_MONITOR = "monitor"; /** * The key prefix of lock provider profile. * This profile must describes {@link ExecutionLockProvider} service. */ public static final String PREFIX_LOCK = "lock"; /** * The key prefix of job scheduler profile. * This profile must describes {@link JobScheduler} service. */ public static final String PREFIX_SCHEDULER = "scheduler"; /** * The key prefix of Hadoop script handler profile. * This profile must describes {@link HadoopScriptHandler} service. */ public static final String PREFIX_HADOOP = "hadoop"; /** * The key prefix of command script handlers profile. * Each command script handler must be use {@code "command.<profile-name>"} as its prefix. * This profile must describes {@link CommandScriptHandler} service. */ public static final String PREFIX_COMMAND = "command"; private static final String GROUP_PREFIX_COMMAND = PREFIX_COMMAND + QUALIFIER; private final ServiceProfile<CoreProfile> core; private final ServiceProfile<ExecutionMonitorProvider> monitors; private final ServiceProfile<ExecutionLockProvider> locks; private final ServiceProfile<JobScheduler> scheduler; private final ServiceProfile<HadoopScriptHandler> hadoopHandler; private final Map<String, ServiceProfile<CommandScriptHandler>> commandHandlers; /** * Creates a new instance. * @param core core profile * @param monitors monitor profile * @param locks lock profile * @param scheduler scheduler profile * @param hadoopHandler hadoop handler profile * @param commandHandlers command handler profiles * @throws IllegalArgumentException if some parameters were {@code null} */ public YaessProfile( ServiceProfile<CoreProfile> core, ServiceProfile<ExecutionMonitorProvider> monitors, ServiceProfile<ExecutionLockProvider> locks, ServiceProfile<JobScheduler> scheduler, ServiceProfile<HadoopScriptHandler> hadoopHandler, Collection<ServiceProfile<CommandScriptHandler>> commandHandlers) { if (core == null) { throw new IllegalArgumentException("core must not be null"); //$NON-NLS-1$ } if (monitors == null) { throw new IllegalArgumentException("monitors must not be null"); //$NON-NLS-1$ } if (locks == null) { throw new IllegalArgumentException("locks must not be null"); //$NON-NLS-1$ } if (scheduler == null) { throw new IllegalArgumentException("scheduler must not be null"); //$NON-NLS-1$ } if (hadoopHandler == null) { throw new IllegalArgumentException("hadoopHandler must not be null"); //$NON-NLS-1$ } if (commandHandlers == null) { throw new IllegalArgumentException("commandHandlers must not be null"); //$NON-NLS-1$ } checkPrefix(core, PREFIX_CORE); checkPrefix(monitors, PREFIX_MONITOR); checkPrefix(locks, PREFIX_LOCK); checkPrefix(scheduler, PREFIX_SCHEDULER); checkPrefix(hadoopHandler, PREFIX_HADOOP); this.core = core; this.monitors = monitors; this.locks = locks; this.scheduler = scheduler; this.hadoopHandler = hadoopHandler; Map<String, ServiceProfile<CommandScriptHandler>> map = new TreeMap<>(); for (ServiceProfile<CommandScriptHandler> profile : commandHandlers) { if (profile.getPrefix().startsWith(GROUP_PREFIX_COMMAND) == false) { throw new IllegalArgumentException(MessageFormat.format( "Profile \"{1}\" is invalid, this must be \"{0}<profile-name>\" ({2})", GROUP_PREFIX_COMMAND, profile.getPrefix(), profile.getServiceClass().getName())); } String profileName = profile.getPrefix().substring(GROUP_PREFIX_COMMAND.length()); if (map.containsKey(profileName)) { throw new IllegalArgumentException(MessageFormat.format( "Profile \"{0}\" is duplicated ({1} <=> {2})", profileName, profile.getServiceClass().getName(), map.get(profileName).getServiceClass().getName())); } map.put(profileName, profile); } this.commandHandlers = Collections.unmodifiableMap(map); } private void checkPrefix(ServiceProfile<?> profile, String prefix) { assert profile != null; assert prefix != null; if (profile.getPrefix().equals(prefix) == false) { throw new IllegalArgumentException(MessageFormat.format( "Profile \"{1}\" is invalid, this must be \"{0}\" ({2})", prefix, profile.getPrefix(), profile.getServiceClass().getName())); } } /** * Loads a YAESS profile from the specified properties. * @param properties source properties * @param classLoader the class loader to load the service class * @return the loaded profile * @throws IllegalArgumentException if the target profile is invalid, or parameters contain {@code null} * @deprecated use {@link #load(Properties, ProfileContext)} instead */ @Deprecated public static YaessProfile load(Properties properties, ClassLoader classLoader) { if (properties == null) { throw new IllegalArgumentException("properties must not be null"); //$NON-NLS-1$ } if (classLoader == null) { throw new IllegalArgumentException("classLoader must not be null"); //$NON-NLS-1$ } return load(properties, ProfileContext.system(classLoader)); } /** * Loads a YAESS profile from the specified properties. * @param properties source properties * @param context the current profile context * @return the loaded profile * @throws IllegalArgumentException if the target profile is invalid, or parameters contain {@code null} * @since 0.2.4 */ public static YaessProfile load(Properties properties, ProfileContext context) { if (properties == null) { throw new IllegalArgumentException("properties must not be null"); //$NON-NLS-1$ } if (context == null) { throw new IllegalArgumentException("context must not be null"); //$NON-NLS-1$ } ServiceProfile<CoreProfile> core = ServiceProfile.load(properties, PREFIX_CORE, CoreProfile.class, context); ServiceProfile<ExecutionMonitorProvider> monitors = ServiceProfile.load(properties, PREFIX_MONITOR, ExecutionMonitorProvider.class, context); ServiceProfile<ExecutionLockProvider> locks = ServiceProfile.load(properties, PREFIX_LOCK, ExecutionLockProvider.class, context); ServiceProfile<JobScheduler> scheduler = ServiceProfile.load(properties, PREFIX_SCHEDULER, JobScheduler.class, context); ServiceProfile<HadoopScriptHandler> hadoopHandler = ServiceProfile.load(properties, PREFIX_HADOOP, HadoopScriptHandler.class, context); List<ServiceProfile<CommandScriptHandler>> commandHandlers = new ArrayList<>(); for (String commandHandlerPrefix : PropertiesUtil.getChildKeys(properties, GROUP_PREFIX_COMMAND, ".")) { ServiceProfile<CommandScriptHandler> profile = ServiceProfile.load(properties, commandHandlerPrefix, CommandScriptHandler.class, context); commandHandlers.add(profile); } return new YaessProfile(core, monitors, locks, scheduler, hadoopHandler, commandHandlers); } /** * Returns a core profile. * @return core profile */ public ServiceProfile<CoreProfile> getCore() { return core; } /** * Returns a monitor provider. * @return monitor provider */ public ServiceProfile<ExecutionMonitorProvider> getMonitors() { return monitors; } /** * Returns a lock provider. * @return lock provider */ public ServiceProfile<ExecutionLockProvider> getLocks() { return locks; } /** * Returns a job scheduler. * @return the scheduler */ public ServiceProfile<JobScheduler> getScheduler() { return scheduler; } /** * Returns a Hadoop script handler. * @return Hadoop script handler */ public ServiceProfile<HadoopScriptHandler> getHadoopHandler() { return hadoopHandler; } /** * Returns command script handlers for each target profile name. * @return the command script handlers */ public Map<String, ServiceProfile<CommandScriptHandler>> getCommandHandlers() { return commandHandlers; } }