001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.maven;
017:
018: // J2SE dependencies
019: import java.io.*;
020: import java.util.Set;
021: import java.util.Iterator;
022: import java.util.zip.ZipEntry;
023: import java.util.zip.ZipOutputStream;
024:
025: // Maven and Plexus dependencies
026: import org.apache.maven.plugin.AbstractMojo;
027: import org.apache.maven.plugin.MojoExecutionException;
028: import org.apache.maven.project.MavenProject;
029: import org.apache.maven.artifact.Artifact;
030:
031: // Note: javadoc in class and fields descriptions must be XHTML.
032: /**
033: * Creates a <code>.oxt</code> package for <a href="http://www.openoffice.org">OpenOffice</a>
034: * addins.
035: *
036: * @goal unopkg
037: * @phase package
038: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/build/maven/unopkg/src/main/java/org/geotools/maven/UnoPkg.java $
039: * @version $Id: UnoPkg.java 25335 2007-04-25 13:46:57Z desruisseaux $
040: * @author Martin Desruisseaux
041: */
042: public class UnoPkg extends AbstractMojo implements FilenameFilter {
043: /**
044: * The encoding for text files to read and write.
045: */
046: private static final String ENCODING = "UTF-8";
047:
048: /**
049: * The string to replace by the final name.
050: */
051: private static final String SUBSTITUTE = "${project.build.finalName}";
052:
053: /**
054: * Directory where the source files are located. The plugin will looks for the
055: * <code>META-INF/manifest.xml</code> and <code>*.rdb</code> files in this directory.
056: *
057: * @parameter expression="${basedir}/src/main/unopkg"
058: * @required
059: */
060: private String sourceDirectory;
061:
062: /**
063: * Directory where the output <code>oxt</code> file will be located.
064: *
065: * @parameter expression="${project.build.directory}"
066: * @required
067: */
068: private String outputDirectory;
069:
070: /**
071: * In <code>META-INF/manifest.xml</code>, replaces all occurences of
072: * <code>${project.build.finalName}</code> by this value.
073: *
074: * @parameter expression="${project.build.finalName}"
075: * @required
076: */
077: private String finalName;
078:
079: /**
080: * The name for the <code>oxt</code> file to create.
081: *
082: * @parameter expression="${project.build.finalName}"
083: * @required
084: */
085: private String oxtName;
086:
087: /**
088: * Project dependencies.
089: *
090: * @parameter expression="${project.artifacts}"
091: * @required
092: */
093: private Set/*<Artifact>*/dependencies;
094:
095: /**
096: * The Maven project running this plugin.
097: *
098: * @parameter expression="${project}"
099: * @required
100: */
101: private MavenProject project;
102:
103: /**
104: * The prefix to be added before JAR file names.
105: * To be determined by heuristic rule.
106: */
107: private transient String prefix;
108:
109: /**
110: * Apply prefix only for dependencies of this group.
111: */
112: private transient String prefixGroup;
113:
114: /**
115: * Tests if a specified file should be included in a file list.
116: *
117: * @param directory the directory in which the file was found.
118: * @param name the name of the file.
119: */
120: public boolean accept(final File directory, final String name) {
121: return name.endsWith(".jar") || name.endsWith(".JAR")
122: || name.endsWith(".rdb") || name.endsWith(".RDB");
123: }
124:
125: /**
126: * Generates the {@code .oxt} file from all {@code .jar} files found in the target directory.
127: *
128: * @throws MojoExecutionException if the plugin execution failed.
129: */
130: public void execute() throws MojoExecutionException {
131: final int i = finalName.indexOf(project.getArtifactId());
132: prefix = (i >= 0) ? finalName.substring(0, i) : "";
133: prefixGroup = project.getGroupId();
134: try {
135: createPackage();
136: } catch (IOException e) {
137: throw new MojoExecutionException(
138: "Error creating the oxt file.", e);
139: }
140: }
141:
142: /**
143: * Creates the {@code .oxt} file.
144: */
145: private void createPackage() throws IOException {
146: final String manifestName = "META-INF/manifest.xml";
147: final File outputDirectory = new File(this .outputDirectory);
148: final File zipFile = new File(outputDirectory, oxtName + ".oxt");
149: final File manifestFile = new File(sourceDirectory,
150: manifestName);
151: final File[] jars = outputDirectory.listFiles(this );
152: final File[] rdbs = new File(sourceDirectory).listFiles(this );
153: final ZipOutputStream out = new ZipOutputStream(
154: new FileOutputStream(zipFile));
155: if (manifestFile.isFile()) {
156: copyFiltered(manifestFile, out, manifestName);
157: }
158: /*
159: * Copies the RDB files.
160: */
161: for (int i = 0; i < rdbs.length; i++) {
162: copy(rdbs[i], out, null);
163: }
164: /*
165: * Copies the JAR (and any additional JARs provided in the output directory).
166: */
167: for (int i = 0; i < jars.length; i++) {
168: copy(jars[i], out, null);
169: }
170: /*
171: * Copies the dependencies.
172: */
173: if (dependencies != null) {
174: for (final Iterator it = dependencies.iterator(); it
175: .hasNext();) {
176: final Artifact artifact = (Artifact) it.next();
177: final String scope = artifact.getScope();
178: if (scope != null && // Maven 2.0.6 bug?
179: (scope.equalsIgnoreCase(Artifact.SCOPE_COMPILE) || scope
180: .equalsIgnoreCase(Artifact.SCOPE_RUNTIME))) {
181: final File file = artifact.getFile();
182: String name = file.getName();
183: if (artifact.getGroupId().startsWith(prefixGroup)
184: && !name.startsWith(prefix)) {
185: name = prefix + name;
186: }
187: copy(file, out, name);
188: }
189: }
190: }
191: out.close();
192: }
193:
194: /**
195: * Copies the content of the specified binary file to the specified output stream.
196: */
197: private static void copy(final File file,
198: final ZipOutputStream out, String name) throws IOException {
199: if (name == null) {
200: name = file.getName();
201: }
202: final ZipEntry entry = new ZipEntry(name);
203: out.putNextEntry(entry);
204: final InputStream in = new FileInputStream(file);
205: final byte[] buffer = new byte[4 * 1024];
206: int length;
207: while ((length = in.read(buffer)) >= 0) {
208: out.write(buffer, 0, length);
209: }
210: in.close();
211: out.closeEntry();
212: }
213:
214: /**
215: * Copies the content of the specified ASCII file to the specified output stream.
216: */
217: private void copyFiltered(final File file,
218: final ZipOutputStream out, String name) throws IOException {
219: if (name == null) {
220: name = file.getName();
221: }
222: final ZipEntry entry = new ZipEntry(name);
223: out.putNextEntry(entry);
224: final Writer writer = new OutputStreamWriter(out, ENCODING);
225: final BufferedReader in = new BufferedReader(
226: new InputStreamReader(new FileInputStream(file),
227: ENCODING));
228: String line;
229: while ((line = in.readLine()) != null) {
230: int r = -1;
231: while ((r = line.indexOf(SUBSTITUTE, r + 1)) >= 0) {
232: line = line.substring(0, r) + finalName
233: + line.substring(r + SUBSTITUTE.length());
234: }
235: writer.write(line);
236: writer.write('\n');
237: }
238: in.close();
239: writer.flush();
240: out.closeEntry();
241: }
242: }
|