Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 127375 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/update/core/FeatureContentProvider.java (-8 / +10 lines)
Lines 109-115 Link Here
109
109
110
	// hashtable of locks
110
	// hashtable of locks
111
	private static Hashtable locks = new Hashtable();
111
	private static Hashtable locks = new Hashtable();
112
112
	
113
	protected static Object getLock(String key) {
114
		synchronized (lock) {
115
			if (locks.get(key) == null)
116
				locks.put(key, key);
117
			return locks.get(key);
118
		}
119
	}
120
	
113
	/**
121
	/**
114
	 * Feature content provider constructor
122
	 * Feature content provider constructor
115
	 * 
123
	 * 
Lines 179-191 Link Here
179
		// is still copying into it
187
		// is still copying into it
180
		File localFile = null;
188
		File localFile = null;
181
		FileFragment localFileFragment = null;
189
		FileFragment localFileFragment = null;
182
		Object keyLock = null;
190
		Object keyLock = getLock(key);
183
		synchronized (lock) {
184
			if (locks.get(key) == null)
185
				locks.put(key, key);
186
			keyLock = locks.get(key);
187
		}
188
189
		synchronized (keyLock) {
191
		synchronized (keyLock) {
190
			localFile = Utilities.lookupLocalFile(key);
192
			localFile = Utilities.lookupLocalFile(key);
191
			if (localFile != null) {
193
			if (localFile != null) {
(-)src/org/eclipse/update/internal/core/FeaturePackagedContentProvider.java (-6 / +65 lines)
Lines 10-22 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.update.internal.core;
11
package org.eclipse.update.internal.core;
12
import java.io.*;
12
import java.io.*;
13
import java.net.*;
13
import java.net.URL;
14
import java.util.*;
14
import java.util.*;
15
15
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.*;
17
import org.eclipse.osgi.util.NLS;
16
import org.eclipse.osgi.util.NLS;
18
import org.eclipse.update.core.*;
17
import org.eclipse.update.core.*;
19
import org.eclipse.update.internal.security.*;
18
import org.eclipse.update.core.model.SiteModel;
19
import org.eclipse.update.internal.security.JarVerifier;
20
import org.eclipse.update.jarprocessor.JarProcessor;
20
21
21
/**
22
/**
22
 * Content Provider of a Feature Package
23
 * Content Provider of a Feature Package
Lines 26-32 Link Here
26
	private ContentReference localManifest = null;
27
	private ContentReference localManifest = null;
27
	private ContentReference[] localFeatureFiles = new ContentReference[0];
28
	private ContentReference[] localFeatureFiles = new ContentReference[0];
28
	private IVerifier jarVerifier = null;
29
	private IVerifier jarVerifier = null;
29
30
	private SiteModel siteModel = null;
30
	/*
31
	/*
31
	 * filter for file with .jar
32
	 * filter for file with .jar
32
	 */
33
	 */
Lines 58-63 Link Here
58
		return jarVerifier;
59
		return jarVerifier;
59
	}
60
	}
60
61
62
	public void setFeature(IFeature feature) {
63
		super.setFeature(feature);
64
		ISite featureSite = feature.getSite();
65
		if(featureSite instanceof SiteModel){
66
			siteModel = (SiteModel) featureSite;
67
		}
68
	}
61
	/*
69
	/*
62
	 * @see IFeatureContentProvider#getFeatureManifestReference()
70
	 * @see IFeatureContentProvider#getFeatureManifestReference()
63
	 */
71
	 */
Lines 162-174 Link Here
162
		URL url = (siteContentProvider == null) ? null : siteContentProvider.getArchiveReference(archiveID);
170
		URL url = (siteContentProvider == null) ? null : siteContentProvider.getArchiveReference(archiveID);
163
171
164
		try {
172
		try {
165
			references[0] = asLocalReference(new JarContentReference(archiveID, url), monitor);
173
			references[0] = retrieveLocalJar(new JarContentReference(archiveID, url), monitor);
166
		} catch (IOException e) {
174
		} catch (IOException e) {
167
			throw errorRetrieving(archiveID, references[0], e);
175
			throw errorRetrieving(archiveID, references[0], e);
168
		}
176
		}
169
		return references;
177
		return references;
170
	}
178
	}
171
179
180
	private ContentReference retrieveLocalJar(JarContentReference reference, InstallMonitor monitor) throws IOException, CoreException {
181
		//If the site does not support pack200, just get the jar as normal
182
		if(siteModel == null || !siteModel.supportsPack200() || !JarProcessor.canPerformUnpack()) {
183
			return asLocalReference(reference, monitor);
184
		}
185
		
186
		ContentReference packedRef = null;
187
		String key = reference.toString();
188
		Object jarLock = getLock(key);
189
		synchronized (jarLock) {
190
			//do we have this jar already?
191
			File localFile = Utilities.lookupLocalFile(key);
192
			if (localFile != null) {
193
				// check if the cached file is still valid (no newer version on server)
194
				if (UpdateManagerUtils.isSameTimestamp(reference.asURL(), localFile.lastModified()))
195
					return reference.createContentReference(reference.getIdentifier(), localFile);
196
			}
197
198
			try {
199
				//don't have jar, check for pack.gz
200
				URL packGZURL = new URL(reference.asURL().toExternalForm() + ".pack.gz"); //$NON-NLS-1$
201
				packedRef = asLocalReference(new JarContentReference(reference.getIdentifier(), packGZURL), monitor);
202
			} catch (IOException e) {
203
				//no pack.gz
204
			}
205
		}
206
		if (packedRef == null) {
207
			//no pack.gz on server, get normal jar
208
			return asLocalReference(reference, monitor);
209
		}
210
211
		synchronized (jarLock) {
212
			Object packedLock = getLock(packedRef.toString());
213
			synchronized (packedLock) {
214
				File tempFile = packedRef.asFile();
215
				long timeStamp = tempFile.lastModified();
216
217
				JarProcessor processor = JarProcessor.getUnpackProcessor(null);
218
				processor.setWorkingDirectory(tempFile.getParent());
219
220
				File packedFile = new File(tempFile.toString() + ".pack.gz"); //$NON-NLS-1$
221
				tempFile.renameTo(packedFile);
222
				//unpacking the jar will strip the ".pack.gz" and leave us back with the original filename
223
				processor.processJar(packedFile);
224
225
				tempFile.setLastModified(timeStamp);
226
				Utilities.mapLocalFile(key, tempFile);
227
			}
228
		}
229
		return packedRef;
230
	}
