comparison src/main/gov/nasa/jpf/util/Source.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:61d41facf527
1 /*
2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
4 * All rights reserved.
5 *
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0.
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package gov.nasa.jpf.util;
19
20
21 import gov.nasa.jpf.Config;
22 import gov.nasa.jpf.JPF;
23
24 import java.io.BufferedReader;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.FileNotFoundException;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.InputStreamReader;
31 import java.util.ArrayList;
32 import java.util.Hashtable;
33 import java.util.LinkedList;
34 import java.util.List;
35 import java.util.jar.JarEntry;
36 import java.util.jar.JarFile;
37 import java.util.logging.Logger;
38
39
40 /**
41 * utility class to access arbitrary source files by line number
42 * sources can be files inside of root directories, or
43 * can be entries in jars
44 */
45 public class Source {
46
47 static Logger logger = JPF.getLogger("gov.nasa.jpf.util.Source");
48
49 static List<SourceRoot> sourceRoots;
50 static Hashtable<String,Source> sources = new Hashtable<String,Source>();
51 static Source noSource = new Source(null, null);
52
53 static abstract class SourceRoot { // common base
54 abstract InputStream getInputStream (String fname);
55 }
56
57 static class DirRoot extends SourceRoot {
58 String path;
59
60 DirRoot (String path){
61 this.path = path;
62 }
63
64 @Override
65 InputStream getInputStream (String fname) {
66 if (File.separatorChar != '/'){
67 fname = fname.replace('/', File.separatorChar);
68 }
69
70 File f = new File(path, fname);
71 if (f.exists()) {
72 try {
73 return new FileInputStream(f);
74 } catch (FileNotFoundException fnfx) {
75 return null;
76 }
77 } else {
78 return null;
79 }
80 }
81
82 @Override
83 public boolean equals (Object other){
84 return (other != null) && (other instanceof DirRoot) &&
85 path.equals(((DirRoot)other).path);
86 }
87
88 @Override
89 public String toString() {
90 return path;
91 }
92 }
93
94 static class JarRoot extends SourceRoot {
95 JarFile jar;
96 String entryPrefix;
97
98 JarRoot (String path, String ep) throws IOException {
99 jar = new JarFile(path);
100
101 if (ep == null) {
102 entryPrefix = null;
103 } else {
104 entryPrefix = ep;
105 if (ep.charAt(ep.length()-1) != '/') {
106 entryPrefix += '/';
107 }
108 }
109 }
110
111 @Override
112 InputStream getInputStream (String fname) {
113 String en = (entryPrefix != null) ? entryPrefix + fname : fname;
114 JarEntry entry = jar.getJarEntry(en);
115 if (entry != null) {
116 try {
117 return jar.getInputStream(entry);
118 } catch (IOException e) {
119 return null;
120 }
121 } else {
122 return null;
123 }
124 }
125
126 @Override
127 public boolean equals (Object other){
128 if ( (other != null) && (other instanceof JarRoot)){
129
130 // just how hard can it be to check if two JarFiles instances refer to
131 // the same file?
132 JarRoot o = (JarRoot)other;
133 File f = new File(jar.getName());
134 File fOther = new File(o.jar.getName());
135 if (f.getAbsolutePath().equals(fOther.getAbsolutePath())){
136 if (entryPrefix == null){
137 return o.entryPrefix == null;
138 } else {
139 entryPrefix.equals(o.entryPrefix);
140 }
141 }
142 }
143
144 return false;
145 }
146
147 @Override
148 public String toString() {
149 return jar.getName();
150 }
151 }
152
153 static void addSourceRoot (Config config, List<SourceRoot> roots, String spec){
154 SourceRoot sr = null;
155
156 try {
157 int i = spec.indexOf(".jar");
158 if (i >= 0) { // jar
159 String pn = FileUtils.asPlatformPath(spec.substring(0, i + 4));
160 File jar = new File(pn);
161 if (jar.exists()) {
162 int i0 = i + 5; // scrub the leading path separator
163 // JarFile assumes Unix for archive-internal paths (also on Windows)
164 String ep = (spec.length() > i0) ? FileUtils.asCanonicalUnixPath(spec.substring(i0)) : null;
165 // we should probably check here if there is such a dir in the Jar
166 sr = new JarRoot(pn, ep);
167 }
168
169 } else { // directory
170 String pn = FileUtils.asPlatformPath(spec);
171 File dir = new File(pn);
172 if (dir.exists()) {
173 sr = new DirRoot(pn);
174 }
175 }
176 } catch (IOException iox) {
177 // we report this below
178 }
179
180 if (sr != null) {
181 if (!roots.contains(sr)){
182 roots.add(sr);
183 }
184 } else {
185 logger.info("not a valid source root: " + spec);
186 }
187 }
188
189 static String findSrcRoot (String cpEntry){
190 if (cpEntry.endsWith(".jar")){
191 // check if there is a 'src' dir in the jar
192 try {
193 JarFile jf = new JarFile(cpEntry);
194 JarEntry srcEntry = jf.getJarEntry("src");
195 if (srcEntry != null && srcEntry.isDirectory()) {
196 return jf.getName() + "/src"; // jar internal paths use '/' separators
197 }
198 } catch (IOException iox){
199 return null;
200 }
201
202 } else { // is it a dir?
203 File cpe = new File(cpEntry);
204 if (cpe.isDirectory()){
205 // go up until you hit a dir that has a 'src' subdir
206 // remember the traversed path elements
207 LinkedList<String> dirStack = new LinkedList<String>();
208 dirStack.addFirst(cpe.getName());
209 for (File pd = cpe.getParentFile(); pd != null; pd = pd.getParentFile()){
210 File sd = new File(pd,"src");
211 if (sd.isDirectory()){
212 String srcRoot = sd.getPath();
213 for (String e : dirStack) {
214 srcRoot = srcRoot + File.separatorChar + e;
215 }
216 sd = new File(srcRoot);
217 if (sd.isDirectory()){
218 return srcRoot;
219 }
220 } else {
221 dirStack.addFirst(pd.getName());
222 }
223 }
224 }
225 }
226
227 return null;
228 }
229
230 public static void init (Config config) {
231 ArrayList<SourceRoot> roots = new ArrayList<SourceRoot>();
232
233 String[] srcPaths = config.getCompactStringArray("sourcepath");
234 if (srcPaths != null){
235 for (String e : srcPaths){
236 addSourceRoot(config, roots, e);
237 }
238 }
239
240 sourceRoots = roots;
241 sources.clear();
242
243 //printRoots();
244 }
245
246 // for debugging purposes
247 static void printRoots() {
248 System.out.println("source roots:");
249 for (SourceRoot sr : sourceRoots){
250 System.out.println(" " + sr);
251 }
252 }
253
254 public static Source getSource (String relPathName) {
255 if (relPathName == null){
256 return null;
257 }
258
259 Source s = sources.get(relPathName);
260 if (s == noSource) {
261 return null;
262 }
263
264 if (s == null) {
265 for (SourceRoot root : sourceRoots) {
266 InputStream is = root.getInputStream(relPathName);
267 if (is != null) {
268 try {
269 s = new Source(root,relPathName);
270 s.loadLines(is);
271 is.close();
272
273 sources.put(relPathName, s);
274 return s;
275 } catch (IOException iox) {
276 logger.warning("error reading " + relPathName + " from" + root);
277 return null;
278 }
279 }
280 }
281 } else {
282 return s;
283 }
284
285 sources.put(relPathName, noSource);
286 return null;
287 }
288
289 //--- the Source instance data itself
290 protected SourceRoot root;
291 protected String fname;
292 protected String[] lines;
293
294
295 protected Source (SourceRoot root, String fname) {
296 this.root = root;
297 this.fname = fname;
298 }
299
300 protected void loadLines (InputStream is) throws IOException {
301 BufferedReader in = new BufferedReader(new InputStreamReader(is));
302
303 ArrayList<String> l = new ArrayList<String>();
304 for (String line = in.readLine(); line != null; line = in.readLine()) {
305 l.add(line);
306 }
307 in.close();
308
309 if (l.size() > 0) {
310 lines = l.toArray(new String[l.size()]);
311 }
312 }
313
314
315 /**
316 * this is our sole purpose in life - answer line strings
317 * line index is 1-based
318 */
319 public String getLine (int i) {
320 if ((lines == null) || (i <= 0) || (i > lines.length)) {
321 return null;
322 } else {
323 return lines[i-1];
324 }
325 }
326
327 public int getLineCount()
328 {
329 return(lines.length);
330 }
331
332 public String getPath() {
333 return root.toString() + File.separatorChar + fname;
334 }
335 }