blob: d4d8f76d5b0f8aa68bbdab8ab0f7ff8d17a68e8b [file] [log] [blame]
Karl Pauls36407322008-03-07 00:37:30 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * 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,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.apache.felix.framework.security.util;
20
21import java.io.ByteArrayInputStream;
22import java.io.ByteArrayOutputStream;
23import java.io.IOException;
24import java.io.InputStream;
25import java.io.OutputStream;
26import java.util.ArrayList;
Karl Paulse2913e62010-12-22 18:29:22 +000027import java.util.Collections;
Karl Pauls36407322008-03-07 00:37:30 +000028import java.util.Enumeration;
29import java.util.List;
30import java.util.jar.JarEntry;
31import java.util.jar.JarOutputStream;
32
Karl Paulsfbb32572010-05-30 22:16:56 +000033//import org.apache.felix.moduleloader.IContent;
34import org.apache.felix.framework.resolver.Content;
Karl Pauls36407322008-03-07 00:37:30 +000035
36/**
Karl Pauls23287bd2010-01-10 22:11:27 +000037 * This class makes a given content available as a inputstream with a jar
38 * content. In other words the stream can be used as input to a JarInputStream.
Karl Pauls36407322008-03-07 00:37:30 +000039 */
40public final class BundleInputStream extends InputStream
41{
Karl Paulsfbb32572010-05-30 22:16:56 +000042 private final Content m_root;
Karl Pauls36407322008-03-07 00:37:30 +000043 private final Enumeration m_content;
44 private final OutputStreamBuffer m_outputBuffer = new OutputStreamBuffer();
Karl Pauls23287bd2010-01-10 22:11:27 +000045
Karl Pauls36407322008-03-07 00:37:30 +000046 private ByteArrayInputStream m_buffer = null;
47 private JarOutputStream m_output = null;
Karl Pauls23287bd2010-01-10 22:11:27 +000048
Karl Paulsfbb32572010-05-30 22:16:56 +000049 public BundleInputStream(Content root) throws IOException
Karl Pauls36407322008-03-07 00:37:30 +000050 {
51 m_root = root;
Karl Pauls23287bd2010-01-10 22:11:27 +000052
Karl Pauls36407322008-03-07 00:37:30 +000053 List entries = new ArrayList();
Karl Pauls23287bd2010-01-10 22:11:27 +000054
Karl Pauls36407322008-03-07 00:37:30 +000055 int count = 0;
56 String manifest = null;
Karl Pauls23287bd2010-01-10 22:11:27 +000057 for (Enumeration e = m_root.getEntries(); e.hasMoreElements();)
Karl Pauls36407322008-03-07 00:37:30 +000058 {
59 String entry = (String) e.nextElement();
60 if (entry.equalsIgnoreCase("META-INF/MANIFEST.MF"))
61 {
62 if (manifest == null)
63 {
64 manifest = entry;
65 }
66 }
67 else if (entry.toUpperCase().startsWith("META-INF/"))
68 {
69 entries.add(count++, entry);
70 }
71 else
72 {
73 entries.add(entry);
74 }
75 }
76 if (manifest == null)
77 {
78 manifest = "META-INF/MANIFEST.MF";
79 }
Karl Paulse2913e62010-12-22 18:29:22 +000080 m_content = Collections.enumeration(entries);
Karl Pauls23287bd2010-01-10 22:11:27 +000081
Karl Pauls36407322008-03-07 00:37:30 +000082 try
83 {
84 m_output = new JarOutputStream(m_outputBuffer);
85 readNext(manifest);
Karl Pauls23287bd2010-01-10 22:11:27 +000086 m_buffer = new ByteArrayInputStream(m_outputBuffer.m_outBuffer
87 .toByteArray());
Karl Pauls36407322008-03-07 00:37:30 +000088
89 m_outputBuffer.m_outBuffer = null;
Karl Pauls23287bd2010-01-10 22:11:27 +000090 }
Karl Pauls36407322008-03-07 00:37:30 +000091 catch (IOException ex)
92 {
93 // TODO: figure out what is wrong
94 ex.printStackTrace();
95 throw ex;
96 }
97 }
98
99 public int read() throws IOException
100 {
101 if ((m_output == null) && (m_buffer == null))
102 {
103 return -1;
104 }
105
106 if (m_buffer != null)
107 {
108 int result = m_buffer.read();
109
110 if (result == -1)
111 {
112 m_buffer = null;
113 return read();
114 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000115
Karl Pauls36407322008-03-07 00:37:30 +0000116 return result;
117 }
118
119 if (m_content.hasMoreElements())
120 {
121 String current = (String) m_content.nextElement();
Karl Pauls23287bd2010-01-10 22:11:27 +0000122
Karl Pauls36407322008-03-07 00:37:30 +0000123 readNext(current);
Karl Pauls23287bd2010-01-10 22:11:27 +0000124
Karl Pauls36407322008-03-07 00:37:30 +0000125 if (!m_content.hasMoreElements())
126 {
127 m_output.close();
128 m_output = null;
129 }
130
Karl Pauls23287bd2010-01-10 22:11:27 +0000131 m_buffer = new ByteArrayInputStream(m_outputBuffer.m_outBuffer
132 .toByteArray());
Karl Pauls36407322008-03-07 00:37:30 +0000133
134 m_outputBuffer.m_outBuffer = null;
135 }
136
137 return read();
138 }
139
140 private void readNext(String path) throws IOException
141 {
142 m_outputBuffer.m_outBuffer = new ByteArrayOutputStream();
143
144 InputStream in = null;
145 try
146 {
147 in = m_root.getEntryAsStream(path);
148
149 if (in == null)
150 {
151 throw new IOException("Missing entry");
152 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000153
Karl Pauls36407322008-03-07 00:37:30 +0000154 JarEntry entry = new JarEntry(path);
155
156 m_output.putNextEntry(entry);
157
158 byte[] buffer = new byte[4 * 1024];
159
160 for (int c = in.read(buffer); c != -1; c = in.read(buffer))
161 {
162 m_output.write(buffer, 0, c);
163 }
164 }
165 finally
166 {
167 if (in != null)
168 {
169 try
170 {
171 in.close();
172 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000173 catch (Exception ex)
Karl Pauls36407322008-03-07 00:37:30 +0000174 {
175 // Not much we can do
176 }
177 }
178 }
179
180 m_output.closeEntry();
181
182 m_output.flush();
183 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000184
Karl Pauls36407322008-03-07 00:37:30 +0000185 private static final class OutputStreamBuffer extends OutputStream
186 {
187 ByteArrayOutputStream m_outBuffer = null;
188
189 public void write(int b)
190 {
191 m_outBuffer.write(b);
192 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000193
Karl Pauls36407322008-03-07 00:37:30 +0000194 public void write(byte[] buffer) throws IOException
195 {
196 m_outBuffer.write(buffer);
Karl Pauls23287bd2010-01-10 22:11:27 +0000197 }
198
Karl Pauls36407322008-03-07 00:37:30 +0000199 public void write(byte[] buffer, int offset, int length)
200 {
201 m_outBuffer.write(buffer, offset, length);
202 }
203 }
204}