View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.maven.plugin;
21  
22  import org.apache.maven.artifact.DependencyResolutionRequiredException;
23  import org.apache.maven.plugin.MojoExecutionException;
24  import org.codehaus.plexus.archiver.ArchiverException;
25  import org.codehaus.plexus.archiver.UnArchiver;
26  import org.codehaus.plexus.archiver.manager.ArchiverManager;
27  import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
28  import org.codehaus.plexus.archiver.zip.ZipEntry;
29  import org.codehaus.plexus.archiver.zip.ZipFile;
30  import org.codehaus.plexus.util.FileUtils;
31  import org.codehaus.plexus.util.IOUtil;
32  import org.codehaus.plexus.util.ReaderFactory;
33  import org.codehaus.plexus.util.xml.XmlStreamReader;
34  import org.codehaus.plexus.util.xml.Xpp3Dom;
35  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
36  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
37  
38  import java.io.ByteArrayInputStream;
39  import java.io.File;
40  import java.io.IOException;
41  import java.io.StringReader;
42  import java.io.StringWriter;
43  import java.util.Enumeration;
44  import java.util.Iterator;
45  import java.util.Locale;
46  import java.util.Properties;
47  
48  /**
49   * @goal resources
50   * @phase process-resources
51   * @requiresDependencyResolution runtime
52   */
53  public class UnPackThemeMojo extends AbstractThemeMojo {
54    /**
55     * To look up Archiver/UnArchiver implementations
56     *
57     * @parameter expression="${component.org.codehaus.plexus.archiver.manager.ArchiverManager}"
58     * @required
59     */
60    private ArchiverManager archiverManager;
61  
62    /**
63     * Directory to unpack JARs into if needed
64     *
65     * @parameter expression="${project.build.directory}/theme/work"
66     * @required
67     */
68    private File workDirectory;
69  
70    /**
71     * The directory where the webapp is built.
72     *
73     * @parameter expression="${project.build.directory}/${project.build.finalName}"
74     * @required
75     */
76    private File webappDirectory;
77  
78    /**
79     * Don't use the versioned information of the themes..
80     *
81     * @parameter
82     */
83    private boolean ignoreVersioned;
84  
85  
86    private String getThemeDescriptor(File jarFile) throws MojoExecutionException {
87      ZipFile zip = null;
88      try {
89        zip = new ZipFile(jarFile);
90        Enumeration files = zip.getEntries();
91        while (files.hasMoreElements()) {
92          ZipEntry nextEntry = (ZipEntry) files.nextElement();
93          if (nextEntry == null || nextEntry.isDirectory()) {
94            continue;
95          }
96          String name = nextEntry.getName();
97          if (name.equals("META-INF/tobago-theme.xml") || name.equals("META-INF/tobago-config.xml")) {
98            XmlStreamReader xsr = null;
99            try {
100             StringWriter stringWriter = new StringWriter();
101             xsr = ReaderFactory.newXmlReader(zip.getInputStream(nextEntry));
102             IOUtil.copy(xsr, stringWriter);
103             return stringWriter.toString();
104           } finally {
105             IOUtil.close(xsr);
106           }
107         }
108       }
109     } catch (IOException e) {
110       throw new MojoExecutionException("Error find ThemeDescriptor in " + jarFile, e);
111     } finally {
112       if (zip != null) {
113         try {
114           zip.close();
115         } catch (IOException e) {
116           // ignore
117         }
118       }
119     }
120     return null;
121   }
122 
123   public void execute() throws MojoExecutionException {
124     try {
125       Iterator artifacts =  getProject().getRuntimeClasspathElements().iterator();
126       if (!workDirectory.exists()) {
127         workDirectory.mkdirs();
128       }
129       while (artifacts.hasNext()) {
130 
131         String artifact = (String) artifacts.next();
132         if (getLog().isDebugEnabled()) {
133           getLog().debug("Testing jar "+ artifact);
134         }
135 
136         File file = new File(artifact);
137         if (file.isFile() && artifact.endsWith(".jar")) {
138           String descriptor = getThemeDescriptor(file);
139           if (descriptor != null) {
140 
141             String name = file.getName();
142             File tempLocation = new File(workDirectory, name.substring(0, name.length() - 4));
143             boolean process = false;
144             if (!tempLocation.exists()) {
145               tempLocation.mkdirs();
146               process = true;
147             } else if (file.lastModified() > tempLocation.lastModified()) {
148               process = true;
149             }
150             if (process) {
151               try {
152                 unpack(file, tempLocation);
153                 String version = null;
154                 String resourcePath = null;
155                 try {
156                   Xpp3Dom xpp3Dom = Xpp3DomBuilder.build(new StringReader(descriptor));
157                   Xpp3Dom themeDefinitions = xpp3Dom.getChild("theme-definitions");
158                   if (themeDefinitions != null && !ignoreVersioned) {
159                     for (Xpp3Dom themeDefinition : themeDefinitions.getChildren()) {
160                       Xpp3Dom versionedDom = themeDefinition.getChild("versioned");
161                       if (versionedDom != null) {
162                         boolean versioned = Boolean.parseBoolean(versionedDom.getValue());
163                         if (versioned) {
164                           Xpp3Dom resourcePathDom = themeDefinition.getChild("resource-path");
165                           resourcePath = resourcePathDom.getValue();
166                           Properties properties = new Properties();
167                           String metaInf = tempLocation + "/META-INF/MANIFEST.MF";
168                           properties.load(new ByteArrayInputStream(FileUtils.fileRead(metaInf).getBytes()));
169                           version = properties.getProperty("Implementation-Version");
170                           if (version == null) {
171                             getLog().error("No Implementation-Version found in Manifest-File for theme: '"
172                                 + name + "'.");
173                           }
174                         }
175                       }
176                     }
177                   }
178                 } catch (IOException e) {
179                   getLog().error(e);
180                 } catch (XmlPullParserException e) {
181                   getLog().error(e);
182                 }
183                 if (getLog().isDebugEnabled()) {
184                   getLog().debug("Expanding theme: "+ name);
185                   getLog().debug("Version: " + version);
186                   getLog().debug("ResourcePath: " + resourcePath);
187                 }
188                 String[] fileNames = getThemeFiles(tempLocation);
189                 for (int i = 0, fileNamesLength = fileNames.length; i < fileNamesLength; i++) {
190                   String fileName = fileNames[i];
191                   File fromFile = new File(tempLocation, fileName);
192                   String toFileName = fileName;
193                   if (resourcePath != null && version != null && toFileName.startsWith(resourcePath)
194                           && !fileName.endsWith("blank.html")) {
195                     toFileName = resourcePath + "/" + version + "/" +toFileName.substring(resourcePath.length()+1);
196                   }
197                   if (getLog().isDebugEnabled()) {
198                     getLog().debug("Copy file " + fromFile + " to: " + toFileName);
199                   }
200                   File toFile = new File(webappDirectory, toFileName);
201                   try {
202                     FileUtils.copyFile(fromFile, toFile);
203                   } catch (IOException e) {
204                     throw new MojoExecutionException("Error copy file: " + fromFile + " to: " + toFile, e);
205                   }
206                 }
207               } catch (NoSuchArchiverException e) {
208                 getLog().info("Skip unpacking dependency file with unknown extension: " + file.getPath());
209               }
210             }
211           }
212         }
213       }
214     } catch (DependencyResolutionRequiredException drre) {
215       throw new MojoExecutionException(drre.getMessage(), drre);
216     }
217   }
218 
219   private void unpack(File file, File location)
220       throws MojoExecutionException, NoSuchArchiverException {
221     String archiveExt = FileUtils.getExtension(file.getAbsolutePath()).toLowerCase(Locale.ENGLISH);
222     try {
223       UnArchiver unArchiver = archiverManager.getUnArchiver(archiveExt);
224       unArchiver.setSourceFile(file);
225       unArchiver.setDestDirectory(location);
226       unArchiver.extract();
227     } catch (ArchiverException e) {
228       throw new MojoExecutionException("Error unpacking file: " + file + "to: " + location, e);
229     }
230   }
231 }
232 
233