-
Notifications
You must be signed in to change notification settings - Fork 2
/
Bundle.h
154 lines (131 loc) · 3.75 KB
/
Bundle.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#pragma once
#include "macros.h"
#include "Manifest.h"
/**
Allows to query for a file.
TODO: add enum/find/iterate method with visitor
@author_philk
*/
struct IFileLocator {
/**
@param path [in] to the file to load as a stream.
*/
virtual IStream* createStream(LPCTSTR path) = 0;
};
/**
Implementation that will locate files inside a JAR/Zip archiv.
@author_philk
*/
class JarFileLocator : public IFileLocator {
public:
JarFileLocator(LPCTSTR path) : jar(path) {
}
IStream* createStream(LPCTSTR path) {
return jar.get(path);
}
private:
java::util::jar::JarFile jar;
};
/**
A file locator that operates on the filesystem inside a folder.
@author_philk
*/
class FolderFileLocator : public IFileLocator {
public:
FolderFileLocator(LPCTSTR folder) : folder(folder) {
this->folder += L'/';
}
IStream* createStream(LPCTSTR path) {
IStream* stream;
if SUCCEEDED(::SHCreateStreamOnFile(folder + ATL::CStringW(path), STGM_READ | STGM_SHARE_DENY_NONE, &stream)) {
return stream;
}
return 0;
}
private:
ATL::CString folder;
};
namespace org { namespace osgi { namespace framework {
/**
Minimal implementation of an OSGi bundle.
<p>
This basically only offers to query the bundles headers.
@author_philk
*/
class Bundle {
public:
Bundle(LPCWSTR path) : valid(false), locator(0) {
const DWORD attribs = ::GetFileAttributes(path);
if (attribs == -1) {
return;
}
if (attribs & FILE_ATTRIBUTE_DIRECTORY) {
locator = new FolderFileLocator(path);
} else {
locator = new JarFileLocator(path);
}
ATL::CComPtr<IStream> stream(locator->createStream(L"/META-INF/MANIFEST.MF"));
if (stream) {
manifest.read(java::util::InputStream(stream));
valid = !manifest.getValue("Bundle-SymbolicName").IsEmpty();
}
loadBundleLocalization();
}
const bool isValid() const { return valid; }
const bool hasHeader(const ATL::CStringA& header) const {
return manifest.hasValue(header);
}
const bool isFragment() const {
return hasHeader("Fragment-Host");
}
/**
Checks whether the bundle contains service components.
<p>
It actually only checks the "Service-Component" bundle header and not the
actual defined components.
@return if the bundle contains service components.
*/
const bool hasServiceComponents() const {
return hasHeader("Service-Component");
}
ATL::CStringW getHeader(const ATL::CStringA& header) const {
ATL::CStringW value = manifest.getValue(header);
if (value[0] == L'%') {
ATL::CStringA l10nKey(value.GetString()+1);
if (l10n.hasValue(l10nKey)) {
return l10n.getValue(l10nKey);
}
return ATL::CStringW(l10nKey);
}
return value;
}
~Bundle() {
delete locator;
}
void loadBundleLocalization() {
ATL::CStringW location = manifest.getValue("Bundle-Localization");
if (location.IsEmpty()) {
location = L"/OSGI-INF/l10n/bundle";
}
// The order to read them would be:
// _locale.properties
// _en.properties
// .properties
// Each time l10n.read with the stream
// But it would have also search in fragments...
ATL::CComPtr<IStream> stream(locator->createStream(location + L".properties"));
if (stream) {
l10n.read(java::util::InputStream(stream));
}
}
private:
DISALLOW_COPY_AND_ASSIGN(Bundle);
bool valid;
// Will hold the bundles localized headers
java::util::Properties l10n;
// Holds the bundles manifest
java::util::jar::Manifest manifest;
// Describes how we find our files
IFileLocator* locator;
};
}}} // org::osgi::framework