172
	/*
231
	/*
173
	 * @see IFeatureContentProvider#getNonPluginEntryArchiveReferences(INonPluginEntry)
232
	 * @see IFeatureContentProvider#getNonPluginEntryArchiveReferences(INonPluginEntry)
174
	 */
233
	 */
(-)src/org/eclipse/update/core/model/SiteModel.java (+19 lines)
Lines 45-50 Link Here
45
	private URL locationURL;
45
	private URL locationURL;
46
	private String mirrorsURLString;
46
	private String mirrorsURLString;
47
	private ConfiguredSiteModel configuredSiteModel;
47
	private ConfiguredSiteModel configuredSiteModel;
48
	private boolean pack200 = false;
48
49
49
	/**
50
	/**
50
	 * Creates an uninitialized site model object.
51
	 * Creates an uninitialized site model object.
Lines 447-450 Link Here
447
		assertIsWriteable();
448
		assertIsWriteable();
448
		this.mirrorsURLString = mirrorsURL;
449
		this.mirrorsURLString = mirrorsURL;
449
	}
450
	}
451
	
452
	/**
453
	 * Get whether or not this site may contain jars packed with pack200.
454
	 * The packed version of foo.jar, is expected to be foo.jar.pack.gz
455
	 * @return
456
	 */
457
	public boolean supportsPack200() {
458
		return pack200;
459
	}
460
	
461
	/**
462
	 * Set whether or not this site may contain jars packed with pack200
463
	 * The packed version of foo.jar is expected to be foo.jar.pack.gz
464
	 * @param pack
465
	 */
466
	public void setSupportsPack200(boolean pack){
467
		pack200 = pack;
468
	}
450
}
469
}
(-)src/org/eclipse/update/core/model/DefaultSiteParser.java (+5 lines)
Lines 513-518 Link Here
513
				site.setMirrorsURLString(mirrorsURL);
513
				site.setMirrorsURLString(mirrorsURL);
514
		}
514
		}
515
		
515
		
516
		String pack200 = attributes.getValue("pack200"); //$NON-NLS-1$
517
		if(pack200 != null && new Boolean(pack200).booleanValue()){
518
			site.setSupportsPack200(true);
519
		}
520
		
