1 /*
2 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24 package com.sun.classanalyzer;
25
26 import java.io.BufferedReader;
27 import java.io.File;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.InputStreamReader;
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.List;
34 import java.util.Set;
35 import java.util.TreeSet;
36
37 /**
38 *
39 */
40 public class ResourceFile implements Comparable<ResourceFile> {
41 private final String pathname;
42 private final long filesize;
43 protected final String name;
44 private Module module;
45
46 ResourceFile(String fname) {
47 this(fname, 0);
48 }
49
50 ResourceFile(String fname, long size) {
51 this.pathname = fname.replace('/', File.separatorChar);
52 this.name = fname.replace(File.separatorChar, '/');
53 this.filesize = size;
54 }
55
56 Module getModule() {
57 return module;
58 }
59
60 void setModule(Module m) {
61 if (module != null) {
62 throw new RuntimeException("Module for " + this + " already set");
63 }
64 this.module = m;
65 }
66
67 String getName() {
68 return name;
69 }
70
71 String getPathname() {
72 return pathname;
73 }
74
75 long getFileSize() {
76 return filesize;
77 }
78
79 @Override
80 public String toString() {
81 return name;
82 }
83
84 @Override
85 public int compareTo(ResourceFile o) {
86 return name.compareTo(o.name);
87 }
88
89 private static Set<ResourceFile> resources = new TreeSet<ResourceFile>();
90
91 static boolean isResource(String pathname) {
92 // skip these files
93 String name = pathname.replace(File.separatorChar, '/');
94 if (name.endsWith("META-INF/MANIFEST.MF")) {
95 return false;
96 }
97 if (name.contains("META-INF/JCE_RSA.")) {
98 return false;
99 }
100 if (name.contains("META-INF/") &&
101 (name.endsWith(".RSA") || name.endsWith(".SF"))) {
102 return false;
103 }
104
105 return true;
106 }
107
108 static ResourceFile addResource(String fname, InputStream in, long size) {
109 ResourceFile res;
110 fname = fname.replace(File.separatorChar, '/');
111 if (fname.startsWith("META-INF/services")) {
112 res = new ServiceProviderConfigFile(fname, in, size);
113 } else {
114 res = new ResourceFile(fname, size);
115 }
116 resources.add(res);
117 return res;
118 }
119
120 static Set<ResourceFile> getAllResources() {
121 return Collections.unmodifiableSet(resources);
122 }
123
124 static class ServiceProviderConfigFile extends ResourceFile {
125 final List<String> providers = new ArrayList<String>();
126 final String service;
127
128 ServiceProviderConfigFile(String fname, InputStream in) {
129 this(fname, in, 0);
130 }
131
132 ServiceProviderConfigFile(String fname, InputStream in, long size) {
133 super(fname, size);
134 readServiceConfiguration(in, providers);
135 this.service = name.substring("META-INF/services".length() + 1, name.length());
136 }
137
138 @Override
139 String getName() {
140 if (providers.isEmpty()) {
141 return service;
142 } else {
143 // just use the first one for matching
144 return providers.get(0);
145 }
146 }
147
148 @Override
149 public boolean equals(Object o) {
150 if (o instanceof ServiceProviderConfigFile) {
151 ServiceProviderConfigFile sp = (ServiceProviderConfigFile) o;
152 if (service.equals(sp.service) && providers.size() == sp.providers.size()) {
153 List<String> tmp = new ArrayList<String>(providers);
154 if (tmp.removeAll(sp.providers)) {
155 return tmp.size() == 0;
156 }
157 }
158 }
159 return false;
160 }
161
162 public int hashCode() {
163 int hash = 7;
164 hash = 73 * hash + (this.providers != null ? this.providers.hashCode() : 0);
165 hash = 73 * hash + (this.service != null ? this.service.hashCode() : 0);
166 return hash;
167 }
168
169 @Override
170 public int compareTo(ResourceFile o) {
171 if (this.equals(o)) {
172 return 0;
173 } else {
174 if (getName().compareTo(o.getName()) < 0) {
175 return -1;
176 } else {
177 return 1;
178 }
179 }
180 }
181
182 @SuppressWarnings("empty-statement")
183 void readServiceConfiguration(InputStream in, List<String> names) {
184 BufferedReader br = null;
185 try {
186 if (in != null) {
187 // Properties doesn't perserve the order of the input file
188 br = new BufferedReader(new InputStreamReader(in, "utf-8"));
189 int lc = 1;
190 while ((lc = parseLine(br, lc, names)) >= 0);
191 }
192 } catch (IOException ex) {
193 throw new RuntimeException(ex);
194 } finally {
195 if (br != null) {
196 try {
197 br.close();
198 } catch (IOException ex) {
199 throw new RuntimeException(ex);
200 }
201 }
202 }
203 }
204
205 // Parse a single line from the given configuration file, adding the name
206 // on the line to the names list.
207 //
208 private int parseLine(BufferedReader r, int lc, List<String> names) throws IOException {
209 String ln = r.readLine();
210 if (ln == null) {
211 return -1;
212 }
213 int ci = ln.indexOf('#');
214 if (ci >= 0) {
215 ln = ln.substring(0, ci);
216 }
217 ln = ln.trim();
218 int n = ln.length();
219 if (n != 0) {
220 if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) {
221 throw new RuntimeException("Illegal configuration-file syntax");
222 }
223 int cp = ln.codePointAt(0);
224 if (!Character.isJavaIdentifierStart(cp)) {
225 throw new RuntimeException("Illegal provider-class name: " + ln);
226 }
227 for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
228 cp = ln.codePointAt(i);
229 if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) {
230 throw new RuntimeException("Illegal provider-class name: " + ln);
231 }
232 }
233 if (!names.contains(ln)) {
234 names.add(ln);
235 }
236 }
237 return lc + 1;
238 }
239 }
240 }
--- EOF ---