Skip to content

Commit

Permalink
improve OSGi bundle loading (reduce file access)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeloffner committed Oct 23, 2023
1 parent a24574f commit 63b74fe
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 42 deletions.
32 changes: 19 additions & 13 deletions core/src/main/java/lucee/commons/io/res/util/ResourceUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -816,9 +816,14 @@ public static String getMimeType(Resource res, String fileName, String defaultVa
* @return is inside or not
*/
public static boolean isChildOf(Resource file, Resource dir) {
while (file != null) {
if (file.equals(dir)) return true;
file = file.getParentResource();
if (dir == null || !file.getResourceProvider().getScheme().equals(dir.getResourceProvider().getScheme())) return false;
//
if ((file.getAbsolutePath()).startsWith(dir.getAbsolutePath())) {
return true;
}

if ((getCanonicalPathEL(file)).startsWith(getCanonicalPathEL(dir))) {
return true;
}
return false;
}
Expand All @@ -829,18 +834,19 @@ public static boolean isChildOf(Resource file, Resource dir) {
* @param file file to search
* @param dir directory to search
*/
public static String getPathToChild(Resource file, Resource dir) {
public static String getPathToChild(Resource file, final Resource dir) {
if (dir == null || !file.getResourceProvider().getScheme().equals(dir.getResourceProvider().getScheme())) return null;
boolean isFile = file.isFile();
String str = "/";
while (file != null) {
if (file.equals(dir)) {
if (isFile) return str.substring(0, str.length() - 1);
return str;
}
str = "/" + file.getName() + str;
file = file.getParentResource();

String strFile, strDir;
//
if ((strFile = file.getAbsolutePath()).startsWith(strDir = dir.getAbsolutePath())) {
return strFile.substring(strDir.length());
}

if ((strFile = getCanonicalPathEL(file)).startsWith(strDir = getCanonicalPathEL(dir))) {
return strFile.substring(strDir.length());
}

return null;
}

Expand Down
135 changes: 108 additions & 27 deletions core/src/main/java/lucee/runtime/osgi/OSGiUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -81,7 +82,7 @@
import lucee.runtime.type.util.ListUtil;

public class OSGiUtil {

private static boolean[] checkBundleRanges = new boolean[] { true, false };
private static final int QUALIFIER_APPENDIX_SNAPSHOT = 1;
private static final int QUALIFIER_APPENDIX_BETA = 2;
private static final int QUALIFIER_APPENDIX_RC = 3;
Expand All @@ -99,6 +100,12 @@ protected Set<String> initialValue() {

private static class Filter implements FilenameFilter, ResourceNameFilter {

private BundleRange bundleRange;

public Filter(BundleRange bundleRange) {
this.bundleRange = bundleRange;
}

@Override
public boolean accept(File dir, String name) {
return accept(name);
Expand All @@ -110,11 +117,22 @@ public boolean accept(Resource dir, String name) {
}

private boolean accept(String name) {
return name.endsWith(".jar");
if (!name.endsWith(".jar")) return false;
if (bundleRange == null) return true;
Version v;
String[] patterns = new String[] { bundleRange.getName() + "-", bundleRange.getName().replace('.', '-') + "-", bundleRange.getName().replace('-', '.') + "-" };
for (String pattern: patterns) {
if (name.startsWith(pattern)) {
v = toVersion(name.substring(pattern.length(), name.length() - 4), null);
if (v != null) return true;
}
}

return false;
}
}

private static final Filter JAR_EXT_FILTER = new Filter();
private static final Filter JAR_EXT_FILTER = new Filter(null);

private static String[] bootDelegation;
private static Map<String, String> packageBundleMapping = new LinkedHashMap<String, String>();
Expand Down Expand Up @@ -751,13 +769,18 @@ public static Bundle _loadBundle(final BundleRange bundleRange, Identification i
if (bundleRange.getVersionRange() != null && !bundleRange.getVersionRange().isEmpty()) {
// TODO not only check for from version, request a range, but that needs an adjustment with the
// provider
BundleFile _bf = BundleFile.getInstance(factory.downloadBundle(bundleRange.getName(), bundleRange.getVersionRange().getFrom().getVersion().toString(), id));
BundleFile _bf = improveFileName(
BundleFile.getInstance(factory.downloadBundle(bundleRange.getName(), bundleRange.getVersionRange().getFrom().getVersion().toString(), id)));
resetJarsFromBundleDirectory(factory);
b = _loadBundle(bc, _bf);
}
else {
// MUST find out why this breaks at startup with commandbox if version exists
Resource r = downloadBundle(factory, bundleRange.getName(), null, id);
BundleFile src = BundleFile.getInstance(r);
BundleFile trg = improveFileName(src);
if (src != trg) r = ResourceUtil.toResource(trg.getFile());

resetJarsFromBundleDirectory(factory);
b = _loadBundle(bc, r);
}
Expand Down Expand Up @@ -835,9 +858,11 @@ private static Resource downloadBundle(CFMLEngineFactory factory, final String s
throw re;
}
}

// print.e("xxxxxxxxxxxxxxxxxxxxxxx");
// print.e(symbolicName + ":" + symbolicVersion);
final Resource jarDir = ResourceUtil.toResource(factory.getBundleDirectory());
final URL updateProvider = factory.getUpdateLocation();

if (symbolicVersion == null) symbolicVersion = "latest";
final URL updateUrl = new URL(updateProvider, "/rest/update/provider/download/" + symbolicName + "/" + symbolicVersion + "/" + (id != null ? id.toQueryString() : "")
+ (id == null ? "?" : "&") + "allowRedirect=true"
Expand Down Expand Up @@ -1078,7 +1103,7 @@ private static BundleFile _getBundleFile(CFMLEngineFactory factory, BundleRange
BundleFile mbf = null;
Resource dir = ResourceUtil.toResource(factory.getBundleDirectory());
// first we check if there is a file match (fastest solution)
List<Resource> jars = createPossibleNameMatches(dir, addional, bundleRange.getName());
List<Resource> jars = createPossibleNameMatches(dir, addional, bundleRange);
for (Resource jar: jars) {
if (jar.isFile()) {
match = jar;
Expand All @@ -1088,30 +1113,41 @@ private static BundleFile _getBundleFile(CFMLEngineFactory factory, BundleRange
}
}
}
if (mbf != null) return mbf;

if (mbf != null) {
return improveFileName(mbf);
}
List<Resource> children = listFiles(dir, addional, JAR_EXT_FILTER);

// now we check by Manifest comparsion, name not necessary reflect the correct bundle info
BundleFile bf;
for (Resource child: children) {
match = child;
bf = BundleFile.getInstance(child);
if (bf.isBundle()) {
if (bf.getSymbolicName().equals(bundleRange.getName())) {
if (bundleRange.matches(bf)) {
if (mbf == null || OSGiUtil.isNewerThan(bf.getVersion(), mbf.getVersion())) mbf = bf;
}
else {
if (versionsFound != null) {
if (versionsFound.length() > 0) versionsFound.append(", ");
versionsFound.append(bf.getVersionAsString());
// now we check all jar files
{

// now we check by Manifest comparsion, name not necessary reflect the correct bundle info
BundleFile bf;
for (boolean checkBundleRange: checkBundleRanges) {
mbf = null;
for (Resource child: children) {
if (checkBundleRange && !new Filter(bundleRange).accept(child.getName())) continue;
match = child;
bf = BundleFile.getInstance(child);
if (bf.isBundle()) {
if (bf.getSymbolicName().equals(bundleRange.getName())) {
if (bundleRange.matches(bf)) {
if (mbf == null || OSGiUtil.isNewerThan(bf.getVersion(), mbf.getVersion())) mbf = bf;
}
else {
if (versionsFound != null) {
if (versionsFound.length() > 0) versionsFound.append(", ");
versionsFound.append(bf.getVersionAsString());
}
}
}
}
}
if (mbf != null) {
return improveFileName(mbf);
}
}
}
if (mbf != null) return mbf;

}
catch (Exception e) {
Expand All @@ -1137,15 +1173,60 @@ private static BundleFile _getBundleFile(CFMLEngineFactory factory, BundleRange
return null;
}

private static List<Resource> createPossibleNameMatches(Resource dir, List<Resource> addional, String name) {
String[] patterns = new String[] { name + "-", name.replace('.', '-'), name.replace('-', '.') };
/**
* rename file to match the Manifest information
*
* @param bf
*/
private static BundleFile improveFileName(BundleFile bf) {
File f = bf.getFile();
String preferedName = bf.getSymbolicName() + "-" + bf.getVersionAsString() + ".jar";
if (!preferedName.equals(f.getName())) {
try {
File nf = new File(f.getParentFile(), preferedName);

if (f.renameTo(nf)) {
return BundleFile.getInstance(nf);
}
else {
IOUtil.copy(new FileInputStream(f), new FileOutputStream(nf), true, true);
if (!f.delete()) {
f.deleteOnExit();
}
else {
return BundleFile.getInstance(nf);
}
}
}
catch (Exception e) {
LogUtil.log("OSGi", e);
}
}
return bf;
}

private static List<Resource> createPossibleNameMatches(Resource dir, List<Resource> addional, BundleRange bundleRange) {
List<Resource> resources = new ArrayList<Resource>();
for (String pattern: patterns) {
resources.add(dir.getRealResource(pattern));

// do we have a from match
VersionRange vr = bundleRange.getVersionRange();
if (vr != null) {
VersionDefinition from = vr.getFrom();
if (from != null && from.op == VersionDefinition.EQ || from.op == VersionDefinition.GTE) {
String name = bundleRange.getName();
String[] patterns = new String[] { name + "-" + from.version + ".jar", name.replace('.', '-') + "-" + (from.version.toString().replace('.', '-')) + ".jar",
name.replace('-', '.') + "-" + from.version + ".jar" };

for (String pattern: patterns) {
resources.add(dir.getRealResource(pattern));
}
}
}

if (addional != null && !addional.isEmpty()) {
String name = bundleRange.getName();
String[] patterns = new String[] { name + "-", name.replace('.', '-'), name.replace('-', '.') };

Iterator<Resource> it = addional.iterator();
Resource res;
while (it.hasNext()) {
Expand Down
2 changes: 1 addition & 1 deletion loader/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<project default="core" basedir="." name="Lucee"
xmlns:resolver="antlib:org.apache.maven.resolver.ant">

<property name="version" value="6.0.1.4-SNAPSHOT"/>
<property name="version" value="6.0.1.5-SNAPSHOT"/>

<taskdef uri="antlib:org.apache.maven.resolver.ant" resource="org/apache/maven/resolver/ant/antlib.xml">
<classpath>
Expand Down
2 changes: 1 addition & 1 deletion loader/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.lucee</groupId>
<artifactId>lucee</artifactId>
<version>6.0.1.4-SNAPSHOT</version>
<version>6.0.1.5-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Lucee Loader Build</name>
Expand Down

0 comments on commit 63b74fe

Please sign in to comment.