View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.osgi.boot.warurl.internal;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.OutputStream;
24  import java.io.PipedInputStream;
25  import java.io.PipedOutputStream;
26  import java.net.URL;
27  import java.net.URLConnection;
28  import java.security.Permission;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.jar.JarFile;
32  import java.util.jar.JarInputStream;
33  import java.util.jar.JarOutputStream;
34  import java.util.jar.Manifest;
35  import java.util.zip.ZipEntry;
36  
37  import org.eclipse.jetty.util.IO;
38  import org.eclipse.jetty.util.resource.Resource;
39  
40  /**
41   * Facade for a URLConnection that will read a jar and substitute its
42   * manifest by the manifest provided here.
43   * <p>
44   * Use Piped streams to avoid having to create temporary files.
45   * </p>
46   */
47  public class WarURLConnection extends URLConnection
48  {
49  
50      /**
51       * Use PipedOuputStream and PipedInputStream to do the transformation without making
52       * a new temporary file ust to replace the manifest.
53       * @param newmanifest The new manifest
54       * @param rawIn The file input stream or equivalent. not the jar input stream.
55       */
56      public static InputStream substitueManifest(final Manifest newmanifest,
57              final InputStream rawIn) throws IOException
58      {
59          final PipedOutputStream pOut = new PipedOutputStream();
60          PipedInputStream pIn = new PipedInputStream(pOut);
61          Runnable run = new Runnable()
62          {
63              public void run()
64              {
65                  JarInputStream jin = null;
66                  JarOutputStream dest = null;
67                  try
68                  {
69                      jin = new JarInputStream(rawIn, false);
70                      dest = new JarOutputStream(pOut, newmanifest);
71                      ZipEntry next = jin.getNextEntry();
72                      while (next != null)
73                      {
74                          if (next.getName().equalsIgnoreCase(JarFile.MANIFEST_NAME))
75                          {
76                              continue;
77                          }
78                          dest.putNextEntry(next);
79                          if (next.getSize() > 0)
80                          {
81                              IO.copy(jin,dest,next.getSize());
82                          }
83                          next = jin.getNextJarEntry();
84                      }
85                  }
86                  catch (IOException ioe) {
87                      ioe.printStackTrace();
88                  }
89                  finally
90                  {
91                      if (dest != null) IO.close(dest);
92                      if (jin != null) IO.close(jin);
93                      IO.close(pOut);
94                  }
95              }
96          };
97          Thread th = new Thread(run);
98          th.start();
99          return pIn;
100     }
101     
102     private Manifest _mf;
103     private URLConnection _conn;
104     
105     /**
106      * @param url The file url (for example)
107      * @param mf The manifest to use as a replacement to the jar file inside
108      * the file url.
109      */
110     public WarURLConnection(URL url, Manifest mf) throws IOException
111     {
112         super(url);
113         _conn = url.openConnection();
114         _conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
115         _mf = mf;
116     }
117     @Override
118     public void connect() throws IOException
119     {
120         _conn.connect();
121     }
122     
123 
124     public InputStream getInputStream() throws IOException
125     {
126         return substitueManifest(_mf, _conn.getInputStream());
127     }
128 
129     public void addRequestProperty(String key, String value)
130     {
131         _conn.addRequestProperty(key,value);
132     }
133 
134     public boolean equals(Object obj)
135     {
136         return _conn.equals(obj);
137     }
138 
139     public boolean getAllowUserInteraction()
140     {
141         return _conn.getAllowUserInteraction();
142     }
143 
144     public int getConnectTimeout()
145     {
146         return _conn.getConnectTimeout();
147     }
148 
149     public Object getContent() throws IOException
150     {
151         return _conn.getContent();
152     }
153 
154     public Object getContent(Class[] classes) throws IOException
155     {
156         return _conn.getContent(classes);
157     }
158 
159     public String getContentEncoding()
160     {
161         return _conn.getContentEncoding();
162     }
163 
164     public int getContentLength()
165     {
166         return _conn.getContentLength();
167     }
168 
169     public String getContentType()
170     {
171         return _conn.getContentType();
172     }
173 
174     public long getDate()
175     {
176         return _conn.getDate();
177     }
178 
179     public boolean getDefaultUseCaches()
180     {
181         return _conn.getDefaultUseCaches();
182     }
183 
184     public boolean getDoInput()
185     {
186         return _conn.getDoInput();
187     }
188 
189     public boolean getDoOutput()
190     {
191         return _conn.getDoOutput();
192     }
193 
194     public long getExpiration()
195     {
196         return _conn.getExpiration();
197     }
198 
199     public String getHeaderField(int n)
200     {
201         return _conn.getHeaderField(n);
202     }
203 
204     public String getHeaderField(String name)
205     {
206         return _conn.getHeaderField(name);
207     }
208 
209     public long getHeaderFieldDate(String name, long Default)
210     {
211         return _conn.getHeaderFieldDate(name,Default);
212     }
213 
214     public int getHeaderFieldInt(String name, int Default)
215     {
216         return _conn.getHeaderFieldInt(name,Default);
217     }
218 
219     public String getHeaderFieldKey(int n)
220     {
221         return _conn.getHeaderFieldKey(n);
222     }
223 
224     public Map<String, List<String>> getHeaderFields()
225     {
226         return _conn.getHeaderFields();
227     }
228 
229     public long getIfModifiedSince()
230     {
231         return _conn.getIfModifiedSince();
232     }
233 
234     public long getLastModified()
235     {
236         return _conn.getLastModified();
237     }
238 
239     public OutputStream getOutputStream() throws IOException
240     {
241         return _conn.getOutputStream();
242     }
243 
244     public Permission getPermission() throws IOException
245     {
246         return _conn.getPermission();
247     }
248 
249     public int getReadTimeout()
250     {
251         return _conn.getReadTimeout();
252     }
253 
254     public Map<String, List<String>> getRequestProperties()
255     {
256         return _conn.getRequestProperties();
257     }
258 
259     public String getRequestProperty(String key)
260     {
261         return _conn.getRequestProperty(key);
262     }
263 
264     public URL getURL()
265     {
266         return _conn.getURL();
267     }
268 
269     public boolean getUseCaches()
270     {
271         return _conn.getUseCaches();
272     }
273 
274     public void setAllowUserInteraction(boolean allowuserinteraction)
275     {
276         _conn.setAllowUserInteraction(allowuserinteraction);
277     }
278 
279     public void setConnectTimeout(int timeout)
280     {
281         _conn.setConnectTimeout(timeout);
282     }
283 
284     public void setDefaultUseCaches(boolean defaultusecaches)
285     {
286         _conn.setDefaultUseCaches(defaultusecaches);
287     }
288 
289     public void setDoInput(boolean doinput)
290     {
291         _conn.setDoInput(doinput);
292     }
293 
294     public void setDoOutput(boolean dooutput)
295     {
296         _conn.setDoOutput(dooutput);
297     }
298 
299     public void setIfModifiedSince(long ifmodifiedsince)
300     {
301         _conn.setIfModifiedSince(ifmodifiedsince);
302     }
303 
304     public void setReadTimeout(int timeout)
305     {
306         _conn.setReadTimeout(timeout);
307     }
308 
309     public void setRequestProperty(String key, String value)
310     {
311         _conn.setRequestProperty(key,value);
312     }
313 
314     public void setUseCaches(boolean usecaches)
315     {
316         _conn.setUseCaches(usecaches);
317     }
318 
319     
320 
321 }