View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.deployment.impl;
18  
19  import java.io.File;
20  import java.io.FileFilter;
21  import java.io.FileNotFoundException;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.ArrayList;
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import org.apache.commons.configuration.PropertiesConfiguration;
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.jetspeed.deployment.DeploymentEvent;
32  import org.apache.jetspeed.deployment.DeploymentEventListener;
33  import org.apache.jetspeed.deployment.DeploymentException;
34  import org.apache.jetspeed.deployment.DeploymentStatus;
35  import org.apache.jetspeed.util.DirectoryHelper;
36  
37  /***
38   * <p>
39   * DirectFolderEventListener
40   * </p>
41   * 
42   * @author <a href="mailto:weaver@apache.org">Scott T. Weaver </a>
43   * @version $Id: DeployDecoratorEventListener.java 516448 2007-03-09 16:25:47Z ate $
44   */
45  public class DeployDecoratorEventListener implements DeploymentEventListener
46  {
47      protected static final Log log = LogFactory.getLog("deployment");
48      protected String           deployToDir;
49  
50      public DeployDecoratorEventListener(String deployToDir) throws FileNotFoundException
51      {
52          File checkFile = new File(deployToDir);
53          if (checkFile.exists())
54          {
55              try
56              {
57                  this.deployToDir = checkFile.getCanonicalPath();
58              }
59              catch (IOException e) {}
60          }
61          else
62          {
63              throw new FileNotFoundException("The deployment directory, " + checkFile.getAbsolutePath()
64                                              + ", does not exist");
65          }
66      }
67  
68      public void initialize()
69      {
70      // nothing to do
71      }
72  
73      /***
74       * <p>
75       * invokeDeploy
76       * </p>
77       * 
78       * @see org.apache.jetspeed.deployment.DeploymentEventListener#invokeDeploy(org.apache.jetspeed.deployment.DeploymentEvent)
79       * @param event
80       * @throws DeploymentException
81       */
82      public void invokeDeploy(DeploymentEvent event) throws DeploymentException
83      {
84          String fileName = event.getName();
85          if (!fileName.endsWith(".jar") && !fileName.endsWith(".zip"))
86          {
87              return;
88          }
89  
90          // get decorator configuration if available
91          PropertiesConfiguration conf = getDecoratorConfiguration(event);
92          // silently return if configuration not available, (assumes
93          // probably not a decorator)
94          if (conf == null)
95          {
96              return;
97          }
98  
99          // process decorator by id
100         String id = conf.getString("id");
101         if (id == null)
102         {
103             throw new DeploymentException("Unable to deploy decorator, \"id\" attribute not defined in configuration");
104         }
105         
106         log.info("Found decorator deployment archive " + id);
107 
108         try
109         {
110             // construct decorator deploy path
111             String baseDeployPath = getBaseDeployPath(conf);
112             String deployPath = baseDeployPath + File.separator + id;
113             File deployPathFile = new File(deployPath);
114 
115             // undeploy decorator if it already exists and is a redeploy or
116             // skip deployment if initial deployment
117             if (deployPathFile.exists())
118             {
119                 invokeUndeploy(deployPathFile);
120             }
121 
122             // redeploy/deploy decorator w/o META_INF jar metadata
123             log.info("Deploying decorator " + id + " to " + deployPath);
124             JarExpander.expand(event.getDeploymentObject().getFile(), deployPathFile);
125             File metaInf = new File(deployPathFile, "META-INF");
126             if (metaInf.exists())
127             {
128                 DirectoryHelper cleanup = new DirectoryHelper(metaInf);
129                 cleanup.remove();
130                 cleanup.close();
131             }
132 
133             // detect language/country localized decorator components
134             final List localeSpecificDeployPathsList = getLocaleSpecificDeployPaths(deployPathFile);
135 
136             // deploy individual locale specific decorator components
137             Iterator deployPathsIter = localeSpecificDeployPathsList.iterator();
138             while (deployPathsIter.hasNext())
139             {
140                 File localeDeployPathFile = (File) deployPathsIter.next();
141 
142                 // deploy to locale specific location
143                 File deployToPathFile = new File(baseDeployPath
144                                                  + localeDeployPathFile.getPath().substring(deployPath.length())
145                                                  + File.separator + id);
146                 log.info("Deploying locale specific decorator component to " + deployToPathFile.getPath());
147                 deployToPathFile.mkdirs();
148 
149                 // deploy decorator components by moving from deployed decorator
150                 File[] filesToDeploy = localeDeployPathFile.listFiles(new FileFilter()
151                 {
152                     public boolean accept(File pathname)
153                     {
154                         return !localeSpecificDeployPathsList.contains(pathname);
155                     }
156                 });
157                 for (int i = 0; (i < filesToDeploy.length); i++)
158                 {
159                     filesToDeploy[i].renameTo(new File(deployToPathFile, filesToDeploy[i].getName()));
160                 }
161             }
162 
163             // cleanup locale specific deployment directories
164             Iterator cleanupDeployPathsIter = localeSpecificDeployPathsList.iterator();
165             while (cleanupDeployPathsIter.hasNext())
166             {
167                 File cleanupLocaleDeployPathFile = (File) cleanupDeployPathsIter.next();
168                 if (cleanupLocaleDeployPathFile.exists())
169                 {
170                     DirectoryHelper cleanup = new DirectoryHelper(cleanupLocaleDeployPathFile);
171                     cleanup.remove();
172                     cleanup.close();
173                 }
174             }
175 
176             log.info("Decorator " + id + " deployed successfuly.");
177             event.setStatus(DeploymentStatus.STATUS_OKAY);
178         }
179         catch (DeploymentException de)
180         {
181             throw de;
182         }
183         catch (Exception e)
184         {
185             throw new DeploymentException("Error deploying decorator " + id, e);
186         }
187     }
188 
189     /***
190      * <p>
191      * invokeUndeploy
192      * </p>
193      * 
194      * @throws DeploymentException
195      */
196     public void invokeUndeploy(File deployPathFile) throws DeploymentException
197     {
198 
199         if (deployPathFile == null || !deployPathFile.exists() ||
200             !deployPathFile.isDirectory() || deployPathFile.getParentFile() == null ||
201             !deployToDir.equals(deployPathFile.getParentFile().getParent()))
202         {
203             throw new DeploymentException("Cannot undeploy decorator at " + deployPathFile + ": invalid decorator path");
204         }
205 
206         String id = deployPathFile.getName();
207 
208         try
209         {
210             // undeploy decorator
211             log.info("Undeploying decorator " + id + " at " + deployPathFile.getAbsolutePath());
212 
213             // detect language/country localized decorator components
214             final List localeSpecificDeployPathsList = getLocaleSpecificDeployPaths(deployPathFile.getParentFile());
215 
216             // undeploy individual locale specific decorator components depth first
217             for (int i = localeSpecificDeployPathsList.size() - 1; i > -1; i--)
218             {
219                 File localeDeployPathFile = new File((File) localeSpecificDeployPathsList.get(i), id);
220                 if (localeDeployPathFile.exists())
221                 {
222                     log.info("Undeploying locale specific decorator component at " + localeDeployPathFile.getPath());
223                     DirectoryHelper cleanup = new DirectoryHelper(localeDeployPathFile);
224                     cleanup.remove();
225                     cleanup.close();
226                     localeDeployPathFile.getParentFile().delete();
227                 }
228             }
229 
230             // now undeploy the decorator root itself
231             DirectoryHelper cleanup = new DirectoryHelper(deployPathFile);
232             cleanup.remove();
233             cleanup.close();
234 
235             log.info("Decorator " + id + " undeployed successfuly.");
236         }
237         catch (Exception e)
238         {
239             throw new DeploymentException("Error undeploying decorator " + id, e);
240         }
241     }
242 
243     /***
244      * <p>
245      * getDecorationConfiguration
246      * </p>
247      * 
248      * @param event @
249      * @return configuration
250      * @throws DeploymentException
251      */
252     private PropertiesConfiguration getDecoratorConfiguration(DeploymentEvent event) throws DeploymentException
253     {
254         InputStream stream = null;
255         try
256         {
257             if (event.getDeploymentObject() == null)
258             {
259                 return null;
260             }
261             stream = event.getDeploymentObject().getConfiguration("decorator.properties");
262             if (stream == null)
263             {
264                 return null;
265             }
266             else
267             {
268                 PropertiesConfiguration configuration = new PropertiesConfiguration();
269                 configuration.load(stream);
270                 return configuration;
271             }
272         }
273         catch (Exception e1)
274         {
275             throw new DeploymentException("Error reading decorator.properties from " + event.getPath(), e1);
276         }
277         finally
278         {
279             if (stream != null)
280             {
281                 try
282                 {
283                     stream.close();
284                 }
285                 catch (IOException e)
286                 {
287 
288                 }
289             }
290         }
291     }
292 
293     /***
294      * <p>
295      * getBaseDeployPath
296      * </p>
297      * 
298      * @param configuration
299      * @return base deploy path
300      */
301     private String getBaseDeployPath(PropertiesConfiguration configuration)
302     {
303         // construct decorator deploy base path
304         String layoutType = configuration.getString("decorates", "generic");
305         if (layoutType.equalsIgnoreCase("any"))
306         {
307             layoutType = "generic";
308         }
309         return deployToDir + File.separator + layoutType ;
310     }
311 
312     /***
313      * <p>
314      * getLocaleSpecificDeployPaths
315      * </p>
316      * 
317      * @param rootPath
318      * @return locale paths list
319      */
320     private List getLocaleSpecificDeployPaths(File rootPath)
321     {
322         // detect language/country localized deploy paths
323         List localeSpecificDeployPathsList = new ArrayList();
324         File[] localeLanguageSpecificRoots = rootPath.listFiles(new FileFilter()
325         {
326             public boolean accept(File pathname)
327             {
328                 // filter language code dirs, (assume length test is accurate enough)
329                 return (pathname.isDirectory() && (pathname.getName().length() == 2));
330             }
331         });
332         for (int i = 0; (i < localeLanguageSpecificRoots.length); i++)
333         {
334             localeSpecificDeployPathsList.add(localeLanguageSpecificRoots[i]);
335             File[] localeCountrySpecificPaths = localeLanguageSpecificRoots[i].listFiles(new FileFilter()
336             {
337                 public boolean accept(File pathname)
338                 {
339                     // filter country code dirs, (assume length test is accurate enough)
340                     return (pathname.isDirectory() && (pathname.getName().length() == 2));
341                 }
342             });
343             for (int j = 0; (j < localeCountrySpecificPaths.length); j++)
344             {
345                 localeSpecificDeployPathsList.add(localeCountrySpecificPaths[j]);
346             }
347         }
348         return localeSpecificDeployPathsList;
349     }
350 }