Skip to content

Commit

Permalink
Decouple container module from core
Browse files Browse the repository at this point in the history
  • Loading branch information
elrodro83 committed May 28, 2024
1 parent bbc8c68 commit 165848e
Show file tree
Hide file tree
Showing 13 changed files with 305 additions and 37 deletions.
1 change: 0 additions & 1 deletion core/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,6 @@
spring.beans;
exports org.mule.runtime.core.internal.util to
org.mule.runtime.core.components,
org.mule.runtime.container,
org.mule.runtime.deployment.model,
org.mule.runtime.deployment.model.impl,
org.mule.runtime.log4j,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@ public class OrderedProperties extends Properties {
private final Vector<Object> keys = new Vector<>();

@Override
@SuppressWarnings("unchecked")
public Set<Map.Entry<Object, Object>> entrySet() {
Set<Map.Entry<Object, Object>> entries = new LinkedHashSet<>();
Enumeration<?> keys = this.propertyNames();

while (keys.hasMoreElements()) {
Object key = keys.nextElement();
entries.add(new DefaultMapEntry(key, this.getProperty((String) key)));
entries.add(new DefaultMapEntry<>(key, this.getProperty((String) key)));
}

return entries;
Expand Down
5 changes: 0 additions & 5 deletions modules/container/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,6 @@
</build>

<dependencies>
<dependency>
<groupId>org.mule.runtime</groupId>
<artifactId>mule-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.mule.runtime</groupId>
<artifactId>mule-module-artifact</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion modules/container/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
module org.mule.runtime.container {

requires org.mule.runtime.api;
requires org.mule.runtime.core;
requires org.mule.runtime.jar.handling.utils;
requires org.mule.runtime.artifact;
requires org.mule.runtime.jpms.utils;

requires org.apache.commons.collections4;
requires org.apache.commons.io;
requires org.apache.commons.lang3;
requires com.google.common;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
*/
package org.mule.runtime.container.api;

import static org.mule.runtime.container.internal.util.StandaloneServerUtils.getMuleBase;
import static org.mule.runtime.container.internal.util.StandaloneServerUtils.getMuleHome;

import static java.io.File.separator;
import static org.mule.runtime.api.util.Preconditions.checkArgument;
import static org.mule.runtime.core.internal.util.StandaloneServerUtils.getMuleBase;
import static org.mule.runtime.core.internal.util.StandaloneServerUtils.getMuleHome;
import org.mule.runtime.core.api.util.StringUtils;

import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.commons.lang3.StringUtils.isEmpty;

import java.io.File;

Expand Down Expand Up @@ -74,7 +76,7 @@ public static File getServicesFolder() {
* @return a {@link File} pointing to the folder that corresponds to the provided service name when installed.
*/
public static File getServiceFolder(String name) {
checkArgument(!StringUtils.isEmpty(name), "name cannot be empty");
checkArgument(!isEmpty(name), "name cannot be empty");
return new File(getServicesFolder(), name);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
*/
package org.mule.runtime.container.api;

import static org.mule.runtime.api.util.Preconditions.checkArgument;

import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableSet;

import org.mule.runtime.core.api.util.StringUtils;
import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.commons.lang3.StringUtils.isEmpty;

import org.mule.runtime.jpms.api.MuleContainerModule;
import org.mule.runtime.module.artifact.api.classloader.ExportedService;

Expand Down Expand Up @@ -44,7 +44,7 @@ public class MuleModule implements MuleContainerModule {
*/
public MuleModule(String name, Set<String> exportedPackages, Set<String> exportedPaths, Set<String> privilegedExportedPackages,
Set<String> privilegedArtifacts, List<ExportedService> exportedServices) {
checkArgument(!StringUtils.isEmpty(name), "name cannot be empty");
checkArgument(!isEmpty(name), "name cannot be empty");
checkArgument(exportedPackages != null, "exportedPackages cannot be null");
checkArgument(exportedPaths != null, "exportedPaths cannot be null");
checkArgument(!containsMetaInfServicesResource(exportedPaths), "exportedPaths cannot contain paths on META-INF/services");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,31 @@

import static org.mule.runtime.api.i18n.I18nMessageFactory.createStaticMessage;
import static org.mule.runtime.container.api.MuleFoldersUtil.getModulesTempFolder;
import static org.mule.runtime.core.api.util.FileUtils.stringToFile;
import static org.mule.runtime.core.api.util.PropertiesUtils.discoverProperties;

import static java.lang.String.format;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.Files.createTempFile;
import static java.util.Collections.emptyList;

import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.commons.io.FileUtils.cleanDirectory;
import static org.apache.commons.io.FileUtils.writeStringToFile;
import static org.apache.commons.lang3.StringUtils.isEmpty;

import org.mule.runtime.api.exception.MuleRuntimeException;
import org.mule.runtime.container.api.MuleModule;
import org.mule.runtime.core.api.util.func.CheckedSupplier;
import org.mule.runtime.container.internal.util.CheckedSupplier;
import org.mule.runtime.container.internal.util.OrderedProperties;
import org.mule.runtime.jpms.api.MuleContainerModule;
import org.mule.runtime.module.artifact.api.classloader.ExportedService;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -140,6 +145,46 @@ public List<MuleContainerModule> discover() {
return modules;
}

/**
* Discovers properties files available on the given classloader.
*
* @param classLoader classloader used to find properties resources. Not null.
* @param resource resource to find. Not empty
* @return a non null list of Properties
* @throws IOException when a property file cannot be processed
*/
private static List<Properties> discoverProperties(ClassLoader classLoader, String resource) throws IOException {
checkArgument(!isEmpty(resource), "Resource cannot be empty");
checkArgument(classLoader != null, "ClassLoader cannot be null");

List<Properties> result = new LinkedList<>();

Enumeration<URL> allPropertiesResources;
try {
allPropertiesResources = classLoader.getResources(resource);
} catch (IOException e) {
throw new IOException(format("Error getting resources '%s' from classLoader '%s'", resource, classLoader.toString()), e);
}

while (allPropertiesResources.hasMoreElements()) {
URL propertiesResource = allPropertiesResources.nextElement();
if (logger.isDebugEnabled()) {
logger.debug("Reading properties from: " + propertiesResource.toString());
}
Properties properties = new OrderedProperties();

try (InputStream resourceStream = new BufferedInputStream(propertiesResource.openStream())) {
properties.load(resourceStream);
} catch (IOException e) {
throw new IOException(format("Error loading properties from '%s'", propertiesResource.toString()), e);
}

result.add(properties);
}

return result;
}

protected String getModulePropertiesFileName() {
return modulePropertiesResource;
}
Expand Down Expand Up @@ -180,7 +225,7 @@ private List<ExportedService> getServicesFromProperty(String exportedPackagesPro
File serviceFile = serviceInterfaceToServiceFile.apply(serviceInterface);
serviceFile.deleteOnExit();

stringToFile(serviceFile.getAbsolutePath(), serviceImplementation);
writeStringToFile(serviceFile, serviceImplementation, UTF_8);
resource = fileToResource.apply(serviceInterface, serviceFile);
} catch (IOException e) {
throw new IllegalStateException(format("Error creating temporary service provider file for '%s'", serviceInterface), e);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2023 Salesforce, Inc. All rights reserved.
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.container.internal.util;

import org.mule.runtime.api.exception.MuleRuntimeException;

import java.util.function.Supplier;

/**
* A {@link Supplier} which can throw exceptions
*
* @param <T> the generic type of the return value
* @since 4.0
*/
@FunctionalInterface
public interface CheckedSupplier<T> extends Supplier<T> {

@Override
default T get() {
try {
return getChecked();
} catch (Throwable throwable) {
return handleException(throwable);
}
}

/**
* Handles the {@code throwable}
*
* @param throwable the error that was caught
*/
default T handleException(Throwable throwable) {
throw propagate(throwable);
}

/**
* Executes an unsafe operation
*
* @throws Exception if anything goes wrong
*/
T getChecked() throws Throwable;

public static RuntimeException propagate(Throwable t) {
if (t instanceof RuntimeException) {
return (RuntimeException) t;
} else {
return new MuleRuntimeException(t);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2023 Salesforce, Inc. All rights reserved.
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.container.internal.util;

import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Vector;

import org.apache.commons.collections4.keyvalue.DefaultMapEntry;

public class OrderedProperties extends Properties {

private static final long serialVersionUID = -3611415251568805458L;

private final Vector<Object> keys = new Vector<>();

@Override
public Set<Map.Entry<Object, Object>> entrySet() {
Set<Map.Entry<Object, Object>> entries = new LinkedHashSet<>();
Enumeration<?> keys = this.propertyNames();

while (keys.hasMoreElements()) {
Object key = keys.nextElement();
entries.add(new DefaultMapEntry<>(key, this.getProperty((String) key)));
}

return entries;
}

@Override
public Enumeration<?> propertyNames() {
return this.keys.elements();
}

@Override
public Object put(Object key, Object value) {
if (this.keys.contains(key)) {
this.keys.remove(key);
}

this.keys.add(key);

return super.put(key, value);
}

@Override
public Object remove(Object key) {
this.keys.remove(key);
return super.remove(key);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2023 Salesforce, Inc. All rights reserved.
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.container.internal.util;

import static java.util.Optional.of;
import static java.util.Optional.ofNullable;

import java.io.File;
import java.io.IOException;
import java.util.Optional;

/**
* Standalone server instance utility methods.
* <p>
* This utility methods are not meant to be used in container mode.
*
* @since 4.0
*/
public class StandaloneServerUtils {

public static final String MULE_HOME_DIRECTORY_PROPERTY = "mule.home";
public static final String MULE_BASE_DIRECTORY_PROPERTY = "mule.base";

/**
* @return the MULE_HOME directory of this instance. Returns null if the property is not set
*/
public static Optional<File> getMuleHome() {
final String muleHome = System.getProperty(MULE_HOME_DIRECTORY_PROPERTY);
return ofNullable(muleHome != null ? new File(muleHome) : null);
}

/**
* The mule runtime base folder is a directory similar to the mule runtime installation one but with only the specific
* configuration parts of the mule runtime installation such as the apps folder, the domain folder, the conf folder.
*
* @return the MULE_BASE directory of this instance. Returns the
* {@link org.mule.runtime.core.api.config.MuleProperties#MULE_HOME_DIRECTORY_PROPERTY} property value if
* {@link org.mule.runtime.core.api.config.MuleProperties#MULE_BASE_DIRECTORY_PROPERTY} is not set which may be null.
*/
public static Optional<File> getMuleBase() {
Optional<File> muleBase = null;
String muleBaseVar = System.getProperty(MULE_BASE_DIRECTORY_PROPERTY);

if (muleBaseVar != null && !muleBaseVar.trim().equals("") && !muleBaseVar.equals("%MULE_BASE%")) {
try {
muleBase = of(new File(muleBaseVar).getCanonicalFile());
} catch (IOException e) {
throw new RuntimeException(e);
}
}

if (muleBase == null) {
muleBase = getMuleHome();
}
return muleBase;
}

}
Loading

0 comments on commit 165848e

Please sign in to comment.