CCM NG: Some cleanup
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3589 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
fb1ecd04b0
commit
98d1f02f21
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.libreccm.modules;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public interface ModuleDescriptor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the {@link ModuleManager} after the database tables for the
|
|
||||||
* module have been created. Use this method to create initial or example
|
|
||||||
* data.
|
|
||||||
*/
|
|
||||||
void prepare();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the {@link ModuleManager} when a module is removed from the
|
|
||||||
* installation. If necessary clean up the data of the module in the
|
|
||||||
* implementation of this method.
|
|
||||||
*/
|
|
||||||
void uninstall();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called each time the CCM application is started. Use an implementation of
|
|
||||||
* this method for creating static instances or for integrity checking.
|
|
||||||
*/
|
|
||||||
void init();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called each time the CCM application stops.
|
|
||||||
*/
|
|
||||||
void shutdown();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.libreccm.modules;
|
|
||||||
|
|
||||||
import com.arsdigita.runtime.RegistryConfig;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.enterprise.context.ApplicationScoped;
|
|
||||||
import javax.enterprise.inject.Instance;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@ApplicationScoped
|
|
||||||
public class ModuleManager {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private transient Instance<ModuleDescriptor> modules;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks for new or upgraded modules and executes database migrations if
|
|
||||||
* necessary. If a new module is installed the database tables for this
|
|
||||||
* module are generated first. After that the {@code prepare()} method of
|
|
||||||
* the module is called (see {@link ModuleDescriptor#prepare()}).
|
|
||||||
*/
|
|
||||||
public void loadModules() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a module is already installed.
|
|
||||||
*
|
|
||||||
* @param moduleDescriptor The descriptor of the module.
|
|
||||||
*
|
|
||||||
* @return {@code true} if the module is already installed, {@code false}
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
private boolean isInstalled(final ModuleDescriptor moduleDescriptor) {
|
|
||||||
final RegistryConfig registryConfig = new RegistryConfig();
|
|
||||||
registryConfig.load();
|
|
||||||
final String[] packages = registryConfig.getPackages();
|
|
||||||
final List<String> packageList = Arrays.asList(packages);
|
|
||||||
|
|
||||||
return packageList.contains(ModuleUtil.getModuleName(moduleDescriptor));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to uninstall a module. First the {@code uninstal()} method of the
|
|
||||||
* module is called (see {@link ModuleDescriptor#uninstall()}). After that
|
|
||||||
* the database tables of the module are removed.
|
|
||||||
*
|
|
||||||
* @param module The module to uninstall.
|
|
||||||
*/
|
|
||||||
public void uninstallModule(final ModuleDescriptor module) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialises all modules by calling their {@code init()} method (see
|
|
||||||
* {@link ModuleDescriptor#init()}.
|
|
||||||
*/
|
|
||||||
public void initModules() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shutdown all modules by calling their {@link shutdown()} method (see
|
|
||||||
* {@link ModuleDescriptor#shutdown()}).
|
|
||||||
*/
|
|
||||||
public void shutdownModules() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.libreccm.modules;
|
|
||||||
|
|
||||||
import org.libreccm.modules.annotations.Module;
|
|
||||||
import org.libreccm.modules.annotations.RequiredModule;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public final class ModuleUtil {
|
|
||||||
|
|
||||||
private ModuleUtil() {
|
|
||||||
//Nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Module getModuleAnnotation(
|
|
||||||
final ModuleDescriptor module) {
|
|
||||||
final Module annotation = module.getClass().getAnnotation(Module.class);
|
|
||||||
|
|
||||||
if (annotation == null) {
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"The provided implementation of the "
|
|
||||||
+ "org.libreccm.modules.Module interface, \"%s\", is not"
|
|
||||||
+ "annotated with org.libreccm.modules.annotations.Module",
|
|
||||||
module.getClass().getName()));
|
|
||||||
} else {
|
|
||||||
return annotation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getModuleName(final ModuleDescriptor module) {
|
|
||||||
return getModuleAnnotation(module).name();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getVersion(final ModuleDescriptor module) {
|
|
||||||
return getModuleAnnotation(module).version();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RequiredModule[] getRequiredModules(final ModuleDescriptor module) {
|
|
||||||
return getModuleAnnotation(module).requiredModules();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getModuleName(
|
|
||||||
final Class<? extends ModuleDescriptor> module) {
|
|
||||||
|
|
||||||
final Module annotation = module.getAnnotation(Module.class);
|
|
||||||
|
|
||||||
if (annotation == null) {
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"The provided implementation of the "
|
|
||||||
+ "org.libreccm.modules.Module interface, \"%s\", is not"
|
|
||||||
+ "annotated with org.libreccm.modules.annotations.Module",
|
|
||||||
module.getClass().getName()));
|
|
||||||
} else {
|
|
||||||
return annotation.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.libreccm.modules.annotations;
|
|
||||||
|
|
||||||
import org.libreccm.modules.ModuleDescriptor;
|
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import javax.enterprise.util.Nonbinding;
|
|
||||||
import javax.inject.Qualifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotate an implementation of the {@link ModuleDescriptor} interface with
|
|
||||||
* this annotation to use it as a module.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
@Target({METHOD, FIELD, PARAMETER, TYPE})
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Qualifier
|
|
||||||
public @interface Module {
|
|
||||||
|
|
||||||
@Nonbinding String name() default "";
|
|
||||||
|
|
||||||
@Nonbinding String version() default "";
|
|
||||||
|
|
||||||
@Nonbinding RequiredModule[] requiredModules() default {};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.libreccm.modules.annotations;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public @interface RequiredModule {
|
|
||||||
|
|
||||||
Class<? extends org.libreccm.modules.ModuleDescriptor> module();
|
|
||||||
|
|
||||||
String minVersion() default "";
|
|
||||||
|
|
||||||
String maxVersion() default "";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.libreccm.modules.dependencytree;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class DependencyException extends Exception {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance of <code>DependencyException</code> without detail message.
|
|
||||||
*/
|
|
||||||
public DependencyException() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an instance of <code>DependencyException</code> with the specified detail message.
|
|
||||||
*
|
|
||||||
* @param msg The detail message.
|
|
||||||
*/
|
|
||||||
public DependencyException(final String msg) {
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an instance of <code>DependencyException</code> which wraps the
|
|
||||||
* specified exception.
|
|
||||||
*
|
|
||||||
* @param exception The exception to wrap.
|
|
||||||
*/
|
|
||||||
public DependencyException(final Exception exception) {
|
|
||||||
super(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an instance of <code>DependencyException</code> with the specified message which also wraps the
|
|
||||||
* specified exception.
|
|
||||||
*
|
|
||||||
* @param msg The detail message.
|
|
||||||
* @param exception The exception to wrap.
|
|
||||||
*/
|
|
||||||
public DependencyException(final String msg, final Exception exception) {
|
|
||||||
super(msg, exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,268 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.libreccm.modules.dependencytree;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.apache.maven.artifact.versioning.ComparableVersion;
|
|
||||||
import org.libreccm.modules.ModuleDescriptor;
|
|
||||||
import org.libreccm.modules.ModuleUtil;
|
|
||||||
import org.libreccm.modules.annotations.RequiredModule;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.enterprise.inject.Instance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements topological sorting to determine the order in which the
|
|
||||||
* modules are loaded and initialised.
|
|
||||||
*
|
|
||||||
* The class is used by creating an instance with the parameterless constructor.
|
|
||||||
* To create the tree/graph call the
|
|
||||||
* {@link #generateTree(javax.enterprise.inject.Instance)} method. With the
|
|
||||||
* returned list of nodes call the the {@link #orderModules(java.util.List)}
|
|
||||||
* method. The list returned by {@link #orderModules(java.util.List)} contains
|
|
||||||
* all modules in order.
|
|
||||||
*
|
|
||||||
* More information about topological sorting:
|
|
||||||
* <a href="https://en.wikipedia.org/wiki/Topological_sorting">https://en.wikipedia.org/wiki/Topological_sorting</a>
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class DependencyTreeManager {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
|
||||||
DependencyTreeManager.class);
|
|
||||||
|
|
||||||
public List<TreeNode> generateTree(final Instance<ModuleDescriptor> modules)
|
|
||||||
throws DependencyException {
|
|
||||||
|
|
||||||
LOGGER.info("Starting to generate dependency tree...");
|
|
||||||
|
|
||||||
final Map<String, TreeNode> nodes = new HashMap<>();
|
|
||||||
|
|
||||||
for (final ModuleDescriptor module : modules) {
|
|
||||||
createTreeNode(module, nodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final ModuleDescriptor module : modules) {
|
|
||||||
addDependencyRelations(module, nodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<TreeNode> nodeList = new ArrayList<>();
|
|
||||||
for (final Map.Entry<String, TreeNode> entry : nodes.entrySet()) {
|
|
||||||
nodeList.add(entry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.info("Dependency tree generated.");
|
|
||||||
|
|
||||||
return nodeList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TreeNode> orderModules(final List<TreeNode> dependencyTree)
|
|
||||||
throws DependencyException {
|
|
||||||
LOGGER.info("Creating an ordered list from the dependency tree...");
|
|
||||||
|
|
||||||
final List<TreeNode> orderedModules = new ArrayList<>();
|
|
||||||
final List<TreeNode> resolvedModules = new ArrayList<>();
|
|
||||||
|
|
||||||
LOGGER.info("Looking for modules which do not depend on any other "
|
|
||||||
+ "modules...");
|
|
||||||
for (final TreeNode node : dependencyTree) {
|
|
||||||
if (node.getDependsOn().isEmpty()) {
|
|
||||||
LOGGER.info(
|
|
||||||
"\tModule \"{}\" does not depend on any other module",
|
|
||||||
ModuleUtil.getModuleName(node.getModule()));
|
|
||||||
resolvedModules.add(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.info("Ordering remaining nodes...");
|
|
||||||
while (!resolvedModules.isEmpty()) {
|
|
||||||
|
|
||||||
final TreeNode current = resolvedModules.remove(0);
|
|
||||||
LOGGER.info("\tProcessing node for module \"{}\"...",
|
|
||||||
ModuleUtil.getModuleName(current.getModule()));
|
|
||||||
|
|
||||||
orderedModules.add(current);
|
|
||||||
|
|
||||||
for (final TreeNode dependent : current.getDependentModules()) {
|
|
||||||
dependent.removeDependsOn(current);
|
|
||||||
|
|
||||||
if (dependent.getDependsOn().isEmpty()) {
|
|
||||||
resolvedModules.add(dependent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (orderedModules.size() == dependencyTree.size()) {
|
|
||||||
LOGGER.info("Dependency graph proceessed successfully. "
|
|
||||||
+ "Modules in order:");
|
|
||||||
for (final TreeNode node : orderedModules) {
|
|
||||||
LOGGER.info("\t{}", ModuleUtil.getModuleName(node.getModule()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return orderedModules;
|
|
||||||
} else {
|
|
||||||
LOGGER.fatal("The dependency graph has a least one cycle.");
|
|
||||||
throw new DependencyException(
|
|
||||||
"The dependency graph has a least one cycle.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createTreeNode(final ModuleDescriptor module,
|
|
||||||
final Map<String, TreeNode> nodes) {
|
|
||||||
final TreeNode node = new TreeNode(module);
|
|
||||||
|
|
||||||
LOGGER.info("Creating node for module \"{}\"...",
|
|
||||||
ModuleUtil.getModuleName(module));
|
|
||||||
nodes.put(ModuleUtil.getModuleName(module), node);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addDependencyRelations(final ModuleDescriptor module,
|
|
||||||
final Map<String, TreeNode> nodes)
|
|
||||||
throws DependencyException {
|
|
||||||
|
|
||||||
LOGGER.info("Adding dependency relations for module \"{}\"...",
|
|
||||||
ModuleUtil.getModuleName(module));
|
|
||||||
|
|
||||||
final String moduleName = ModuleUtil.getModuleName(module);
|
|
||||||
|
|
||||||
if (!nodes.containsKey(moduleName)) {
|
|
||||||
LOGGER.fatal("Modules nodes map does contain an entry for \"{}\". "
|
|
||||||
+ "That should not happen.",
|
|
||||||
ModuleUtil.getModuleName(module));
|
|
||||||
throw new IllegalArgumentException(String.format(
|
|
||||||
"The nodes map does not contain a node for module \"%s\". "
|
|
||||||
+ "That should not happen.",
|
|
||||||
moduleName));
|
|
||||||
}
|
|
||||||
|
|
||||||
final TreeNode node = nodes.get(moduleName);
|
|
||||||
LOGGER.info("Processing required modules for module \"{}\"...",
|
|
||||||
ModuleUtil.getModuleName(module));
|
|
||||||
for (final RequiredModule requiredModule : ModuleUtil
|
|
||||||
.getRequiredModules(
|
|
||||||
module)) {
|
|
||||||
|
|
||||||
LOGGER.info("\tModule \"{}\" requires module \"{}\".",
|
|
||||||
ModuleUtil.getModuleName(module),
|
|
||||||
ModuleUtil.getModuleName(requiredModule.module()));
|
|
||||||
|
|
||||||
if (!nodes.containsKey(ModuleUtil.getModuleName(requiredModule
|
|
||||||
.module()))) {
|
|
||||||
|
|
||||||
LOGGER.fatal("Required module \"{}\" no found.",
|
|
||||||
ModuleUtil.getModuleName(requiredModule.module()));
|
|
||||||
|
|
||||||
throw new DependencyException(String.format(
|
|
||||||
"Module \"%s\" depends on module \"%s\" but the dependency "
|
|
||||||
+ "tree does contain an entry for module \"%s\".",
|
|
||||||
ModuleUtil.getModuleName(module),
|
|
||||||
ModuleUtil.getModuleName(requiredModule.module()),
|
|
||||||
ModuleUtil.getModuleName(requiredModule.module())));
|
|
||||||
}
|
|
||||||
|
|
||||||
final TreeNode dependencyNode = nodes.get(ModuleUtil.getModuleName(
|
|
||||||
requiredModule.module()));
|
|
||||||
|
|
||||||
//Check version
|
|
||||||
if (!validateVersion(ModuleUtil.getVersion(dependencyNode
|
|
||||||
.getModule()),
|
|
||||||
requiredModule.minVersion(),
|
|
||||||
requiredModule.maxVersion())) {
|
|
||||||
throw new DependencyException(String.format(
|
|
||||||
"The required module is avialable but in the correct "
|
|
||||||
+ "version. "
|
|
||||||
+ "Available version: \"%s\"; "
|
|
||||||
+ "minimal required version: \"%s\"; "
|
|
||||||
+ "maximum required version: \"%s\"",
|
|
||||||
ModuleUtil.getVersion(dependencyNode.getModule()),
|
|
||||||
requiredModule.minVersion(),
|
|
||||||
requiredModule.maxVersion()));
|
|
||||||
}
|
|
||||||
|
|
||||||
node.addDependsOn(dependencyNode);
|
|
||||||
dependencyNode.addDependentModule(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method for checking if an dependency is available in the required
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
* @param availableVersion The available version. Can't be {@code null} or
|
|
||||||
* empty.
|
|
||||||
* @param minRequiredVersion The minimal version required. Can be
|
|
||||||
* {@code null} or empty.
|
|
||||||
* @param maxRequiredVersion The maximum version required. Can be
|
|
||||||
* {@code null} or empty.
|
|
||||||
*
|
|
||||||
* @return {@code true} if the available version is in the required range,
|
|
||||||
* {@code false} if not.
|
|
||||||
*/
|
|
||||||
//The names are fine. Shorter names would be less readable. Also removing
|
|
||||||
//the parentheses in the ifs would make the conditions less readable.
|
|
||||||
@SuppressWarnings({"PMD.LongVariable",
|
|
||||||
"PMD.UselessParentheses",
|
|
||||||
"PMD.CyclomaticComplexity"})
|
|
||||||
private boolean validateVersion(final String availableVersion,
|
|
||||||
final String minRequiredVersion,
|
|
||||||
final String maxRequiredVersion) {
|
|
||||||
if (availableVersion == null || availableVersion.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("No available version specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((minRequiredVersion == null || minRequiredVersion.isEmpty())
|
|
||||||
&& (maxRequiredVersion == null || maxRequiredVersion.isEmpty())) {
|
|
||||||
return true;
|
|
||||||
} else if ((minRequiredVersion != null && !minRequiredVersion.isEmpty())
|
|
||||||
&& (maxRequiredVersion == null || maxRequiredVersion
|
|
||||||
.isEmpty())) {
|
|
||||||
final ComparableVersion minVersion = new ComparableVersion(
|
|
||||||
minRequiredVersion);
|
|
||||||
final ComparableVersion version = new ComparableVersion(
|
|
||||||
availableVersion);
|
|
||||||
|
|
||||||
return minVersion.compareTo(version) <= 0;
|
|
||||||
} else if ((minRequiredVersion == null || minRequiredVersion.isEmpty())
|
|
||||||
&& (maxRequiredVersion != null && !maxRequiredVersion
|
|
||||||
.isEmpty())) {
|
|
||||||
final ComparableVersion maxVersion = new ComparableVersion(
|
|
||||||
maxRequiredVersion);
|
|
||||||
final ComparableVersion version = new ComparableVersion(
|
|
||||||
availableVersion);
|
|
||||||
|
|
||||||
return version.compareTo(maxVersion) <= 0;
|
|
||||||
} else {
|
|
||||||
final ComparableVersion minVersion = new ComparableVersion(
|
|
||||||
minRequiredVersion);
|
|
||||||
final ComparableVersion maxVersion = new ComparableVersion(
|
|
||||||
(maxRequiredVersion));
|
|
||||||
final ComparableVersion version = new ComparableVersion(
|
|
||||||
availableVersion);
|
|
||||||
return minVersion.compareTo(version) <= 0 && version.compareTo(
|
|
||||||
maxVersion) <= 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.libreccm.modules.dependencytree;
|
|
||||||
|
|
||||||
import org.libreccm.modules.ModuleDescriptor;
|
|
||||||
import org.libreccm.modules.ModuleUtil;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a node in the dependency tree.
|
|
||||||
*
|
|
||||||
* @see DependencyTreeManager
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public final class TreeNode {
|
|
||||||
|
|
||||||
private ModuleDescriptor module;
|
|
||||||
private List<TreeNode> dependentModules;
|
|
||||||
private List<TreeNode> dependsOn;
|
|
||||||
|
|
||||||
public TreeNode() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
dependentModules = new ArrayList<>();
|
|
||||||
dependsOn = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TreeNode(final ModuleDescriptor module) {
|
|
||||||
this();
|
|
||||||
|
|
||||||
this.module = module;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModuleDescriptor getModule() {
|
|
||||||
return module;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setModule(final ModuleDescriptor module) {
|
|
||||||
this.module = module;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TreeNode> getDependentModules() {
|
|
||||||
return Collections.unmodifiableList(dependentModules);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDependentModules(final List<TreeNode> dependentModules) {
|
|
||||||
this.dependentModules = dependentModules;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addDependentModule(final TreeNode node) {
|
|
||||||
dependentModules.add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeDependentModule(final TreeNode node) {
|
|
||||||
dependentModules.remove(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TreeNode> getDependsOn() {
|
|
||||||
return Collections.unmodifiableList(dependsOn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDependsOn(final List<TreeNode> dependsOn) {
|
|
||||||
this.dependsOn = dependsOn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addDependsOn(final TreeNode node) {
|
|
||||||
dependsOn.add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeDependsOn(final TreeNode node) {
|
|
||||||
dependsOn.remove(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int hash = 5;
|
|
||||||
|
|
||||||
final String moduleName = ModuleUtil.getModuleName(module);
|
|
||||||
final String version = ModuleUtil.getVersion(module);
|
|
||||||
|
|
||||||
hash = 37 * hash + Objects.hashCode(moduleName);
|
|
||||||
hash = 37 * hash + Objects.hashCode(version);
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object object) {
|
|
||||||
if (object == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(object instanceof TreeNode)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final TreeNode other = (TreeNode) object;
|
|
||||||
final String name = ModuleUtil.getModuleName(module);
|
|
||||||
final String otherName = ModuleUtil.getModuleName(other.getModule());
|
|
||||||
|
|
||||||
if (!name.equals(otherName)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String version = ModuleUtil.getVersion(module);
|
|
||||||
final String otherVersion = ModuleUtil.getVersion(other.getModule());
|
|
||||||
|
|
||||||
return version.equals(otherVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue