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 * @author Mandy Chung 40 */ 41 public class ResourceFile implements Comparable<ResourceFile> { 42 43 private final String pathname; 44 private Module module; 45 46 ResourceFile(String pathname) { 47 this.pathname = pathname.replace(File.separatorChar, '/'); 48 } 49 50 Module getModule() { 51 return module; 52 } 53 54 void setModule(Module m) { 55 if (module != null) { 56 throw new RuntimeException("Module for " + this + " already set"); 57 } 58 this.module = m; 59 } 60 61 String getName() { 62 return pathname; 63 } 64 65 String getPathname() { 66 return pathname; 67 } 68 69 @Override 70 public String toString() { 71 return pathname; 72 } 73 74 @Override 75 public int compareTo(ResourceFile o) { 76 return pathname.compareTo(o.pathname); 77 } 78 static Set<ResourceFile> resources = new TreeSet<ResourceFile>(); 79 80 static boolean isResource(String pathname) { 81 String name = pathname.replace(File.separatorChar, '/'); 82 83 if (name.endsWith("META-INF/MANIFEST.MF")) { 84 return false; 85 } 86 if (name.contains("META-INF/JCE_RSA.")) { 87 return false; 88 } 89 90 return true; 91 } 92 93 static void addResource(String name, InputStream in) { 94 ResourceFile res; 95 name = name.replace(File.separatorChar, '/'); 96 if (name.startsWith("META-INF/services")) { 97 res = new ServiceProviderConfigFile(name, in); 98 } else { 99 res = new ResourceFile(name); 100 } 101 resources.add(res); 102 } 103 104 static Set<ResourceFile> getAllResources() { 105 return Collections.unmodifiableSet(resources); 106 } 107 108 static class ServiceProviderConfigFile extends ResourceFile { 109 110 private final List<String> providers = new ArrayList<String>(); 111 private final String service; 112 ServiceProviderConfigFile(String pathname, InputStream in) { 113 super(pathname); 114 readServiceConfiguration(in, providers); 115 this.service = pathname.substring("META-INF/services".length() + 1, pathname.length()); 116 } 117 118 @Override 119 String getName() { 120 if (providers.isEmpty()) { 121 return service; 122 } else { 123 // just use the first one for matching 124 return providers.get(0); 125 } 126 } 127 128 @SuppressWarnings("empty-statement") 129 void readServiceConfiguration(InputStream in, List<String> names) { 130 BufferedReader br = null; 131 try { 132 if (in != null) { 133 // Properties doesn't perserve the order of the input file 134 br = new BufferedReader(new InputStreamReader(in, "utf-8")); 135 int lc = 1; 136 while ((lc = parseLine(br, lc, names)) >= 0); 137 } 138 } catch (IOException ex) { 139 throw new RuntimeException(ex); 140 } finally { 141 if (br != null) { 142 try { 143 br.close(); 144 } catch (IOException ex) { 145 throw new RuntimeException(ex); 146 } 147 } 148 } 149 } 150 151 // Parse a single line from the given configuration file, adding the name 152 // on the line to the names list. 153 // 154 private int parseLine(BufferedReader r, int lc, List<String> names) throws IOException { 155 String ln = r.readLine(); 156 if (ln == null) { 157 return -1; 158 } 159 int ci = ln.indexOf('#'); 160 if (ci >= 0) { 161 ln = ln.substring(0, ci); 162 } 163 ln = ln.trim(); 164 int n = ln.length(); 165 if (n != 0) { 166 if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) { 167 throw new RuntimeException("Illegal configuration-file syntax"); 168 } 169 int cp = ln.codePointAt(0); 170 if (!Character.isJavaIdentifierStart(cp)) { 171 throw new RuntimeException("Illegal provider-class name: " + ln); 172 } 173 for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) { 174 cp = ln.codePointAt(i); 175 if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) { 176 throw new RuntimeException("Illegal provider-class name: " + ln); 177 } 178 } 179 if (!names.contains(ln)) { 180 names.add(ln); 181 } 182 } 183 return lc + 1; 184 } 185 } 186 }