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.maven.plugin;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Locale;
27  
28  
29  import org.eclipse.jetty.util.log.Log;
30  import org.eclipse.jetty.util.log.Logger;
31  import org.eclipse.jetty.util.resource.Resource;
32  import org.eclipse.jetty.util.resource.ResourceCollection;
33  import org.eclipse.jetty.webapp.WebAppClassLoader;
34  import org.eclipse.jetty.webapp.WebAppContext;
35  import org.eclipse.jetty.webapp.WebInfConfiguration;
36  
37  
38  
39  /**
40   * MavenWebInfConfiguration
41   * 
42   * WebInfConfiguration to take account of overlaid wars expressed as project dependencies and
43   * potentiall configured via the maven-war-plugin.
44   *
45   */
46  public class MavenWebInfConfiguration extends WebInfConfiguration
47  {
48      private static final Logger LOG = Log.getLogger(MavenWebInfConfiguration.class);
49  
50      public static final String RESOURCE_BASES_POST_OVERLAY = "org.eclipse.jetty.resource.postOverlay";
51      protected static int COUNTER = 0; 
52      protected Resource _originalResourceBase;
53      protected List<Resource>  _unpackedOverlayResources;
54    
55      
56      
57      
58      /** 
59       * @see org.eclipse.jetty.webapp.WebInfConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
60       */
61      public void configure(WebAppContext context) throws Exception
62      {
63          JettyWebAppContext jwac = (JettyWebAppContext)context;
64          
65          //put the classes dir and all dependencies into the classpath
66          if (jwac.getClassPathFiles() != null)
67          {
68              if (LOG.isDebugEnabled()) LOG.debug("Setting up classpath ...");
69              Iterator itor = jwac.getClassPathFiles().iterator();
70              while (itor.hasNext())
71                  ((WebAppClassLoader)context.getClassLoader()).addClassPath(((File)itor.next()).getCanonicalPath());
72          }
73          
74          super.configure(context);
75          
76          // knock out environmental maven and plexus classes from webAppContext
77          String[] existingServerClasses = context.getServerClasses();
78          String[] newServerClasses = new String[2+(existingServerClasses==null?0:existingServerClasses.length)];
79          newServerClasses[0] = "org.apache.maven.";
80          newServerClasses[1] = "org.codehaus.plexus.";
81          System.arraycopy( existingServerClasses, 0, newServerClasses, 2, existingServerClasses.length );
82          if (LOG.isDebugEnabled())
83          {
84              LOG.debug("Server classes:");
85              for (int i=0;i<newServerClasses.length;i++)
86                  LOG.debug(newServerClasses[i]);
87          }
88          context.setServerClasses( newServerClasses ); 
89      }
90  
91      
92      
93  
94      /** 
95       * @see org.eclipse.jetty.webapp.WebInfConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext)
96       */
97      public void preConfigure(WebAppContext context) throws Exception
98      {
99          super.preConfigure(context);
100 
101     }
102     
103     
104     
105     
106     /** 
107      * @see org.eclipse.jetty.webapp.AbstractConfiguration#postConfigure(org.eclipse.jetty.webapp.WebAppContext)
108      */
109     public void postConfigure(WebAppContext context) throws Exception
110     {
111         super.postConfigure(context);
112     }
113 
114 
115     
116     
117     /** 
118      * @see org.eclipse.jetty.webapp.WebInfConfiguration#deconfigure(org.eclipse.jetty.webapp.WebAppContext)
119      */
120     public void deconfigure(WebAppContext context) throws Exception
121     {   
122         super.deconfigure(context);
123         //restore whatever the base resource was before we might have included overlaid wars
124         context.setBaseResource(_originalResourceBase);
125         //undo the setting of the overlayed resources
126         context.removeAttribute(RESOURCE_BASES_POST_OVERLAY);
127     }
128 
129     
130     
131 
132     /** 
133      * @see org.eclipse.jetty.webapp.WebInfConfiguration#unpack(org.eclipse.jetty.webapp.WebAppContext)
134      */
135     @Override
136     public void unpack(WebAppContext context) throws IOException
137     {
138         //Unpack and find base resource as normal
139         super.unpack(context);
140         
141         //Get the base resource for the "virtual" webapp
142         _originalResourceBase = context.getBaseResource();
143 
144         JettyWebAppContext jwac = (JettyWebAppContext)context;
145 
146         //determine sequencing of overlays
147         _unpackedOverlayResources = new ArrayList<Resource>();
148 
149        
150 
151         if (jwac.getOverlays() != null && !jwac.getOverlays().isEmpty())
152         {
153             List<Resource> resourceBaseCollection = new ArrayList<Resource>();
154 
155             for (Overlay o:jwac.getOverlays())
156             {
157                 //can refer to the current project in list of overlays for ordering purposes
158                 if (o.getConfig() != null && o.getConfig().isCurrentProject() && _originalResourceBase.exists())
159                 {
160                     resourceBaseCollection.add(_originalResourceBase); 
161                     LOG.debug("Adding virtual project to resource base list");
162                     continue;
163                 }
164 
165                 Resource unpacked = unpackOverlay(jwac,o);
166                 _unpackedOverlayResources.add(unpacked); //remember the unpacked overlays for later so we can delete the tmp files
167                 resourceBaseCollection.add(unpacked); //add in the selectively unpacked overlay in the correct order to the webapps resource base
168                 LOG.debug("Adding "+unpacked+" to resource base list");
169             }
170 
171             if (!resourceBaseCollection.contains(_originalResourceBase) && _originalResourceBase.exists())
172             {
173                 if (jwac.getBaseAppFirst())
174                 {
175                     LOG.debug("Adding virtual project first in resource base list");
176                     resourceBaseCollection.add(0, _originalResourceBase);
177                 }
178                 else
179                 {
180                     LOG.debug("Adding virtual project last in resource base list");
181                     resourceBaseCollection.add(_originalResourceBase);
182                 }
183             }
184             jwac.setBaseResource(new ResourceCollection(resourceBaseCollection.toArray(new Resource[resourceBaseCollection.size()])));
185         }
186         
187         jwac.setAttribute(RESOURCE_BASES_POST_OVERLAY, jwac.getBaseResource());
188     }
189 
190 
191     /**
192      * Get the jars to examine from the files from which we have
193      * synthesized the classpath. Note that the classpath is not
194      * set at this point, so we cannot get them from the classpath.
195      * @param context
196      * @return the list of jars found
197      */
198     @Override
199     protected List<Resource> findJars (WebAppContext context)
200     throws Exception
201     {
202         List<Resource> list = new ArrayList<Resource>();
203         JettyWebAppContext jwac = (JettyWebAppContext)context;
204         if (jwac.getClassPathFiles() != null)
205         {
206             for (File f: jwac.getClassPathFiles())
207             {
208                 if (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".jar"))
209                 {
210                     try
211                     {
212                         list.add(Resource.newResource(f.toURI()));
213                     }
214                     catch (Exception e)
215                     {
216                         LOG.warn("Bad url ", e);
217                     }
218                 }
219             }
220         }
221 
222         List<Resource> superList = super.findJars(context);
223         if (superList != null)
224             list.addAll(superList);
225         return list;
226     }
227     
228     
229     
230     
231 
232     /** 
233      * Add in the classes dirs from test/classes and target/classes
234      * @see org.eclipse.jetty.webapp.WebInfConfiguration#findClassDirs(org.eclipse.jetty.webapp.WebAppContext)
235      */
236     @Override
237     protected List<Resource> findClassDirs(WebAppContext context) throws Exception
238     {
239         List<Resource> list = new ArrayList<Resource>();
240         
241         JettyWebAppContext jwac = (JettyWebAppContext)context;
242         if (jwac.getClassPathFiles() != null)
243         {
244             for (File f: jwac.getClassPathFiles())
245             {
246                 if (f.exists() && f.isDirectory())
247                 {
248                     try
249                     {
250                         list.add(Resource.newResource(f.toURI()));
251                     }
252                     catch (Exception e)
253                     {
254                         LOG.warn("Bad url ", e);
255                     }
256                 }
257             }
258         }
259         
260         List<Resource> classesDirs = super.findClassDirs(context);
261         if (classesDirs != null)
262             list.addAll(classesDirs);
263         return list;
264     }
265 
266 
267 
268 
269 
270     protected  Resource unpackOverlay (WebAppContext context, Overlay overlay)
271     throws IOException
272     {
273         LOG.debug("Unpacking overlay: " + overlay);
274         
275         if (overlay.getResource() == null)
276             return null; //nothing to unpack
277    
278         //Get the name of the overlayed war and unpack it to a dir of the
279         //same name in the temporary directory
280         String name = overlay.getResource().getName();
281         if (name.endsWith("!/"))
282             name = name.substring(0,name.length()-2);
283         int i = name.lastIndexOf('/');
284         if (i>0)
285             name = name.substring(i+1,name.length());
286         name = name.replace('.', '_');
287         name = name+(++COUNTER); //add some digits to ensure uniqueness
288         File dir = new File(context.getTempDirectory(), name); 
289         
290         //if specified targetPath, unpack to that subdir instead
291         File unpackDir = dir;
292         if (overlay.getConfig() != null && overlay.getConfig().getTargetPath() != null)
293             unpackDir = new File (dir, overlay.getConfig().getTargetPath());
294         
295         overlay.getResource().copyTo(unpackDir);
296         //use top level of unpacked content
297         Resource unpackedOverlay = Resource.newResource(dir.getCanonicalPath());
298         
299         LOG.debug("Unpacked overlay: "+overlay+" to "+unpackedOverlay);
300         return  unpackedOverlay;
301     }
302 }