KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > ui > jarpackager > JarWriter2


1 /*******************************************************************************
2  * Copyright (c) 2000, 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 Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.ui.jarpackager;
12
13 import java.io.File JavaDoc;
14 import java.io.FileOutputStream JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.io.InputStream JavaDoc;
17 import java.util.ArrayList JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Set JavaDoc;
21 import java.util.jar.JarEntry JavaDoc;
22 import java.util.jar.JarOutputStream JavaDoc;
23 import java.util.jar.Manifest JavaDoc;
24 import java.util.zip.CRC32 JavaDoc;
25 import java.util.zip.ZipEntry JavaDoc;
26
27 import org.eclipse.core.runtime.Assert;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IPath;
30 import org.eclipse.core.runtime.OperationCanceledException;
31
32 import org.eclipse.core.resources.IFile;
33 import org.eclipse.core.resources.IProject;
34 import org.eclipse.core.resources.IResource;
35 import org.eclipse.core.resources.ResourcesPlugin;
36
37 import org.eclipse.swt.widgets.Shell;
38
39
40 import org.eclipse.jdt.internal.corext.util.Messages;
41
42 import org.eclipse.jdt.internal.ui.JavaPlugin;
43 import org.eclipse.jdt.internal.ui.jarpackager.JarPackagerMessages;
44 import org.eclipse.jdt.internal.ui.jarpackager.JarPackagerUtil;
45
46 /**
47  * Creates a JAR file for the given JAR package data.
48  * <p>
49  * Clients may subclass.
50  * </p>
51  *
52  * @see org.eclipse.jdt.ui.jarpackager.JarPackageData
53  * @since 3.1
54  *
55  * @deprecated Use JarWriter3 instead which leverages new {@link org.eclipse.core.filesystem.EFS EFS} support
56  */

