KickJava   Java API By Example, From Geeks To Geeks.

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


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

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

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

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

122     public void write(IFile resource, IPath destinationPath) throws CoreException {
123         ByteArrayOutputStream JavaDoc output= new ByteArrayOutputStream JavaDoc();
124         BufferedInputStream JavaDoc contentStream= null;
125         try {
126             contentStream= new BufferedInputStream JavaDoc(resource.getContents(false));
127             int chunkSize= 4096;
128             byte[] readBuffer= new byte[chunkSize];
129             int count;
130             while ((count= contentStream.read(readBuffer, 0, chunkSize)) != -1)
131                 output.write(readBuffer, 0, count);
132         } catch (IOException JavaDoc ex) {
133             throw JarPackagerUtil.createCoreException(ex.getLocalizedMessage(), ex);
134         } finally {
135             try {
136                 if (contentStream != null)
137                     contentStream.close();
138             } catch (IOException JavaDoc ex) {
139                 throw JarPackagerUtil.createCoreException(ex.getLocalizedMessage(), ex);
140             }
141         }
142         try {
143             IPath fileLocation= resource.getLocation();
144             long lastModified= System.currentTimeMillis();
145             File JavaDoc file= null;
146             if (fileLocation != null) {
147                 file= new File JavaDoc(fileLocation.toOSString());
148                 if (file.exists()) {
149                     lastModified= file.lastModified();
150                 }
151             }
152             if (fJarPackage.areDirectoryEntriesIncluded())
153                 addDirectories(destinationPath, file);
154             write(destinationPath, output.toByteArray(), lastModified);
155         } catch (IOException JavaDoc ex) {
156             // Ensure full path is visible
157
String JavaDoc message= null;
158             if (ex.getLocalizedMessage() != null)
159                 message= Messages.format(JarPackagerMessages.JarWriter_writeProblemWithMessage, new Object JavaDoc[] {resource.getFullPath(), ex.getLocalizedMessage()});
160             else
161                 message= Messages.format(JarPackagerMessages.JarWriter_writeProblem, resource.getFullPath());
162             throw JarPackagerUtil.createCoreException(message, ex);
163         }
164     }
165     
166     /**
167      * Creates a new JarEntry with the passed path and contents, and writes it
168      * to the current archive.
169      *
170      * @param path the path inside the archive
171      * @param contents the bytes to write
172      * @param lastModified a long which represents the last modification date
173      * @throws IOException if an I/O error has occurred
174      */

175     protected void write(IPath path, byte[] contents, long lastModified) throws IOException JavaDoc {
176         JarEntry JavaDoc newEntry= new JarEntry JavaDoc(path.toString().replace(File.separatorChar, '/'));
177         if (fJarPackage.isCompressed())
178             newEntry.setMethod(ZipEntry.DEFLATED);
179             // Entry is filled automatically.
180
else {
181             newEntry.setMethod(ZipEntry.STORED);
182             newEntry.setSize(contents.length);
183             CRC32 JavaDoc checksumCalculator= new CRC32 JavaDoc();
184             checksumCalculator.update(contents);
185             newEntry.setCrc(checksumCalculator.getValue());
186         }
187         
188         // Set modification time
189
newEntry.setTime(lastModified);
190
191         try {
192             fJarOutputStream.putNextEntry(newEntry);
193             fJarOutputStream.write(contents);
194         } finally {
195             /*
196              * Commented out because some JREs throw an NPE if a stream
197              * is closed twice. This works because
198              * a) putNextEntry closes the previous entry
199              * b) closing the stream closes the last entry
200              */

201             // fJarOutputStream.closeEntry();
202
}
203     }
204     
205     /**
206      * Add the directory entries for the given path to the jar.
207      *
208      * @param destinationPath the path to add
209      * @param correspondingFile the corresponding file in the file system
210      * or <code>null</code> if it doesn't exist
211      * @throws IOException if an I/O error has occurred
212      */

213     private void addDirectories(IPath destinationPath, File JavaDoc correspondingFile) throws IOException JavaDoc {
214         String JavaDoc path= destinationPath.toString().replace(File.separatorChar, '/');
215         int lastSlash= path.lastIndexOf('/');
216         List JavaDoc directories= new ArrayList JavaDoc(2);
217         while(lastSlash != -1) {
218             path= path.substring(0, lastSlash + 1);
219             if (!fDirectories.add(path))
220                 break;
221
222             if (correspondingFile != null)
223                 correspondingFile= correspondingFile.getParentFile();
224             long timeStamp= correspondingFile != null && correspondingFile.exists()
225                 ? correspondingFile.lastModified()
226                 : System.currentTimeMillis();
227                 
228             JarEntry JavaDoc newEntry= new JarEntry JavaDoc(path);
229             newEntry.setMethod(ZipEntry.STORED);
230             newEntry.setSize(0);
231             newEntry.setCrc(0);
232             newEntry.setTime(timeStamp);
233             directories.add(newEntry);
234             
235             lastSlash= path.lastIndexOf('/', lastSlash - 1);
236         }
237             
238         for(int i= directories.size() - 1; i >= 0; --i) {
239             fJarOutputStream.putNextEntry((JarEntry JavaDoc)directories.get(i));
240         }
241     }
242
243     /**
244      * Checks if the JAR file can be overwritten.
245      * If the JAR package setting does not allow to overwrite the JAR
246      * then a dialog will ask the user again.
247      *
248      * @param parent the parent for the dialog,
249      * or <code>null</code> if no dialog should be presented
250      * @return <code>true</code> if it is OK to create the JAR
251      */

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