mirror of
https://github.com/corda/corda.git
synced 2025-05-30 22:24:22 +00:00
add support for Class-Path manifest attribute
This attribute, found in some JAR manifests, indicates additional JARs and/or directories to append to the classpath. Tomcat in particular uses it.
This commit is contained in:
parent
addaf09aa3
commit
d520514a87
170
src/finder.cpp
170
src/finder.cpp
@ -632,59 +632,139 @@ class BuiltinElement: public JarElement {
|
|||||||
const char* libraryName;
|
const char* libraryName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
add(Element** first, Element** last, Element* e)
|
||||||
|
{
|
||||||
|
if (*last) {
|
||||||
|
(*last)->next = e;
|
||||||
|
} else {
|
||||||
|
*first = e;
|
||||||
|
}
|
||||||
|
*last = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
baseName(const char* name, char fileSeparator)
|
||||||
|
{
|
||||||
|
const char* p = name;
|
||||||
|
const char* last = 0;
|
||||||
|
while (*p) {
|
||||||
|
if (*p == fileSeparator) {
|
||||||
|
last = p;
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return last ? (last + 1) - name : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add(System* s, Element** first, Element** last, Allocator* allocator,
|
||||||
|
const char* name, unsigned nameLength, const char* bootLibrary);
|
||||||
|
|
||||||
|
void
|
||||||
|
addJar(System* s, Element** first, Element** last, Allocator* allocator,
|
||||||
|
const char* name, const char* bootLibrary)
|
||||||
|
{
|
||||||
|
if (DebugFind) {
|
||||||
|
fprintf(stderr, "add jar %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
JarElement* e = new (allocator->allocate(sizeof(JarElement)))
|
||||||
|
JarElement(s, allocator, name);
|
||||||
|
|
||||||
|
add(first, last, e);
|
||||||
|
|
||||||
|
System::Region* region = e->find("META-INF/MANIFEST.MF");
|
||||||
|
if (region) {
|
||||||
|
unsigned start = 0;
|
||||||
|
unsigned length;
|
||||||
|
while (readLine(region->start(), region->length(), &start, &length)) {
|
||||||
|
const unsigned PrefixLength = 12;
|
||||||
|
if (strncmp("Class-Path: ", reinterpret_cast<const char*>
|
||||||
|
(region->start() + start), PrefixLength) == 0)
|
||||||
|
{
|
||||||
|
for (Tokenizer t(reinterpret_cast<const char*>
|
||||||
|
(region->start() + start + PrefixLength),
|
||||||
|
length - PrefixLength, ' ');
|
||||||
|
t.hasMore();)
|
||||||
|
{
|
||||||
|
Tokenizer::Token token(t.next());
|
||||||
|
|
||||||
|
unsigned base = baseName(name, s->fileSeparator());
|
||||||
|
|
||||||
|
RUNTIME_ARRAY(char, n, base + token.length + 1);
|
||||||
|
memcpy(RUNTIME_ARRAY_BODY(n), name, base);
|
||||||
|
memcpy(RUNTIME_ARRAY_BODY(n) + base, token.s, token.length);
|
||||||
|
RUNTIME_ARRAY_BODY(n)[base + token.length] = 0;
|
||||||
|
|
||||||
|
add(s, first, last, allocator, RUNTIME_ARRAY_BODY(n),
|
||||||
|
base + token.length, bootLibrary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
region->dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add(System* s, Element** first, Element** last, Allocator* allocator,
|
||||||
|
const char* token, unsigned tokenLength, const char* bootLibrary)
|
||||||
|
{
|
||||||
|
if (*token == '[' and token[tokenLength - 1] == ']') {
|
||||||
|
char* name = static_cast<char*>(allocator->allocate(tokenLength - 1));
|
||||||
|
memcpy(name, token + 1, tokenLength - 1);
|
||||||
|
name[tokenLength - 2] = 0;
|
||||||
|
|
||||||
|
if (DebugFind) {
|
||||||
|
fprintf(stderr, "add builtin %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
add(first, last, new (allocator->allocate(sizeof(BuiltinElement)))
|
||||||
|
BuiltinElement(s, allocator, name, bootLibrary));
|
||||||
|
} else {
|
||||||
|
char* name = static_cast<char*>(allocator->allocate(tokenLength + 1));
|
||||||
|
memcpy(name, token, tokenLength);
|
||||||
|
name[tokenLength] = 0;
|
||||||
|
|
||||||
|
unsigned length;
|
||||||
|
switch (s->stat(name, &length)) {
|
||||||
|
case System::TypeFile: {
|
||||||
|
addJar(s, first, last, allocator, name, bootLibrary);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case System::TypeDirectory: {
|
||||||
|
if (DebugFind) {
|
||||||
|
fprintf(stderr, "add directory %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
add(first, last, new (allocator->allocate(sizeof(DirectoryElement)))
|
||||||
|
DirectoryElement(s, allocator, name));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
if (DebugFind) {
|
||||||
|
fprintf(stderr, "ignore nonexistent %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
allocator->free(name, strlen(name) + 1);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Element*
|
Element*
|
||||||
parsePath(System* s, Allocator* allocator, const char* path,
|
parsePath(System* s, Allocator* allocator, const char* path,
|
||||||
const char* bootLibrary)
|
const char* bootLibrary)
|
||||||
{
|
{
|
||||||
Element* first = 0;
|
Element* first = 0;
|
||||||
Element* prev = 0;
|
Element* last = 0;
|
||||||
for (Tokenizer t(path, s->pathSeparator()); t.hasMore();) {
|
for (Tokenizer t(path, s->pathSeparator()); t.hasMore();) {
|
||||||
Tokenizer::Token token(t.next());
|
Tokenizer::Token token(t.next());
|
||||||
|
|
||||||
Element* e;
|
add(s, &first, &last, allocator, token.s, token.length, bootLibrary);
|
||||||
if (*token.s == '[' and token.s[token.length - 1] == ']') {
|
|
||||||
char* name = static_cast<char*>(allocator->allocate(token.length - 1));
|
|
||||||
memcpy(name, token.s + 1, token.length - 1);
|
|
||||||
name[token.length - 2] = 0;
|
|
||||||
|
|
||||||
e = new (allocator->allocate(sizeof(BuiltinElement)))
|
|
||||||
BuiltinElement(s, allocator, name, bootLibrary);
|
|
||||||
} else {
|
|
||||||
char* name = static_cast<char*>(allocator->allocate(token.length + 1));
|
|
||||||
memcpy(name, token.s, token.length);
|
|
||||||
name[token.length] = 0;
|
|
||||||
|
|
||||||
unsigned length;
|
|
||||||
switch (s->stat(name, &length)) {
|
|
||||||
case System::TypeFile: {
|
|
||||||
e = new (allocator->allocate(sizeof(JarElement)))
|
|
||||||
JarElement(s, allocator, name);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case System::TypeDirectory: {
|
|
||||||
e = new (allocator->allocate(sizeof(DirectoryElement)))
|
|
||||||
DirectoryElement(s, allocator, name);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default: {
|
|
||||||
allocator->free(name, strlen(name) + 1);
|
|
||||||
e = 0;
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DebugFind) {
|
|
||||||
fprintf(stderr, "add element %.*s %p\n", token.length, token.s, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e) {
|
|
||||||
if (prev) {
|
|
||||||
prev->next = e;
|
|
||||||
} else {
|
|
||||||
first = e;
|
|
||||||
}
|
|
||||||
prev = e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return first;
|
return first;
|
||||||
|
16
src/finder.h
16
src/finder.h
@ -17,6 +17,22 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
readLine(const uint8_t* base, unsigned total, unsigned* start,
|
||||||
|
unsigned* length)
|
||||||
|
{
|
||||||
|
const uint8_t* p = base + *start;
|
||||||
|
const uint8_t* end = base + total;
|
||||||
|
while (p != end and (*p == '\n' or *p == '\r')) ++ p;
|
||||||
|
|
||||||
|
*start = p - base;
|
||||||
|
while (p != end and not (*p == '\n' or *p == '\r')) ++ p;
|
||||||
|
|
||||||
|
*length = (p - base) - *start;
|
||||||
|
|
||||||
|
return *length != 0;
|
||||||
|
}
|
||||||
|
|
||||||
class Finder {
|
class Finder {
|
||||||
public:
|
public:
|
||||||
class IteratorImp {
|
class IteratorImp {
|
||||||
|
16
src/main.cpp
16
src/main.cpp
@ -74,22 +74,6 @@ vmNativeCall(void*, void*, unsigned, unsigned)
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool
|
|
||||||
readLine(const uint8_t* base, unsigned total, unsigned* start,
|
|
||||||
unsigned* length)
|
|
||||||
{
|
|
||||||
const uint8_t* p = base + *start;
|
|
||||||
const uint8_t* end = base + total;
|
|
||||||
while (p != end and (*p == '\n' or *p == '\r')) ++ p;
|
|
||||||
|
|
||||||
*start = p - base;
|
|
||||||
while (p != end and not (*p == '\n' or *p == '\r')) ++ p;
|
|
||||||
|
|
||||||
*length = (p - base) - *start;
|
|
||||||
|
|
||||||
return *length != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
mainClass(const char* jar)
|
mainClass(const char* jar)
|
||||||
{
|
{
|
||||||
|
@ -23,20 +23,27 @@ class Tokenizer {
|
|||||||
unsigned length;
|
unsigned length;
|
||||||
};
|
};
|
||||||
|
|
||||||
Tokenizer(const char* s, char delimiter): s(s), delimiter(delimiter) { }
|
Tokenizer(const char* s, char delimiter):
|
||||||
|
s(s), limit(0), delimiter(delimiter)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Tokenizer(const char* s, unsigned length, char delimiter):
|
||||||
|
s(s), limit(s + length), delimiter(delimiter)
|
||||||
|
{ }
|
||||||
|
|
||||||
bool hasMore() {
|
bool hasMore() {
|
||||||
while (*s == delimiter) ++s;
|
while (*s == delimiter and s != limit) ++s;
|
||||||
return *s != 0;
|
return *s != 0 and s != limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token next() {
|
Token next() {
|
||||||
const char* p = s;
|
const char* p = s;
|
||||||
while (*s and *s != delimiter) ++s;
|
while (*s and *s != delimiter and s != limit) ++s;
|
||||||
return Token(p, s - p);
|
return Token(p, s - p);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* s;
|
const char* s;
|
||||||
|
const char* limit;
|
||||||
char delimiter;
|
char delimiter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user