View Javadoc

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