516
		if ( (site instanceof ExtendedSite) && (Boolean.getBoolean(attributes.getValue("digestURL")))) { //$NON-NLS-1$
521
		if ( (site instanceof ExtendedSite) && (Boolean.getBoolean(attributes.getValue("digestURL")))) { //$NON-NLS-1$
517
			ExtendedSite extendedSite = (ExtendedSite) site;
522
			ExtendedSite extendedSite = (ExtendedSite) site;
518
			extendedSite.setDigestExist(true);
523
			extendedSite.setDigestExist(true);
(-)src/org/eclipse/update/jarprocessor/internal/CommandStep.java (+84 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM - Initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.update.jarprocessor.internal;
12
13
import java.io.File;
14
import java.io.IOException;
15
import java.util.Properties;
16
import org.eclipse.update.jarprocessor.IProcessStep;
17
18
/**
19
 * @author aniefer
20
 *
21
 */
22
public class CommandStep implements IProcessStep {
23
	private String command = null;
24
	private String extension = null;
25
	private Properties options = null;
26
	
27
	public CommandStep(Properties options, String command, String extension) {
28
		this.command = command;
29
		this.extension = extension;
30
		this.options = options;
31
	}
32
33
	/* (non-Javadoc)
34
	 * @see org.eclipse.update.jarprocessor.IProcessStep#recursionEffect(java.lang.String)
35
	 */
36
	public String recursionEffect(String entryName) {
37
		if (entryName.endsWith(extension))
38
			return entryName;
39
		return null;
40
	}
41
42
	/* (non-Javadoc)
43
	 * @see org.eclipse.update.jarprocessor.IProcessStep#preProcess(java.io.File, java.io.File)
44
	 */
45
	public File preProcess(File input, File workingDirectory) {
46
		return null;
47
	}
48
49
	/* (non-Javadoc)
50
	 * @see org.eclipse.update.jarprocessor.IProcessStep#postProcess(java.io.File, java.io.File)
51
	 */
52
	public File postProcess(File input, File workingDirectory) {
53
		if(command != null) {
54
			try {
55
				String[] cmd = new String[] {command, input.getCanonicalPath()};
56
				int result = execute(cmd);
57
				if(result == 0)
58
					return input;
59
			} catch (IOException e) {
60
				//boo
61
				e.printStackTrace();
62
			}
63
		}
64
		return input;
65
	}
66
67
	public static int execute(String[] cmd) throws IOException {
68
		Runtime runtime = Runtime.getRuntime();
69
		Process proc = runtime.exec(cmd);
70
		try {
71
			int result = proc.waitFor();
72
			return result;
73
		} catch (InterruptedException e) {
74
			//ignore
75
		}
76
		return -1;
77
	}
78
	
79
	public Properties getOptions() {
80
		if(options == null)
81
			options = new Properties();
82
		return options;
83
	}
84
}
(-)src/org/eclipse/update/jarprocessor/Main.java (+119 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM - Initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.update.jarprocessor;
12
13
import java.io.*;
14
import java.util.zip.ZipException;
15
import org.eclipse.update.jarprocessor.internal.*;
16
17
/**
18
 * @author aniefer
19
 *
20
 */
21
public class Main {
22
	private static final String OUTPUT = "-outputDir="; //$NON-NLS-1$
23
	private static final String COMMAND = "-signCommand="; //$NON-NLS-1$
24
25
	private static String outputDir = null;
26
	private static String command = null;
27
	
28
	private static void printUsage(){
29
		System.out.println(" -pack [-signCommand=value] [-outputDir=value] input"); //$NON-NLS-1$
30
		System.out.println("\tPack the input jars.  If signCommand is specified, then the jars are first repacked and signed using that command"); //$NON-NLS-1$
31
		System.out.println("\tIf input is a directory, all contained jars are packed, subdirectories are visited recursively."); //$NON-NLS-1$
32
		System.out.println("\tThe signCommand will be executed with 1 argument that is the file to sign."); //$NON-NLS-1$
33
		System.out.println();
34
		System.out.println("-unpack [-outputDir=value] input"); //$NON-NLS-1$
35
		System.out.println("\tUnpack the input pack.gz files"); //$NON-NLS-1$
36
		System.out.println();
37
		System.out.println("[-outputDir=value] input.zip"); //$NON-NLS-1$
38
		System.out.println("\tCreate an outputDir/input.zip file containing processed repacked, signed & optionally packed versions of jars found"); //$NON-NLS-1$
39
		System.out.println("\tin input.zip"); //$NON-NLS-1$
40
	}
41
	
42
	private static void processZipFile(File zip){
43
		ZipProcessor processor = new ZipProcessor();
44
		processor.setWorkingDirectory(outputDir);
45
		processor.setCommand(command);
46
		try {
47
			processor.processZip(zip);
48
		} catch (ZipException e) {
49
			// TODO Auto-generated catch block
50
			e.printStackTrace();
51
		} catch (IOException e) {
52
			// TODO Auto-generated catch block
53
			e.printStackTrace();
54
		}
55
		
56
		
57
	}
58
	
59
	/**
60
	 * @param args
61
	 */
62
	public static void main(String[] args) {
63
		boolean packing = true;
64
		
65
		outputDir = "."; //$NON-NLS-1$
66
67
		if (args.length == 0) {
68
			printUsage();
69
			return;
70
		}
71
			
72
		int i = 0;
73
		for (; i < args.length - 1; i++) {
74
			if(args[i].equals("-pack")) {//$NON-NLS-1$
75
				packing = true;
76
			} else if( args[i].equals("-unpack")) { //$NON-NLS-1$
77
				packing = false;
78
			} else if(args[i].startsWith(COMMAND) && args[i].length() > COMMAND.length()) {
79
				command = args[i].substring(COMMAND.length()).trim();
80
			} else 	if (args[i].startsWith(OUTPUT)) {
81
				outputDir=args[i].substring(OUTPUT.length()).trim();
82
			}
83
		}
84
		File input = new File(args[i]);
85
		
86
		if(input.getName().endsWith(".zip")){ //$NON-NLS-1$
87
			processZipFile(input);
88
		} else {
89
			try {
90
				if(packing) {
91
					if(!JarProcessor.canPerformPack()){
92
						System.out.println("Cannot find a pack200 executable."); //$NON-NLS-1$
93
						return;
94
					}
95
					JarProcessor processor = new JarProcessor();
96
					processor.setWorkingDirectory(outputDir);
97
					processor.addProcessStep( command != null ? (IProcessStep) new PackUnpackStep(null) : (IProcessStep) new PackStep(null));
98
					if(command != null){
99
						processor.addProcessStep(new CommandStep(null, command, ".jar")); //$NON-NLS-1$
100
						processor.addProcessStep(new PackStep(null));
101
					}
102
					processor.process(input, Utils.JAR_FILTER);
103
				} else {
104
					if(!JarProcessor.canPerformUnpack()){
105
						System.out.println("Cannot find a unpack200 exectuable."); //$NON-NLS-1$
106
						return;
107
					}
108
					JarProcessor processor = new JarProcessor();
109
					processor.setWorkingDirectory(outputDir);
110
					processor.addProcessStep(new UnpackStep(null));
111
					processor.process(input, Utils.PACK_GZ_FILTER);
112
				}
113
			} catch (FileNotFoundException e ){
114
				System.out.println(e.getLocalizedMessage());
115
			}
116
		}
117
	}
118
119
}
(-)src/org/eclipse/update/jarprocessor/internal/ZipProcessor.java (+169 lines)
Added Link Here
1
/**
2
 * 
3
 */
4
package org.eclipse.update.jarprocessor.internal;
5
6
import java.io.*;
7
import java.util.*;
8
import java.util.zip.*;
9
import org.eclipse.update.jarprocessor.IProcessStep;
10
import org.eclipse.update.jarprocessor.JarProcessor;
11
12
/**
13
 * @author aniefer
14
 *
15
 */
16
public class ZipProcessor {
17
	
18
	private IProcessStep signStep = null;
19
	private IProcessStep packStep = null;
20
	private IProcessStep packUnpackStep = null;
21
22
	private String workingDirectory = null;
23
	private Properties properties = null;
24
	private Set packExclusions = null;
25
	private Set signExclusions = null;
26
	private String command = null;
27
	private boolean packing = false;
28
	private boolean signing = true;
29
	private boolean repacking = true;
30
31
	public void setWorkingDirectory(String dir) {
32
		workingDirectory = dir;
33
	}
34
	
35
	public String getWorkingDirectory() {
36
		if(workingDirectory == null)
37
			workingDirectory = "."; //$NON-NLS-1$
38
		return workingDirectory;
39
	}
40
	
41
	public void setCommand(String command){
42
		this.command = command;
43
	}
44
	
45
	public void processZip(File zipFile) throws ZipException, IOException {
46
		ZipFile zip = new ZipFile(zipFile);
47
		initialize(zip);
48
49
		File tempDir = new File(getWorkingDirectory(), "temp_" + zipFile.getName()); //$NON-NLS-1$
50
		JarProcessor processor = new JarProcessor();
51
		processor.setWorkingDirectory(tempDir.getCanonicalPath());
52
53
		File outputFile = new File(getWorkingDirectory(), zipFile.getName() + ".temp"); //$NON-NLS-1$
54
		File parent = outputFile.getParentFile();
55
		if (!parent.exists())
56
			parent.mkdirs();
57
		ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(outputFile));
58
		Enumeration entries = zip.entries();
59
		if (entries.hasMoreElements()) {
60
			for (ZipEntry entry = (ZipEntry) entries.nextElement(); entry != null; entry = entries.hasMoreElements() ? (ZipEntry) entries.nextElement() : null) {
61
				String name = entry.getName();
62
				
63
				InputStream entryStream = zip.getInputStream(entry);
64
65
				boolean pack = packing && !packExclusions.contains(name);
66
				boolean sign = signing && !signExclusions.contains(name);
67
68
				File extractedFile = null;
69
				if (entry.getName().endsWith(".jar") && (pack || sign)) { //$NON-NLS-1$
70
					extractedFile = new File(tempDir, entry.getName());
71
					parent = extractedFile.getParentFile();
72
					if (!parent.exists())
73
						parent.mkdirs();
74
					FileOutputStream extracted = new FileOutputStream(extractedFile);
75
					Utils.transferStreams(entryStream, extracted, true);
76
77
					processor.clearProcessSteps();
78
					if(repacking || pack)
79
						processor.addProcessStep(packUnpackStep);
80
					if(sign)
81
						processor.addProcessStep(signStep);
82
					processor.processJar(extractedFile);
83
					extractedFile = new File(tempDir, extractedFile.getName());
84
					if(pack){
85
						processor.clearProcessSteps();
86
						processor.addProcessStep(packStep);
87
						processor.processJar(extractedFile);
88
89
						File modifiedFile = new File(tempDir, extractedFile.getName() + ".pack.gz"); //$NON-NLS-1$
90
						ZipEntry zipEntry = new ZipEntry(name + ".pack.gz"); //$NON-NLS-1$
91
						entryStream = new FileInputStream(modifiedFile);
92
						zipOut.putNextEntry(zipEntry);
93
						Utils.transferStreams(entryStream, zipOut, false);
94
						entryStream.close();
95
						Utils.clear(modifiedFile);
96
					}
97
					entryStream = new FileInputStream(extractedFile);
98
				}
99
				ZipEntry newEntry = new ZipEntry(name);
100
				zipOut.putNextEntry(newEntry);
101
				Utils.transferStreams(entryStream, zipOut, false);
102
				zipOut.closeEntry();
103
				entryStream.close();
104
105
				if(extractedFile != null)
106
					Utils.clear(extractedFile);
107
			}
108
109
		}
110
		zipOut.close();
111
		zip.close();
112
		
113
		File finalFile = new File(getWorkingDirectory(), zipFile.getName());
114
		if(finalFile.exists())
115
			finalFile.delete();
116
		outputFile.renameTo(finalFile);
117
		Utils.clear(tempDir);
118
	}
119
120
	private void initialize(ZipFile zip) {
121
		ZipEntry entry = zip.getEntry("pack.properties"); //$NON-NLS-1$
122
		properties = new Properties();
123
		if (entry != null) {
124
			InputStream stream = null;
125
			try {
126
				stream = zip.getInputStream(entry);
127
				properties.load(stream);
128
			} catch (IOException e) {
129
				// TODO Auto-generated catch block
130
				e.printStackTrace();
131
			} finally {
132
				Utils.close(stream);
133
			}
134
		}
135
		String pack = properties.getProperty("packing"); //$NON-NLS-1$
136
		packing = (pack != null && Boolean.valueOf(pack).booleanValue());
137
		String sign = properties.getProperty("signing"); //$NON-NLS-1$
138
		signing = (sign == null || Boolean.valueOf(sign).booleanValue());
139
		String repack = properties.getProperty("repacking"); //$NON-NLS-1$
140
		repacking = (repack == null || Boolean.valueOf(repack).booleanValue());
141
		
142
		String packExcludes = properties.getProperty("pack.excludes"); //$NON-NLS-1$
143
		if (packExcludes != null) {
144
			String[] excludes = packExcludes.split(",\\s*"); //$NON-NLS-1$
145
			packExclusions = new HashSet();
146
			for (int i = 0; i < excludes.length; i++) {
147
				packExclusions.add(excludes[i]);
148
			}
149
		} else {
150
			packExclusions = Collections.EMPTY_SET;
151
		}
152
153
		String signExcludes = properties.getProperty("sign.excludes"); //$NON-NLS-1$
154
		if (signExcludes != null) {
155
			String[] excludes = packExcludes.split(",\\s*"); //$NON-NLS-1$
156
			signExclusions = new HashSet();
157
			for (int i = 0; i < excludes.length; i++) {
158
				signExclusions.add(excludes[i]);
159
			}
160
		} else {
161
			signExclusions = Collections.EMPTY_SET;
162
		}
163
164
		packUnpackStep = new PackUnpackStep(properties);
165
		packStep = new PackStep(properties);
166
		signStep = new CommandStep(properties, command, ".jar"); //$NON-NLS-1$
167
168
	}
169
}
(-)src/org/eclipse/update/jarprocessor/internal/Utils.java (+135 lines)
Added Link Here
1
/**
2
 * 
3
 */
4
package org.eclipse.update.jarprocessor.internal;
5
6
import java.io.*;
7
import java.util.jar.JarFile;
8
import org.eclipse.update.jarprocessor.JarProcessor;
9
10
/**
11
 * @author aniefer
12
 *
13
 */
14
public class Utils {
15
16
	public static final String PACKED_SUFFIX = ".pack.gz"; //$NON-NLS-1$
17
18
	public static final FileFilter JAR_FILTER = new FileFilter() {
19
		public boolean accept(File pathname) {
20
			return pathname.isFile() && pathname.getName().endsWith(".jar"); //$NON-NLS-1$
21
		}
22
	};
23
24
	public static final FileFilter PACK_GZ_FILTER = new FileFilter() {
25
		public boolean accept(File pathname) {
26
			return pathname.isFile() && pathname.getName().endsWith(PACKED_SUFFIX);
27
		}
28
	};
29
30
	public static void close(Object stream) {
31
		if (stream != null) {
32
			try {
33
				if (stream instanceof InputStream)
34
					((InputStream) stream).close();
35
				else if (stream instanceof OutputStream)
36
					((OutputStream) stream).close();
37
				else if (stream instanceof JarFile)
38
					((JarFile) stream).close();
39
			} catch (IOException e) {
40
				//ignore
41
			}
42
		}
43
	}
44
45
	/**
46
	 * get the set of commands to try to execute pack/unpack 
47
	 * @param cmd, the command, either "pack200" or "unpack200"
48
	 * @return String [] or null
49
	 */
50
	public static String[] getPack200Commands(String cmd) {
51
		String[] locations = null;
52
		String prop = System.getProperty(JarProcessor.PACK200_PROPERTY);
53
		String javaHome = System.getProperty("java.home"); //$NON-NLS-1$
54
		if (JarProcessor.NONE.equals(prop)) {
55
			return null;
56
		} else if (JarProcessor.JRE.equals(prop)) {
57
			locations = new String[] {javaHome + "/bin/" + cmd}; //$NON-NLS-1$
58
		} else if (JarProcessor.PATH.equals(prop)) {
59
			locations = new String[] {cmd};
60
		} else if (prop == null) {
61
			locations = new String[] {javaHome + "/bin/" + cmd, cmd}; //$NON-NLS-1$ 
62
		} else {
63
			locations = new String[] {prop + "/" + cmd}; //$NON-NLS-1$
64
		}
65
		return locations;
66
	}
67
68
	/**
69
	 * Transfers all available bytes from the given input stream to the given
70
	 * output stream. Closes both streams if close == true, regardless of failure. 
71
	 * Flushes the destination stream if close == false
72
	 * 
73
	 * @param source
74
	 * @param destination
75
	 * @param close 
76
	 * @throws IOException
77
	 */
78
	public static void transferStreams(InputStream source, OutputStream destination, boolean close) throws IOException {
79
		source = new BufferedInputStream(source);
80
		destination = new BufferedOutputStream(destination);
81
		try {
82
			byte[] buffer = new byte[8192];
83
			while (true) {
84
				int bytesRead = -1;
85
				if ((bytesRead = source.read(buffer)) == -1)
86
					break;
87
				destination.write(buffer, 0, bytesRead);
88
			}
89
		} finally {
90
			if (close) {
91
				close(source);
92
				close(destination);
93
			} else {
94
				destination.flush();
95
			}
96
		}
97
	}
98
99
	/**
100
	 * Deletes all the files and directories from the given root down (inclusive).
101
	 * Returns false if we could not delete some file or an exception occurred
102
	 * at any point in the deletion.
103
	 * Even if an exception occurs, a best effort is made to continue deleting.
104
	 */
105
	public static boolean clear(java.io.File root) {
106
		boolean result = clearChildren(root);
107
		try {
108
			if (root.exists())
109
				result &= root.delete();
110
		} catch (Exception e) {
111
			result = false;
112
		}
113
		return result;
114
	}
115
116
	/**
117
	 * Deletes all the files and directories from the given root down, except for 
118
	 * the root itself.
119
	 * Returns false if we could not delete some file or an exception occurred
120
	 * at any point in the deletion.
121
	 * Even if an exception occurs, a best effort is made to continue deleting.
122
	 */
123
	public static boolean clearChildren(java.io.File root) {
124
		boolean result = true;
125
		if (root.isDirectory()) {
126
			String[] list = root.list();
127
			// for some unknown reason, list() can return null.  
128
			// Just skip the children If it does.
129
			if (list != null)
130
				for (int i = 0; i < list.length; i++)
131
					result &= clear(new java.io.File(root, list[i]));
132
		}
133
		return result;
134
	}
135
}
(-)src/org/eclipse/update/jarprocessor/JarProcessor.java (+288 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM - Initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.update.jarprocessor;
12
13
import java.io.*;
14
import java.util.*;
15
import java.util.jar.*;
16
import org.eclipse.update.jarprocessor.internal.*;
17
18
/**
19
 * @author aniefer
20
 *
21
 */
22
public class JarProcessor {
23
	/**
24
	 * The system property "org.eclipse.update.jarprocessor.pack200".  Set to the location in which to look for the
25
	 * pack200/unpack200 executables. 
26
	 * Possible values are:
27
	 *  "@jre": look for the executables in java.home/bin
28
	 *  "@path": look for the executables in the system search path
29
	 *  "@none": don't use pack200
30
	 *  dir : a directory containing pack200 & unpack200 executables 
31
	 */
32
	public static final String PACK200_PROPERTY = "org.eclipse.update.jarprocessor.pack200"; //$NON-NLS-1$
33
	public static final String JRE = "@jre"; //$NON-NLS-1$
34
	public static final String PATH = "@path"; //$NON-NLS-1$
35
	public static final String NONE = "@none"; //$NON-NLS-1$
36
	
37
	private List steps = new ArrayList();
38
	private String workingDirectory = ""; //$NON-NLS-1$
39
	private int depth = -1;
40
	
41
	static public JarProcessor getUnpackProcessor(Properties properties) {
42
		if(!canPerformUnpack())
43
			throw new UnsupportedOperationException();
44
		JarProcessor processor = new JarProcessor();
45
		processor.addProcessStep(new UnpackStep(properties));
46
		return processor;
47
	}
48
	
49
	static public JarProcessor getPackProcessor(Properties properties) {
50
		if(!canPerformPack())
51
			throw new UnsupportedOperationException();
52
		JarProcessor processor = new JarProcessor();
53
		processor.addProcessStep(new PackStep(properties));
54
		return processor;
55
	}
56
	
57
	static public boolean canPerformPack() {
58
		return PackStep.canPack();
59
	}
60
	
61
	static public boolean canPerformUnpack(){
62
		return UnpackStep.canUnpack();
63
	}
64
	
65
	public String getWorkingDirectory() {
66
		return workingDirectory;
67
	}
68
69
	public void setWorkingDirectory(String dir) {
70
		workingDirectory = dir;
71
	}
72
	
73
	public void addProcessStep(IProcessStep step) {
74
		steps.add(step);
75
	}
76
	
77
	public void clearProcessSteps() {
78
		steps.clear();
79
	}
80
	public void process(File input, FileFilter filter) throws FileNotFoundException  {
81
		if(!input.exists() )
82
			throw new FileNotFoundException();
83
		
84
		File [] files = null;
85
		if(input.isDirectory()){
86
			files = input.listFiles();
87
		} else if(filter.accept(input)) {
88
			files = new File [] {input};
89
		}
90
		for (int i = 0; i < files.length; i++) {
91
			System.out.println("Processing " +files[i].getName()); //$NON-NLS-1$
92
			if(files[i].isDirectory()){
93
				String dir = getWorkingDirectory();
94
				setWorkingDirectory(dir + "/" + files[i].getName()); //$NON-NLS-1$
95
				process(files[i], filter);
96
				setWorkingDirectory(dir);
97
			} else if(filter.accept(files[i])) {
98
				try {
99
					processJar(files[i]);
100
				} catch (IOException e) {
101
					// TODO Auto-generated catch block
102
					e.printStackTrace();
103
				}
104
			}
105
		}
106
	}
107
	
108
	/**
109
	 * Recreate a jar file.  The replacements map specifies entry names to be replaced, the replacements are
110
	 * expected to be found in directory.
111
	 * 
112
	 * @param jar - The input jar
113
	 * @param outputJar - the output
114
	 * @param replacements - map of entryName -> new entryName
115
	 * @param directory - location to find file for new entryName
116
	 * @throws IOException
117
	 */
118
	private void recreateJar(JarFile jar, JarOutputStream outputJar, Map replacements, File directory) throws IOException {
119
		InputStream in = null;
120
		try {
121
			Enumeration entries = jar.entries();
122
			for (JarEntry entry = (JarEntry) entries.nextElement(); entry != null; entry = entries.hasMoreElements() ? (JarEntry) entries.nextElement() : null) {
123
				File replacement = null;
124
				JarEntry newEntry = null;
125
				if (replacements.containsKey(entry.getName())) {
126
					String name = (String) replacements.get(entry.getName());// + Utils.PACKED_SUFFIX;
127
					replacement = new File(directory, name);
128
					in = new FileInputStream(replacement);
129
					newEntry = new JarEntry(name);
130
					//long time = entry.getTime();
131
//					entry = new JarEntry(name);
132
//					entry.setTime(time);
133
				} else {
134
					in = jar.getInputStream(entry);
135
					newEntry = new JarEntry(entry.getName());
136
					//entry.setCompressedSize(-1);
137
				}
138
				newEntry.setTime(entry.getTime());
139
				outputJar.putNextEntry(newEntry);
140
				Utils.transferStreams(in, outputJar, false);
141
				outputJar.closeEntry();
142
				in.close();
143
	
144
				//delete the nested jar file
145
				if (replacement != null) {
146
					replacement.delete();
147
				}
148
			}
149
		} finally {
150
			Utils.close(outputJar);
151
			Utils.close(jar);
152
			Utils.close(in);
153
		}
154
	}
155
	
156
	private String recursionEffect(String entryName) {
157
		String result = null;
158
		for (Iterator iter = steps.iterator(); iter.hasNext();) {
159
			IProcessStep step = (IProcessStep) iter.next();
160
			
161
			result = step.recursionEffect(entryName);
162
			if(result != null)
163
				entryName = result;
164
		}
165
		return result;
166
	}
167
168
	private void extractEntries(JarFile jar, File tempDir, Map data) throws IOException {
169
		Enumeration entries = jar.entries();
170
		if (entries.hasMoreElements()) {
171
			for (JarEntry entry = (JarEntry) entries.nextElement(); entry != null; entry = entries.hasMoreElements() ? (JarEntry) entries.nextElement() : null) {
172
				String name = entry.getName();
173
				String newName = recursionEffect(name);
174
				if (newName != null) {
175
					//extract entry to temp directory
176
					File extracted = new File(tempDir, name);
177
					File parentDir = extracted.getParentFile();
178
					if (!parentDir.exists())
179
						parentDir.mkdirs();
180
					
181
					InputStream in = null;
182
					FileOutputStream out = null;
183
					try {
184
						in = jar.getInputStream(entry);
185
						out = new FileOutputStream(extracted);
186
						Utils.transferStreams(in, out, true); //this will close both streams
187
					} finally {
188
						Utils.close(in);
189
						Utils.close(out);
190
					}
191
					data.put(name, newName);
192
					
193
					//recurse
194
					String dir = getWorkingDirectory();
195
					setWorkingDirectory(parentDir.getCanonicalPath());
196
					processJar(extracted);
197
					setWorkingDirectory(dir);
198
					
199
					//delete the extracted item leaving the recursion result
200
					if(!name.equals(newName))
201
						extracted.delete();
202
				}
203
			}
204
		}
205
	}
206
	
207
208
	
209
	private File preProcess(File input, File tempDir) {
210
		File result = null;
211
		for (Iterator iter = steps.iterator(); iter.hasNext();) {
212
			IProcessStep step = (IProcessStep) iter.next();
213
			result = step.preProcess(input, tempDir);
214
			if( result != null)
215
				input = result;
216
		}
217
		return input;
218
	}
219
	
220
	private File postProcess(File input, File tempDir) {
221
		File result = null;
222
		for (Iterator iter = steps.iterator(); iter.hasNext();) {
223
			IProcessStep step = (IProcessStep) iter.next();
224
			result = step.postProcess(input, tempDir);
225
			if(result != null)
226
				input = result;
227
		}
228
		return input;
229
	}
230
	
231
	public void processJar(File input) throws IOException {
232
		++depth;
233
		File workingDir = new File(getWorkingDirectory());
234
		if(!workingDir.exists())
235
			workingDir.mkdirs();
236
		
237
		//pre
238
		File workingFile = preProcess(input, workingDir);
239
		
240
		//Extract entries from jar and recurse on them
241
		File tempDir = null;
242
		if(depth == 0) {
243
			tempDir = new File(workingDir, "temp." + workingFile.getName()); //$NON-NLS-1$
244
		} else {
245
			File parent = workingDir.getParentFile();
246
			tempDir = new File(parent, "temp_" + depth +'_' + workingFile.getName()); //$NON-NLS-1$
247
		}
248
//		if(depth == 0){
249
//			JarFile jar = new JarFile(workingFile, false);
250
//			Map replacements = new HashMap();
251
//			extractEntries(jar, tempDir, replacements);
252
//			
253
//			//Recreate the jar with replacements
254
//			File tempJar = null;
255
//			if(replacements.size() > 0) {
256
//				tempJar = new File(tempDir, workingFile.getName());
257
//				File parent = tempJar.getParentFile();
258
//				if(!parent.exists())
259
//					parent.mkdirs();
260
//				JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(tempJar));
261
//				recreateJar(jar, jarOut, replacements, tempDir);
262
//			}
263
//			
264
//			jar.close();
265
//			if( tempJar != null) {
266
//				if(!workingFile.equals(input)){
267
//					workingFile.delete();
268
//				} 
269
//				workingFile = tempJar;
270
//			}
271
//		}
272
		//post
273
		File result = postProcess(workingFile, workingDir);
274
		if(!result.equals(workingFile) && !workingFile.equals(input))
275
			workingFile.delete();
276
		if(!result.getParentFile().equals(workingDir)){
277
			File finalFile = new File(workingDir, result.getName());
278
			if(finalFile.exists())
279
				finalFile.delete();
280
			result.renameTo(finalFile);
281
		}
282
		
283
		if(tempDir.exists())
284
			Utils.clear(tempDir);
285
		
286
		--depth;
287
	}
288
}
(-)src/org/eclipse/update/jarprocessor/IProcessStep.java (+47 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM - Initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.update.jarprocessor;
12
13
import java.io.File;
14
15
/**
16
 * @author aniefer
17
 *
18
 */
19
public interface IProcessStep {
20
	
21
	/**
22
	 * The effect of this processing step if the JarProcessor was to recurse on this entry.
23
	 * Return null if this step will not do anything with this entry.
24
	 * Return the new entryName if this step will modify this entry on recursion.
25
	 * @param entryName
26
	 * @return
27
	 */
28
	String recursionEffect(String entryName);
29
	
30
	/**
31
	 * Perform some processing on the input file before the JarProcessor considers the entries for recursion.
32
	 *  return the file containing the result of the processing
33
	 * @param input
34
	 * @param workingDirectory
35
	 * @return
36
	 */
37
	File preProcess(File input, File workingDirectory);
38
	
39
	/**
40
	 * Perform some processing on the input file after the JarProcessor returns from recursion
41
	 * return the file containing the result of the processing
42
	 * @param input
43
	 * @param workingDirectory
44
	 * @return
45
	 */
46
	File postProcess(File input, File workingDirectory);
47
}
(-)src/org/eclipse/update/jarprocessor/internal/PackUnpackStep.java (+81 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM - Initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.update.jarprocessor.internal;
12
13
import java.io.File;
14
import java.io.IOException;
15
import java.util.Properties;
16
17
/**
18
 * @author aniefer
19
 *
20
 */
21
public class PackUnpackStep extends PackStep {
22
//	private PackStep pack = null;
23
//	private UnpackStep unpack = null;
24
	
25
	public PackUnpackStep(Properties options) {
26
		super(options);
27
//		pack = new PackStep(options);
28
//		unpack = new UnpackStep(options);
29
	}
30
31
	public String recursionEffect(String entryName) {
32
		if (canPack() && entryName.endsWith(".jar")) { //$NON-NLS-1$
33
			return entryName;
34
		}
35
		return null;
36
	}
37
38
	/* (non-Javadoc)
39
	 * @see org.eclipse.update.jarprocessor.IProcessStep#preProcess(java.io.File, java.io.File)
40
	 */
41
	public File postProcess(File input, File workingDirectory) {
42
		if (canPack() && command != null) {
43
			File tempFile = new File(workingDirectory, "temp_" + input.getName()); //$NON-NLS-1$
44
			try {
45
				String[] tmp = getCommand(input, tempFile);
46
				String[] cmd = new String[tmp.length + 1];
47
				cmd[0] = tmp[0];
48
				cmd[1] = "-r"; //$NON-NLS-1$
49
				System.arraycopy(tmp, 1, cmd, 2, tmp.length - 1);
50
51
				int result = execute(cmd);
52
				if (result == 0 && tempFile.exists()) {
53
					File finalFile = new File(workingDirectory, input.getName());
54
					if(finalFile.exists())
55
						finalFile.delete();
56
					tempFile.renameTo(finalFile);
57
					return finalFile;
58
				}
59
			} catch (IOException e) {
60
				//didn't work
61
				return null;
62
			}
63
		}
64
		return null;
65
	}
66
//	public File postProcess(File input, File workingDirectory){
67
//		if(PackStep.canPack() && UnpackStep.canUnpack() ){
68
//			File packed = pack.postProcess(input, workingDirectory);
69
//			return unpack.preProcess(packed, workingDirectory);
70
//		}
71
//		return null;
72
//	}
73
74
	/* (non-Javadoc)
75
	 * @see org.eclipse.update.jarprocessor.IProcessStep#postProcess(java.io.File, java.io.File)
76
	 */
77
	public File preProcess(File input, File workingDirectory) {
78
		return null;
79
	}
80
81
}
(-)src/org/eclipse/update/jarprocessor/internal/UnpackStep.java (+109 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM - Initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.update.jarprocessor.internal;
12
13
import java.io.File;
14
import java.io.IOException;
15
import java.util.Properties;
16
17
/**
18
 * @author aniefer
19
 *
20
 */
21
public class UnpackStep extends CommandStep {
22
	public static final String UNPACKER_PROPERTY = "org.eclipse.update.jarprocessor.Unpacker"; //$NON-NLS-1$
23
	private static Boolean canUnpack = null;
24
	private static String command = null;
25
26
	public static boolean canUnpack() {
27
		if (canUnpack != null)
28
			return canUnpack.booleanValue();
29
30
		String[] locations = Utils.getPack200Commands("unpack200"); //$NON-NLS-1$
31
		if (locations == null) {
32
			canUnpack = Boolean.FALSE;
33
			command = null;
34
			return false;
35
		}
36
37
		int result;
38
		for (int i = 0; i < locations.length; i++) {
39
			if (locations[i] == null)
40
				continue;
41
			try {
42
				result = execute(new String[] {locations[i], "-V"}); //$NON-NLS-1$
43
				if (result == 0) {
44
					command = locations[i];
45
					canUnpack = Boolean.TRUE;
46
					return true;
47
				}
48
			} catch (IOException e) {
49
				//no good
50
			}
51
		}
52
53
		canUnpack = Boolean.FALSE;
54
		return false;
55
	}
56
57
	public UnpackStep(Properties options) {
58
		super(options, null, null);
59
	}
60
61
	/* (non-Javadoc)
62
	 * @see org.eclipse.update.jarprocessor.IProcessStep#recursionEffect(java.lang.String)
63
	 */
64
	public String recursionEffect(String entryName) {
65
		if (canUnpack() && entryName.endsWith(Utils.PACKED_SUFFIX)) {
66
			return entryName.substring(0, entryName.length() - Utils.PACKED_SUFFIX.length());
67
		}
68
		return null;
69
	}
70
71
	/* (non-Javadoc)
72
	 * @see org.eclipse.update.jarprocessor.IProcessStep#preProcess(java.io.File, java.io.File)
73
	 */
74
	public File preProcess(File input, File workingDirectory) {
75
		if (canUnpack() && command != null) {
76
			String name = input.getName();
77
			if (name.endsWith(Utils.PACKED_SUFFIX)) {
78
				name = name.substring(0, name.length() - Utils.PACKED_SUFFIX.length());
79
80
				File unpacked = new File(workingDirectory, name);
81
				File parent = unpacked.getParentFile();
82
				if (!parent.exists())
83
					parent.mkdirs();
84
				try {
85
					String options = getOptions().getProperty(input.getName() + ".unpack.args"); //$NON-NLS-1$
86
					String[] cmd = null;
87
					if (options != null) {
88
						cmd = new String[] {command, options, input.getCanonicalPath(), unpacked.getCanonicalPath()};
89
					} else {
90
						cmd = new String[] {command, input.getCanonicalPath(), unpacked.getCanonicalPath()};
91
					}
92
					execute(cmd);
93
				} catch (IOException e) {
94
					//didn't work
95
					return null;
96
				}
97
				return unpacked;
98
			}
99
		}
100
		return null;
101
	}
102
103
	/* (non-Javadoc)
104
	 * @see org.eclipse.update.jarprocessor.IProcessStep#postProcess(java.io.File, java.io.File)
105
	 */
106
	public File postProcess(File input, File workingDirectory) {
107
		return null;
108
	}
109
}
(-)src/org/eclipse/update/jarprocessor/internal/PackStep.java (+100 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM - Initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.update.jarprocessor.internal;
12
13
import java.io.File;
14
import java.io.IOException;
15
import java.util.*;
16
17
public class PackStep extends CommandStep {
18
19
	protected static String command = null;
20
	private static Boolean canPack = null;
21
22
	private Set exclusions = Collections.EMPTY_SET;
23
24
	public static boolean canPack() {
25
		if (canPack != null)
26
			return canPack.booleanValue();
27
28
		String[] locations = Utils.getPack200Commands("pack200"); //$NON-NLS-1$
29
		if (locations == null) {
30
			canPack = Boolean.FALSE;
31
			command = null;
32
			return false;
33
		}
34
35
		int result;
36
		for (int i = 0; i < locations.length; i++) {
37
			if (locations[i] == null)
38
				continue;
39
			try {
40
				result = execute(new String[] {locations[i], "-V"}); //$NON-NLS-1$
41
				if (result == 0) {
42
					command = locations[i];
43
					canPack = Boolean.TRUE;
44
					return true;
45
				}
46
			} catch (IOException e) {
47
				//no good
48
			}
49
		}
50
51
		canPack = Boolean.FALSE;
52
		return false;
53
	}
54
55
	public PackStep(Properties options) {
56
		super(options, null, null);
57
	}
58
59
	public String recursionEffect(String entryName) {
60
		if (canPack() && entryName.endsWith(".jar") && !exclusions.contains(entryName)) { //$NON-NLS-1$
61
			return entryName + Utils.PACKED_SUFFIX;
62
		}
63
		return null;
64
	}
65
66
	public File preProcess(File input, File workingDirectory) {
67
		return null;
68
	}
69
70
	public File postProcess(File input, File workingDirectory) {
71
		if (canPack() && command != null) {
72
			File outputFile = new File(workingDirectory, input.getName() + Utils.PACKED_SUFFIX);
73
			try {
74
				String[] cmd = getCommand(input, outputFile);
75
				execute(cmd);
76
			} catch (IOException e) {
77
				//didn't work
78
				return null;
79
			}
80
			return outputFile;
81
		}
82
		return null;
83
	}
84
85
	protected String[] getCommand(File input, File outputFile) throws IOException {
86
		String[] cmd = null;
87
		String options = getOptions().getProperty(input.getName() + ".pack.args"); //$NON-NLS-1$
88
		if (options != null) {
89
			String[] args = options.split(",\\s*"); //$NON-NLS-1$
90
			cmd = new String[3 + args.length];
91
			cmd[0] = command;
92
			System.arraycopy(args, 0, cmd, 1, args.length);
93
			cmd[cmd.length - 2] = outputFile.getCanonicalPath();
94
			cmd[cmd.length - 1] = input.getCanonicalPath();
95
		} else {
96
			cmd = new String[] {command, outputFile.getCanonicalPath(), input.getCanonicalPath()};
97
		}
98
		return cmd;
99
	}
100
}

Return to bug 127375