49 /**
50 * A manager for pool of resources.
51 */
52 public class ResourcePoolManager {
53 // utility to read Module Attributes of the given ResourcePoolModule
54 static Attributes readModuleAttributes(ResourcePoolModule mod) {
55 String p = "/" + mod.name() + "/module-info.class";
56 Optional<ResourcePoolEntry> content = mod.findEntry(p);
57 if (content.isEmpty()) {
58 throw new PluginException("module-info.class not found for " +
59 mod.name() + " module");
60 }
61 ByteBuffer bb = ByteBuffer.wrap(content.get().contentBytes());
62 try {
63 return ModuleInfo.read(bb, null);
64 } catch (RuntimeException re) {
65 throw new RuntimeException("module info cannot be read for " + mod.name(), re);
66 }
67 }
68
69 /**
70 * Returns true if a resource is located in a named package.
71 */
72 public static boolean isNamedPackageResource(String name) {
73 int index = name.lastIndexOf("/");
74 if (index == -1) {
75 return false;
76 } else {
77 String pn = name.substring(0, index).replace('/', '.');
78 return Checks.isPackageName(pn);
79 }
80 }
81
82 static class ResourcePoolModuleImpl implements ResourcePoolModule {
83
84 final Map<String, ResourcePoolEntry> moduleContent = new LinkedHashMap<>();
85 // lazily initialized
86 private ModuleDescriptor descriptor;
87 private ModuleTarget target;
88
89 final String name;
90
91 private ResourcePoolModuleImpl(String name) {
92 this.name = name;
93 }
94
95 @Override
96 public String name() {
97 return name;
98 }
99
100 @Override
101 public Optional<ResourcePoolEntry> findEntry(String path) {
102 if (!path.startsWith("/")) {
115 }
116
117 @Override
118 public String targetPlatform() {
119 initModuleAttributes();
120 return target != null? target.targetPlatform() : null;
121 }
122
123 private void initModuleAttributes() {
124 if (this.descriptor == null) {
125 Attributes attr = readModuleAttributes(this);
126 this.descriptor = attr.descriptor();
127 this.target = attr.target();
128 }
129 }
130
131 @Override
132 public Set<String> packages() {
133 Set<String> pkgs = new HashSet<>();
134 moduleContent.values().stream()
135 .filter(m -> m.type() == ResourcePoolEntry.Type.CLASS_OR_RESOURCE)
136 .forEach(res -> {
137 String name = ImageFileCreator.resourceName(res.path());
138 if (isNamedPackageResource(name)) {
139 String pkg = ImageFileCreator.toPackage(name);
140 if (!pkg.isEmpty()) {
141 pkgs.add(pkg);
142 }
143 }
144 });
145 return pkgs;
146 }
147
148 @Override
149 public String toString() {
150 return name();
151 }
152
153 @Override
154 public Stream<ResourcePoolEntry> entries() {
155 return moduleContent.values().stream();
156 }
157
158 @Override
159 public int entryCount() {
160 return moduleContent.values().size();
161 }
162 }
163
164 public class ResourcePoolImpl implements ResourcePool {
165 @Override
166 public ResourcePoolModuleView moduleView() {
167 return ResourcePoolManager.this.moduleView();
168 }
169
170 @Override
171 public Stream<ResourcePoolEntry> entries() {
172 return ResourcePoolManager.this.entries();
173 }
174
175 @Override
176 public int entryCount() {
177 return ResourcePoolManager.this.entryCount();
178 }
179
180 @Override
181 public Optional<ResourcePoolEntry> findEntry(String path) {
|
49 /**
50 * A manager for pool of resources.
51 */
52 public class ResourcePoolManager {
53 // utility to read Module Attributes of the given ResourcePoolModule
54 static Attributes readModuleAttributes(ResourcePoolModule mod) {
55 String p = "/" + mod.name() + "/module-info.class";
56 Optional<ResourcePoolEntry> content = mod.findEntry(p);
57 if (content.isEmpty()) {
58 throw new PluginException("module-info.class not found for " +
59 mod.name() + " module");
60 }
61 ByteBuffer bb = ByteBuffer.wrap(content.get().contentBytes());
62 try {
63 return ModuleInfo.read(bb, null);
64 } catch (RuntimeException re) {
65 throw new RuntimeException("module info cannot be read for " + mod.name(), re);
66 }
67 }
68
69 static class ResourcePoolModuleImpl implements ResourcePoolModule {
70 private static final String PREVIEW_PREFIX = "META-INF/preview/";
71
72 final Map<String, ResourcePoolEntry> moduleContent = new LinkedHashMap<>();
73 // lazily initialized
74 private ModuleDescriptor descriptor;
75 private ModuleTarget target;
76
77 final String name;
78
79 private ResourcePoolModuleImpl(String name) {
80 this.name = name;
81 }
82
83 @Override
84 public String name() {
85 return name;
86 }
87
88 @Override
89 public Optional<ResourcePoolEntry> findEntry(String path) {
90 if (!path.startsWith("/")) {
103 }
104
105 @Override
106 public String targetPlatform() {
107 initModuleAttributes();
108 return target != null? target.targetPlatform() : null;
109 }
110
111 private void initModuleAttributes() {
112 if (this.descriptor == null) {
113 Attributes attr = readModuleAttributes(this);
114 this.descriptor = attr.descriptor();
115 this.target = attr.target();
116 }
117 }
118
119 @Override
120 public Set<String> packages() {
121 Set<String> pkgs = new HashSet<>();
122 moduleContent.values().stream()
123 .filter(m -> m.type() == ResourcePoolEntry.Type.CLASS_OR_RESOURCE)
124 .forEach(res -> inferPackageName(res).ifPresent(pkgs::add));
125 return pkgs;
126 }
127
128 @Override
129 public String toString() {
130 return name();
131 }
132
133 @Override
134 public Stream<ResourcePoolEntry> entries() {
135 return moduleContent.values().stream();
136 }
137
138 @Override
139 public int entryCount() {
140 return moduleContent.values().size();
141 }
142
143 /**
144 * Returns a valid non-empty package name, inferred from a resource pool
145 * entry's path.
146 *
147 * <p>If the resource pool entry is for a preview resource (i.e. with
148 * path {@code "/mod-name/META-INF/preview/pkg-path/resource-name"})
149 * the package name is the non-preview name based on {@code "pkg-path"}.
150 *
151 * @return the inferred package name, or {@link Optional#empty() empty}
152 * if no name could be inferred.
153 */
154 private static Optional<String> inferPackageName(ResourcePoolEntry res) {
155 // Expect entry paths to be "/mod-name/pkg-path/resource-name", but
156 // may also get "/mod-name/META-INF/preview/pkg-path/resource-name"
157 String name = res.path();
158 if (name.charAt(0) == '/') {
159 int pkgStart = name.indexOf('/', 1) + 1;
160 int pkgEnd = name.lastIndexOf('/');
161 if (pkgStart > 0 && pkgEnd > pkgStart) {
162 String pkgPath = name.substring(pkgStart, pkgEnd);
163 // Handle preview paths by removing the prefix.
164 if (pkgPath.startsWith(PREVIEW_PREFIX)) {
165 pkgPath = pkgPath.substring(PREVIEW_PREFIX.length());
166 }
167 String pkgName = pkgPath.replace('/', '.');
168 if (Checks.isPackageName(pkgName)) {
169 return Optional.of(pkgName);
170 }
171 }
172 }
173 return Optional.empty();
174 }
175 }
176
177 public class ResourcePoolImpl implements ResourcePool {
178 @Override
179 public ResourcePoolModuleView moduleView() {
180 return ResourcePoolManager.this.moduleView();
181 }
182
183 @Override
184 public Stream<ResourcePoolEntry> entries() {
185 return ResourcePoolManager.this.entries();
186 }
187
188 @Override
189 public int entryCount() {
190 return ResourcePoolManager.this.entryCount();
191 }
192
193 @Override
194 public Optional<ResourcePoolEntry> findEntry(String path) {
|