57 public class JarWriter2 {
58     
59     private JarOutputStream JavaDoc fJarOutputStream;
60     private JarPackageData fJarPackage;
61
62     private Set JavaDoc fDirectories= new HashSet JavaDoc();
63     
64     /**
65      * Creates an instance which is used to create a JAR based
66      * on the given JarPackage.
67      *
68      * @param jarPackage the JAR specification
69      * @param parent the shell used to display question dialogs,
70      * or <code>null</code> if "false/no/cancel" is the answer
71      * and no dialog should be shown
72      * @throws CoreException to signal any other unusual termination.
73      * This can also be used to return information
74      * in the status object.
75      */

76     public JarWriter2(JarPackageData jarPackage, Shell parent) throws CoreException {
77         Assert.isNotNull(jarPackage, "The JAR specification is null"); //$NON-NLS-1$
78
fJarPackage= jarPackage;
79         Assert.isTrue(fJarPackage.isValid(), "The JAR package specification is invalid"); //$NON-NLS-1$
80
if (!canCreateJar(parent))
81             throw new OperationCanceledException();
82
83         try {
84             if (fJarPackage.usesManifest() && fJarPackage.areGeneratedFilesExported()) {
85                 Manifest JavaDoc manifest= fJarPackage.getManifestProvider().create(fJarPackage);
86                 fJarOutputStream= new JarOutputStream JavaDoc(new FileOutputStream JavaDoc(fJarPackage.getAbsoluteJarLocation().toOSString()), manifest);
87             } else
88                 fJarOutputStream= new JarOutputStream JavaDoc(new FileOutputStream JavaDoc(fJarPackage.getAbsoluteJarLocation().toOSString()));
89             String JavaDoc comment= jarPackage.getComment();
90             if (comment != null)
91                 fJarOutputStream.setComment(comment);
92         } catch (IOException JavaDoc ex) {
93             throw JarPackagerUtil.createCoreException(ex.getLocalizedMessage(), ex);
94         }
95     }
96     
97     /**
98      * Closes the archive and does all required cleanup.
99      *
100      * @throws CoreException to signal any other unusual termination.
101      * This can also be used to return information
102      * in the status object.
103      */

104     public void close() throws CoreException {
105         if (fJarOutputStream != null)
106             try {
107                 fJarOutputStream.close();
108                 registerInWorkspaceIfNeeded();
109             } catch (IOException JavaDoc ex) {
110                 throw JarPackagerUtil.createCoreException(ex.getLocalizedMessage(), ex);
111             }
112     }
113     
114     /**
115      * Writes the passed resource to the current archive.
116      *
117      * @param resource the file to be written
118      * @param destinationPath the path for the file inside the archive
119      * @throws CoreException to signal any other unusual termination.
120      * This can also be used to return information
121      * in the status object.
122      */

123     public void write(IFile resource, IPath destinationPath) throws CoreException {
124         try {
125             IPath fileLocation= resource.getLocation();
126             File JavaDoc file= null;
127             if (fileLocation != null) {
128                 file= new File JavaDoc(fileLocation.toOSString());
129             }
130             if (fJarPackage.areDirectoryEntriesIncluded())
131                 addDirectories(destinationPath, file);
132             addFile(resource, destinationPath, file);
133         } catch (IOException JavaDoc ex) {
134             // Ensure full path is visible
135
String JavaDoc message= null;
136             if (ex.getLocalizedMessage() != null)
137                 message= Messages.format(JarPackagerMessages.JarWriter_writeProblemWithMessage, new Object JavaDoc[] {resource.getFullPath(), ex.getLocalizedMessage()});
138             else
139                 message= Messages.format(JarPackagerMessages.JarWriter_writeProblem, resource.getFullPath());
140             throw JarPackagerUtil.createCoreException(message, ex);
141         }
142     }
143     
144     /**
145      * Creates a new JarEntry with the passed path and contents, and writes it
146      * to the current archive.
147      *
148      * @param resource the file to write
149      * @param path the path inside the archive
150      * @param correspondingFile the corresponding file in the file system
151      * or <code>null</code> if it doesn't exist
152      * @throws IOException if an I/O error has occurred
153      * @throws CoreException if the resource can-t be accessed
154      */

155     protected void addFile(IFile resource, IPath path, File JavaDoc correspondingFile) throws IOException JavaDoc, CoreException {
156         JarEntry JavaDoc newEntry= new JarEntry JavaDoc(path.toString().replace(File.separatorChar, '/'));
157         byte[] readBuffer= new byte[4096];
158
159         if (fJarPackage.isCompressed())
160             newEntry.setMethod(ZipEntry.DEFLATED);
161             // Entry is filled automatically.
162
else {
163             newEntry.setMethod(ZipEntry.STORED);
164             calculateCrcAndSize(newEntry, resource, readBuffer);
165         }
166
167         long lastModified= correspondingFile != null && correspondingFile.exists() ? correspondingFile.lastModified() : System.currentTimeMillis();
168         // Set modification time
169
newEntry.setTime(lastModified);
170
171         InputStream JavaDoc contentStream = resource.getContents(false);
172
173         try {
174             fJarOutputStream.putNextEntry(newEntry);
175             int count;
176             while ((count= contentStream.read(readBuffer, 0, readBuffer.length)) != -1)
177                 fJarOutputStream.write(readBuffer, 0, count);
178         } finally {
179             if (contentStream != null)
180                 contentStream.close();
181
182             /*
183              * Commented out because some JREs throw an NPE if a stream
184              * is closed twice. This works because
185              * a) putNextEntry closes the previous entry
186              * b) closing the stream closes the last entry
187              */

188             // fJarOutputStream.closeEntry();
189
}
190     }
191
192     /**
193      * Calculates the CRC and size of the resource and updates the jarEntry.
194      *
195      * @param jarEntry the JarEntry to update
196      * @param resource the file to calculate
197      * @param readBuffer a shared read buffer to store temporary data
198      *
199      * @throws IOException if an I/O error has occurred
200      * @throws CoreException if the resource can-t be accessed
201      */

202     private void calculateCrcAndSize(JarEntry JavaDoc jarEntry, IFile resource, byte[] readBuffer) throws IOException JavaDoc, CoreException {
203         InputStream JavaDoc contentStream = resource.getContents(false);
204         int size = 0;
205         CRC32 JavaDoc checksumCalculator= new CRC32 JavaDoc();
206         int count;
207         try {
208             while ((count= contentStream.read(readBuffer, 0, readBuffer.length)) != -1) {
209                 checksumCalculator.update(readBuffer, 0, count);
210                 size += count;
211             }
212         } finally {
213             if (contentStream != null)
214                 contentStream.close();
215         }
216         jarEntry.setSize(size);
217         jarEntry.setCrc(checksumCalculator.getValue());
218     }
219     
220     /**
221      * Creates the directory entries for the given path and writes it to the
222      * current archive.
223      *
224      * @param destinationPath the path to add
225      * @param correspondingFile the corresponding file in the file system
226      * or <code>null</code> if it doesn't exist
227      * @throws IOException if an I/O error has occurred
228      */

229     protected void addDirectories(IPath destinationPath, File JavaDoc correspondingFile) throws IOException JavaDoc {
230         String JavaDoc path= destinationPath.toString().replace(File.separatorChar, '/');
231         int lastSlash= path.lastIndexOf('/');
232         List JavaDoc directories= new ArrayList JavaDoc(2);
233         while(lastSlash != -1) {
234             path= path.substring(0, lastSlash + 1);
235             if (!fDirectories.add(path))
236                 break;
237
238             if (correspondingFile != null)
239                 correspondingFile= correspondingFile.getParentFile();
240             long timeStamp= correspondingFile != null && correspondingFile.exists()
241                 ? correspondingFile.lastModified()
242                 : System.currentTimeMillis();
243                 
244             JarEntry JavaDoc newEntry= new JarEntry JavaDoc(path);
245             newEntry.setMethod(ZipEntry.STORED);
246             newEntry.setSize(0);
247             newEntry.setCrc(0);
248             newEntry.setTime(timeStamp);
249             directories.add(newEntry);
250             
251             lastSlash= path.lastIndexOf('/', lastSlash - 1);
252         }
253             
254         for(int i= directories.size() - 1; i >= 0; --i) {
255             fJarOutputStream.putNextEntry((JarEntry JavaDoc)directories.get(i));
256         }
257     }
258
259     /**
260      * Checks if the JAR file can be overwritten.
261      * If the JAR package setting does not allow to overwrite the JAR
262      * then a dialog will ask the user again.
263      *
264      * @param parent the parent for the dialog,
265      * or <code>null</code> if no dialog should be presented
266      * @return <code>true</code> if it is OK to create the JAR
267      */

268     protected boolean canCreateJar(Shell parent) {
269         File JavaDoc file= fJarPackage.getAbsoluteJarLocation().toFile();
270         if (file.exists()) {
271             if (!file.canWrite())
272                 return false;
273             if (fJarPackage.allowOverwrite())
274                 return true;
275             return parent != null && JarPackagerUtil.askForOverwritePermission(parent, fJarPackage.getAbsoluteJarLocation().toOSString());
276         }
277                     
278         // Test if directory exists
279
String JavaDoc path= file.getAbsolutePath();
280         int separatorIndex = path.lastIndexOf(File.separator);
281         if (separatorIndex == -1) // i.e.- default directory, which is fine
282
return true;
283         File JavaDoc directory= new File JavaDoc(path.substring(0, separatorIndex));
284         if (!directory.exists()) {
285             if (JarPackagerUtil.askToCreateDirectory(parent, directory))
286                 return directory.mkdirs();
287             else
288                 return false;
289         }
290         return true;
291     }
292
293     private void registerInWorkspaceIfNeeded() {
294         IPath jarPath= fJarPackage.getAbsoluteJarLocation();
295         IProject[] projects= ResourcesPlugin.getWorkspace().getRoot().getProjects();
296         for (int i= 0; i < projects.length; i++) {
297             IProject project= projects[i];
298             // The Jar is always put into the local file system. So it can only be
299
// part of a project if the project is local as well. So using getLocation
300
// is currently save here.
301
IPath projectLocation= project.getLocation();
302             if (projectLocation != null && projectLocation.isPrefixOf(jarPath)) {
303                 try {
304                     jarPath= jarPath.removeFirstSegments(projectLocation.segmentCount());
305                     jarPath= jarPath.removeLastSegments(1);
306                     IResource containingFolder= project.findMember(jarPath);
307                     if (containingFolder != null && containingFolder.isAccessible())
308                         containingFolder.refreshLocal(IResource.DEPTH_ONE, null);
309                 } catch (CoreException ex) {
310                     // don't refresh the folder but log the problem
311
JavaPlugin.log(ex);
312                 }
313             }
314         }
315     }
316 }
317
Popular Tags