xref: /aosp_15_r20/dalvik/dx/src/com/android/multidex/Path.java (revision 055d459012065f78d96b68be8421640240ddf631)
1*055d4590SKeyi Gui /*
2*055d4590SKeyi Gui  * Copyright (C) 2014 The Android Open Source Project
3*055d4590SKeyi Gui  *
4*055d4590SKeyi Gui  * Licensed under the Apache License, Version 2.0 (the "License");
5*055d4590SKeyi Gui  * you may not use this file except in compliance with the License.
6*055d4590SKeyi Gui  * You may obtain a copy of the License at
7*055d4590SKeyi Gui  *
8*055d4590SKeyi Gui  *      http://www.apache.org/licenses/LICENSE-2.0
9*055d4590SKeyi Gui  *
10*055d4590SKeyi Gui  * Unless required by applicable law or agreed to in writing, software
11*055d4590SKeyi Gui  * distributed under the License is distributed on an "AS IS" BASIS,
12*055d4590SKeyi Gui  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*055d4590SKeyi Gui  * See the License for the specific language governing permissions and
14*055d4590SKeyi Gui  * limitations under the License.
15*055d4590SKeyi Gui  */
16*055d4590SKeyi Gui 
17*055d4590SKeyi Gui package com.android.multidex;
18*055d4590SKeyi Gui 
19*055d4590SKeyi Gui import com.android.dx.cf.direct.DirectClassFile;
20*055d4590SKeyi Gui import com.android.dx.cf.direct.StdAttributeFactory;
21*055d4590SKeyi Gui import java.io.ByteArrayOutputStream;
22*055d4590SKeyi Gui import java.io.File;
23*055d4590SKeyi Gui import java.io.FileNotFoundException;
24*055d4590SKeyi Gui import java.io.IOException;
25*055d4590SKeyi Gui import java.io.InputStream;
26*055d4590SKeyi Gui import java.util.ArrayList;
27*055d4590SKeyi Gui import java.util.List;
28*055d4590SKeyi Gui import java.util.regex.Pattern;
29*055d4590SKeyi Gui import java.util.zip.ZipException;
30*055d4590SKeyi Gui import java.util.zip.ZipFile;
31*055d4590SKeyi Gui 
32*055d4590SKeyi Gui class Path {
33*055d4590SKeyi Gui 
getClassPathElement(File file)34*055d4590SKeyi Gui     static ClassPathElement getClassPathElement(File file)
35*055d4590SKeyi Gui             throws ZipException, IOException {
36*055d4590SKeyi Gui         if (file.isDirectory()) {
37*055d4590SKeyi Gui             return new FolderPathElement(file);
38*055d4590SKeyi Gui         } else if (file.isFile()) {
39*055d4590SKeyi Gui             return new ArchivePathElement(new ZipFile(file));
40*055d4590SKeyi Gui         } else if (file.exists()) {
41*055d4590SKeyi Gui             throw new IOException("\"" + file.getPath() +
42*055d4590SKeyi Gui                     "\" is not a directory neither a zip file");
43*055d4590SKeyi Gui         } else {
44*055d4590SKeyi Gui             throw new FileNotFoundException("File \"" + file.getPath() + "\" not found");
45*055d4590SKeyi Gui         }
46*055d4590SKeyi Gui     }
47*055d4590SKeyi Gui 
48*055d4590SKeyi Gui     List<ClassPathElement> elements = new ArrayList<ClassPathElement>();
49*055d4590SKeyi Gui     private final String definition;
50*055d4590SKeyi Gui     private final ByteArrayOutputStream baos = new ByteArrayOutputStream(40 * 1024);
51*055d4590SKeyi Gui     private final byte[] readBuffer = new byte[20 * 1024];
52*055d4590SKeyi Gui 
Path(String definition)53*055d4590SKeyi Gui     Path(String definition) throws IOException {
54*055d4590SKeyi Gui         this.definition = definition;
55*055d4590SKeyi Gui         for (String filePath : definition.split(Pattern.quote(File.pathSeparator))) {
56*055d4590SKeyi Gui             try {
57*055d4590SKeyi Gui                 addElement(getClassPathElement(new File(filePath)));
58*055d4590SKeyi Gui             } catch (IOException e) {
59*055d4590SKeyi Gui                 throw new IOException("Wrong classpath: " + e.getMessage(), e);
60*055d4590SKeyi Gui             }
61*055d4590SKeyi Gui         }
62*055d4590SKeyi Gui     }
63*055d4590SKeyi Gui 
readStream(InputStream in, ByteArrayOutputStream baos, byte[] readBuffer)64*055d4590SKeyi Gui     private static byte[] readStream(InputStream in, ByteArrayOutputStream baos, byte[] readBuffer)
65*055d4590SKeyi Gui             throws IOException {
66*055d4590SKeyi Gui         try {
67*055d4590SKeyi Gui             for (;;) {
68*055d4590SKeyi Gui                 int amt = in.read(readBuffer);
69*055d4590SKeyi Gui                 if (amt < 0) {
70*055d4590SKeyi Gui                     break;
71*055d4590SKeyi Gui                 }
72*055d4590SKeyi Gui 
73*055d4590SKeyi Gui                 baos.write(readBuffer, 0, amt);
74*055d4590SKeyi Gui             }
75*055d4590SKeyi Gui         } finally {
76*055d4590SKeyi Gui             in.close();
77*055d4590SKeyi Gui         }
78*055d4590SKeyi Gui         return baos.toByteArray();
79*055d4590SKeyi Gui     }
80*055d4590SKeyi Gui 
81*055d4590SKeyi Gui     @Override
toString()82*055d4590SKeyi Gui     public String toString() {
83*055d4590SKeyi Gui         return definition;
84*055d4590SKeyi Gui     }
85*055d4590SKeyi Gui 
getElements()86*055d4590SKeyi Gui     Iterable<ClassPathElement> getElements() {
87*055d4590SKeyi Gui       return elements;
88*055d4590SKeyi Gui     }
89*055d4590SKeyi Gui 
addElement(ClassPathElement element)90*055d4590SKeyi Gui     private void addElement(ClassPathElement element) {
91*055d4590SKeyi Gui         assert element != null;
92*055d4590SKeyi Gui         elements.add(element);
93*055d4590SKeyi Gui     }
94*055d4590SKeyi Gui 
getClass(String path)95*055d4590SKeyi Gui     synchronized DirectClassFile getClass(String path) throws FileNotFoundException {
96*055d4590SKeyi Gui         DirectClassFile classFile = null;
97*055d4590SKeyi Gui         for (ClassPathElement element : elements) {
98*055d4590SKeyi Gui             try {
99*055d4590SKeyi Gui                 InputStream in = element.open(path);
100*055d4590SKeyi Gui                 try {
101*055d4590SKeyi Gui                     byte[] bytes = readStream(in, baos, readBuffer);
102*055d4590SKeyi Gui                     baos.reset();
103*055d4590SKeyi Gui                     classFile = new DirectClassFile(bytes, path, false);
104*055d4590SKeyi Gui                     classFile.setAttributeFactory(StdAttributeFactory.THE_ONE);
105*055d4590SKeyi Gui                     break;
106*055d4590SKeyi Gui                 } finally {
107*055d4590SKeyi Gui                     in.close();
108*055d4590SKeyi Gui                 }
109*055d4590SKeyi Gui             } catch (IOException e) {
110*055d4590SKeyi Gui                 // search next element
111*055d4590SKeyi Gui             }
112*055d4590SKeyi Gui         }
113*055d4590SKeyi Gui         if (classFile == null) {
114*055d4590SKeyi Gui             throw new FileNotFoundException("File \"" + path + "\" not found");
115*055d4590SKeyi Gui         }
116*055d4590SKeyi Gui         return classFile;
117*055d4590SKeyi Gui     }
118*055d4590SKeyi Gui }
119