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  // ========================================================================
13  package org.eclipse.jetty.osgi.boot.internal.webapp;
14  
15  import java.io.File;
16  import java.io.FileOutputStream;
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.net.URI;
20  import java.net.URISyntaxException;
21  import java.net.URL;
22  import java.util.Enumeration;
23  import java.util.zip.ZipEntry;
24  import java.util.zip.ZipFile;
25  
26  import org.eclipse.jetty.util.URIUtil;
27  
28  /**
29   * <p>
30   * Magically extract the jettyhome folder from this bundle's jar place it
31   * somewhere in the file-system. Currently we do this only when we detect a
32   * system property 'jetty.magic.home.parent' or if we are inside the pde in dev
33   * mode. In dev mode we use the osgi.configuration.area folder.
34   * </p>
35   * <p>
36   * This work is done through the jetty launch configuration inside the
37   * "Jetty Config" tab. We could choose to remove this code at some point
38   * although it does not hurt and it helps for users who don't go through the
39   * jetty launch.
40   * </p>
41   */
42  class JettyHomeHelper
43  {
44  
45      /** only magically extract jettyhome if we are inside the pde. */
46      static boolean magic_install_only_in_pde = Boolean.valueOf(System.getProperty("jetty.magic.home.pde.only","true"));
47  
48      /**
49       * Hack for eclipse-PDE. When no jetty.home was set, detect if we running
50       * inside eclipse-PDE in development mode. In that case extract the
51       * jettyhome folder embedded inside this plugin inside the configuration
52       * area folder. It is specific to the workspace. Set the folder as
53       * jetty.home. If the folder already exist don't extract it again.
54       * <p>
55       * If we are not pde dev mode, the same but look in the installation folder
56       * of eclipse itself.
57       * </p>
58       * 
59       * @return
60       * @throws URISyntaxException
61       */
62      static String setupJettyHomeInEclipsePDE(File thisbundlejar)
63      {
64          File ecFolder = getParentFolderOfMagicHome();
65          if (ecFolder == null || !ecFolder.exists())
66          {
67              return null;
68          }
69          File jettyhome = new File(ecFolder,"jettyhome");
70          String path;
71          try
72          {
73              path = jettyhome.getCanonicalPath();
74              if (jettyhome.exists())
75              {
76                  System.setProperty("jetty.home",path);
77                  return path;
78              }
79              else
80              {
81                  // now grab the jar and unzip the relevant portion
82                  unzipJettyHomeIntoDirectory(thisbundlejar,ecFolder);
83                  System.setProperty("jetty.home",path);
84                  return path;
85              }
86          }
87          catch (IOException e)
88          {
89              e.printStackTrace();
90          }
91          return null;
92      }
93  
94      /**
95       * @return true when we are currently being run by the pde in development
96       *         mode.
97       */
98      private static boolean isPDEDevelopment()
99      {
100         String eclipseCommands = System.getProperty("eclipse.commands");
101         // detect if we are being run from the pde: ie during development.
102         return eclipseCommands != null && eclipseCommands.indexOf("-dev") != -1
103                 && (eclipseCommands.indexOf("-dev\n") != -1 || eclipseCommands.indexOf("-dev\r") != -1 || eclipseCommands.indexOf("-dev ") != -1);
104     }
105 
106     /**
107      * @return
108      */
109     private static File getConfigurationAreaDirectory()
110     {
111         return getFile(System.getProperty("osgi.configuration.area"));
112     }
113 
114     /**
115      * @param zipFile
116      *            The current jar file for this bundle. contains an archive of
117      *            the default jettyhome
118      * @param parentOfMagicJettyHome
119      *            The folder inside which jettyhome is created.
120      */
121     private static void unzipJettyHomeIntoDirectory(File thisbundlejar, File parentOfMagicJettyHome) throws IOException
122     {
123         ZipFile zipFile = null;
124         try
125         {
126             zipFile = new ZipFile(thisbundlejar);
127             Enumeration<? extends ZipEntry> files = zipFile.entries();
128             File f = null;
129             FileOutputStream fos = null;
130 
131             while (files.hasMoreElements())
132             {
133                 try
134                 {
135                     ZipEntry entry = files.nextElement();
136                     String entryName = entry.getName();
137                     if (!entryName.startsWith("jettyhome"))
138                     {
139                         continue;
140                     }
141 
142                     InputStream eis = zipFile.getInputStream(entry);
143                     byte[] buffer = new byte[1024];
144                     int bytesRead = 0;
145                     f = new File(parentOfMagicJettyHome,entry.getName());
146 
147                     if (entry.isDirectory())
148                     {
149                         f.mkdirs();
150                     }
151                     else
152                     {
153                         f.getParentFile().mkdirs();
154                         f.createNewFile();
155                         fos = new FileOutputStream(f);
156                         while ((bytesRead = eis.read(buffer)) != -1)
157                         {
158                             fos.write(buffer,0,bytesRead);
159                         }
160                     }
161                 }
162                 catch (IOException e)
163                 {
164                     e.printStackTrace();
165                     continue;
166                 }
167                 finally
168                 {
169                     if (fos != null)
170                     {
171                         try
172                         {
173                             fos.close();
174                         }
175                         catch (IOException e)
176                         {
177                         }
178                         fos = null;
179                     }
180                 }
181             }
182         }
183         finally
184         {
185             if (zipFile != null)
186                 try
187                 {
188                     zipFile.close();
189                 }
190                 catch (Throwable t)
191                 {
192                 }
193         }
194     }
195 
196     /**
197      * Look for the parent folder that contains jettyhome. Can be specified by
198      * the sys property jetty.magic.home.parent or if inside the pde will
199      * default on the configuration area. Otherwise returns null.
200      * 
201      * @return The folder inside which jettyhome should be placed.
202      */
203     private static File getParentFolderOfMagicHome()
204     {
205         // for (java.util.Map.Entry<Object, Object> e :
206         // System.getProperties().entrySet()) {
207         // System.err.println(e.getKey() + " -> " + e.getValue());
208         // }
209         String magicParent = WebappRegistrationHelper.stripQuotesIfPresent(System.getProperty("jetty.magic.home.parent"));
210         String magicParentValue = magicParent != null?System.getProperty(magicParent):null;
211         File specifiedMagicParent = magicParentValue != null?getFile(magicParentValue) // in
212                                                                                        // that
213                                                                                        // case
214                                                                                        // it
215                                                                                        // was
216                                                                                        // pointing
217                                                                                        // to
218                                                                                        // another
219                                                                                        // system
220                                                                                        // property.
221                 :getFile(magicParent); // in that case it was directly a file.
222         if (specifiedMagicParent != null && specifiedMagicParent.exists())
223         {
224             return specifiedMagicParent;
225         }
226         if (isPDEDevelopment())
227         {
228             return getConfigurationAreaDirectory();
229         }
230         return null;
231     }
232 
233     /**
234      * Be flexible with the url/uri/path that can be the value of the various
235      * system properties.
236      * 
237      * @param file
238      * @return a file. might not exist.
239      */
240     private static File getFile(String file)
241     {
242         if (file == null)
243         {
244             return null;
245         }
246         file = WebappRegistrationHelper.stripQuotesIfPresent(file);
247         try
248         {
249             if (file.startsWith("file:/"))
250             {
251                 if (!file.startsWith("file://"))
252                 {
253                     return new File(new URI(URIUtil.encodePath(file)));
254                 }
255                 else
256                 {
257                     return new File(new URL(file).toURI());
258                 }
259             }
260             else
261             {
262                 return new File(file);
263             }
264         }
265         catch (Throwable t)
266         {
267             t.printStackTrace();
268             return new File(file);
269         }
270 
271     }
272 }