001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.jarpackager;
011:
012: import java.io.BufferedOutputStream;
013: import java.io.ByteArrayOutputStream;
014: import java.io.IOException;
015: import java.io.OutputStream;
016: import java.io.UnsupportedEncodingException;
017:
018: import javax.xml.parsers.DocumentBuilder;
019: import javax.xml.parsers.DocumentBuilderFactory;
020: import javax.xml.parsers.ParserConfigurationException;
021: import javax.xml.transform.OutputKeys;
022: import javax.xml.transform.Transformer;
023: import javax.xml.transform.TransformerException;
024: import javax.xml.transform.TransformerFactory;
025: import javax.xml.transform.dom.DOMSource;
026: import javax.xml.transform.stream.StreamResult;
027:
028: import org.eclipse.core.runtime.Assert;
029: import org.eclipse.core.runtime.CoreException;
030: import org.eclipse.core.runtime.IStatus;
031: import org.eclipse.core.runtime.Status;
032:
033: import org.eclipse.core.resources.IProject;
034: import org.eclipse.core.resources.IResource;
035:
036: import org.eclipse.ltk.core.refactoring.RefactoringCore;
037: import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
038: import org.eclipse.ltk.core.refactoring.RefactoringDescriptorProxy;
039: import org.eclipse.ltk.core.refactoring.history.IRefactoringHistoryService;
040:
041: import org.eclipse.jdt.core.IJavaElement;
042: import org.eclipse.jdt.core.IPackageFragment;
043:
044: import org.eclipse.jdt.ui.jarpackager.IJarDescriptionWriter;
045: import org.eclipse.jdt.ui.jarpackager.JarPackageData;
046:
047: import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
048: import org.eclipse.jdt.internal.ui.JavaPlugin;
049:
050: import org.w3c.dom.DOMException;
051: import org.w3c.dom.Document;
052: import org.w3c.dom.Element;
053:
054: /**
055: * Writes a JarPackage to an underlying OutputStream
056: */
057: public class JarPackageWriter extends Object implements
058: IJarDescriptionWriter {
059:
060: private final OutputStream fOutputStream;
061: private final String fEncoding;
062:
063: /**
064: * Create a JarPackageWriter on the given output stream.
065: * It is the clients responsibility to close the output stream.
066: */
067: public JarPackageWriter(OutputStream outputStream, String encoding) {
068: Assert.isNotNull(outputStream);
069: fOutputStream = new BufferedOutputStream(outputStream);
070: fEncoding = encoding;
071: }
072:
073: public void write(JarPackageData jarPackage) throws CoreException {
074: try {
075: writeXML(jarPackage);
076: } catch (IOException ex) {
077: String message = (ex.getLocalizedMessage() != null ? ex
078: .getLocalizedMessage() : ""); //$NON-NLS-1$
079: throw new CoreException(new Status(IStatus.ERROR,
080: JavaPlugin.getPluginId(),
081: IJavaStatusConstants.INTERNAL_ERROR, message, ex));
082: }
083: }
084:
085: /**
086: * Writes a XML representation of the JAR specification
087: * to to the underlying stream.
088: *
089: * @exception IOException if writing to the underlying stream fails
090: */
091: public void writeXML(JarPackageData jarPackage) throws IOException {
092: Assert.isNotNull(jarPackage);
093: DocumentBuilder docBuilder = null;
094: DocumentBuilderFactory factory = DocumentBuilderFactory
095: .newInstance();
096: factory.setValidating(false);
097: try {
098: docBuilder = factory.newDocumentBuilder();
099: } catch (ParserConfigurationException ex) {
100: throw new IOException(
101: JarPackagerMessages.JarWriter_error_couldNotGetXmlBuilder);
102: }
103: Document document = docBuilder.newDocument();
104:
105: // Create the document
106: Element xmlJarDesc = document
107: .createElement(JarPackagerUtil.DESCRIPTION_EXTENSION);
108: document.appendChild(xmlJarDesc);
109: xmlWriteJarLocation(jarPackage, document, xmlJarDesc);
110: xmlWriteOptions(jarPackage, document, xmlJarDesc);
111: xmlWriteRefactoring(jarPackage, document, xmlJarDesc);
112: xmlWriteSelectedProjects(jarPackage, document, xmlJarDesc);
113: if (jarPackage.areGeneratedFilesExported())
114: xmlWriteManifest(jarPackage, document, xmlJarDesc);
115: xmlWriteSelectedElements(jarPackage, document, xmlJarDesc);
116:
117: try {
118: // Write the document to the stream
119: Transformer transformer = TransformerFactory.newInstance()
120: .newTransformer();
121: transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
122: transformer.setOutputProperty(OutputKeys.ENCODING,
123: fEncoding);
124: transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
125: transformer.setOutputProperty(
126: "{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$
127: DOMSource source = new DOMSource(document);
128: StreamResult result = new StreamResult(fOutputStream);
129: transformer.transform(source, result);
130: } catch (TransformerException e) {
131: throw new IOException(
132: JarPackagerMessages.JarWriter_error_couldNotTransformToXML);
133: }
134: }
135:
136: private void xmlWriteJarLocation(JarPackageData jarPackage,
137: Document document, Element xmlJarDesc) throws DOMException {
138: Element jar = document
139: .createElement(JarPackagerUtil.JAR_EXTENSION);
140: xmlJarDesc.appendChild(jar);
141: jar.setAttribute(
142: "path", jarPackage.getJarLocation().toPortableString()); //$NON-NLS-1$
143: }
144:
145: private void xmlWriteOptions(JarPackageData jarPackage,
146: Document document, Element xmlJarDesc) throws DOMException {
147: Element options = document.createElement("options"); //$NON-NLS-1$
148: xmlJarDesc.appendChild(options);
149: options.setAttribute(
150: "overwrite", "" + jarPackage.allowOverwrite()); //$NON-NLS-2$ //$NON-NLS-1$
151: options
152: .setAttribute(
153: "compress", "" + jarPackage.isCompressed()); //$NON-NLS-2$ //$NON-NLS-1$
154: options.setAttribute(
155: "exportErrors", "" + jarPackage.areErrorsExported()); //$NON-NLS-2$ //$NON-NLS-1$
156: options.setAttribute(
157: "exportWarnings", "" + jarPackage.exportWarnings()); //$NON-NLS-2$ //$NON-NLS-1$
158: options
159: .setAttribute(
160: "saveDescription", "" + jarPackage.isDescriptionSaved()); //$NON-NLS-2$ //$NON-NLS-1$
161: options
162: .setAttribute(
163: "descriptionLocation", jarPackage.getDescriptionLocation().toPortableString()); //$NON-NLS-1$
164: options
165: .setAttribute(
166: "useSourceFolders", "" + jarPackage.useSourceFolderHierarchy()); //$NON-NLS-2$ //$NON-NLS-1$
167: options.setAttribute(
168: "buildIfNeeded", "" + jarPackage.isBuildingIfNeeded()); //$NON-NLS-2$ //$NON-NLS-1$
169: options
170: .setAttribute(
171: "includeDirectoryEntries", "" + jarPackage.areDirectoryEntriesIncluded()); //$NON-NLS-1$//$NON-NLS-2$
172: options
173: .setAttribute(
174: "storeRefactorings", "" + jarPackage.isRefactoringAware()); //$NON-NLS-1$//$NON-NLS-2$
175: }
176:
177: private void xmlWriteRefactoring(JarPackageData jarPackage,
178: Document document, Element xmlJarDesc) throws DOMException {
179: Element refactoring = document
180: .createElement("storedRefactorings"); //$NON-NLS-1$
181: xmlJarDesc.appendChild(refactoring);
182: refactoring
183: .setAttribute(
184: "structuralOnly", "" + jarPackage.isExportStructuralOnly()); //$NON-NLS-1$ //$NON-NLS-2$
185: refactoring
186: .setAttribute(
187: "deprecationInfo", "" + jarPackage.isDeprecationAware()); //$NON-NLS-1$ //$NON-NLS-2$
188: final IProject[] projects = jarPackage.getRefactoringProjects();
189: if (projects != null && projects.length > 0) {
190: for (int index = 0; index < projects.length; index++)
191: refactoring
192: .setAttribute(
193: "project" + (index + 1), projects[index].getName()); //$NON-NLS-1$
194: }
195: final RefactoringDescriptorProxy[] proxies = jarPackage
196: .getRefactoringDescriptors();
197: if (proxies != null && proxies.length > 0) {
198: int count = 1;
199: IRefactoringHistoryService service = RefactoringCore
200: .getHistoryService();
201: try {
202: service.connect();
203: for (int index = 0; index < proxies.length; index++, count++) {
204: try {
205: final ByteArrayOutputStream stream = new ByteArrayOutputStream();
206: service
207: .writeRefactoringDescriptors(
208: new RefactoringDescriptorProxy[] { proxies[index] },
209: stream,
210: RefactoringDescriptor.NONE,
211: true, null);
212: refactoring
213: .setAttribute(
214: "refactoring" + count, stream.toString("UTF-8")); //$NON-NLS-1$ //$NON-NLS-2$
215: } catch (CoreException exception) {
216: JavaPlugin.log(exception);
217: } catch (UnsupportedEncodingException exception) {
218: Assert.isTrue(false);
219: }
220: }
221: } finally {
222: service.disconnect();
223: }
224: }
225: }
226:
227: private void xmlWriteManifest(JarPackageData jarPackage,
228: Document document, Element xmlJarDesc) throws DOMException {
229: Element manifest = document.createElement("manifest"); //$NON-NLS-1$
230: xmlJarDesc.appendChild(manifest);
231: manifest.setAttribute(
232: "manifestVersion", jarPackage.getManifestVersion()); //$NON-NLS-1$
233: manifest.setAttribute(
234: "usesManifest", "" + jarPackage.usesManifest()); //$NON-NLS-2$ //$NON-NLS-1$
235: manifest.setAttribute(
236: "reuseManifest", "" + jarPackage.isManifestReused()); //$NON-NLS-2$ //$NON-NLS-1$
237: manifest.setAttribute(
238: "saveManifest", "" + jarPackage.isManifestSaved()); //$NON-NLS-2$ //$NON-NLS-1$
239: manifest
240: .setAttribute(
241: "generateManifest", "" + jarPackage.isManifestGenerated()); //$NON-NLS-2$ //$NON-NLS-1$
242: manifest
243: .setAttribute(
244: "manifestLocation", jarPackage.getManifestLocation().toPortableString()); //$NON-NLS-1$
245: if (jarPackage.getManifestMainClass() != null)
246: manifest
247: .setAttribute(
248: "mainClassHandleIdentifier", jarPackage.getManifestMainClass().getHandleIdentifier()); //$NON-NLS-1$
249: xmlWriteSealingInfo(jarPackage, document, manifest);
250: }
251:
252: private void xmlWriteSealingInfo(JarPackageData jarPackage,
253: Document document, Element manifest) throws DOMException {
254: Element sealing = document.createElement("sealing"); //$NON-NLS-1$
255: manifest.appendChild(sealing);
256: sealing.setAttribute("sealJar", "" + jarPackage.isJarSealed()); //$NON-NLS-2$ //$NON-NLS-1$
257: Element packagesToSeal = document
258: .createElement("packagesToSeal"); //$NON-NLS-1$
259: sealing.appendChild(packagesToSeal);
260: add(jarPackage.getPackagesToSeal(), packagesToSeal, document);
261: Element packagesToUnSeal = document
262: .createElement("packagesToUnSeal"); //$NON-NLS-1$
263: sealing.appendChild(packagesToUnSeal);
264: add(jarPackage.getPackagesToUnseal(), packagesToUnSeal,
265: document);
266: }
267:
268: private void xmlWriteSelectedElements(JarPackageData jarPackage,
269: Document document, Element xmlJarDesc) throws DOMException {
270: Element selectedElements = document
271: .createElement("selectedElements"); //$NON-NLS-1$
272: xmlJarDesc.appendChild(selectedElements);
273: selectedElements
274: .setAttribute(
275: "exportClassFiles", "" + jarPackage.areClassFilesExported()); //$NON-NLS-2$ //$NON-NLS-1$
276: selectedElements
277: .setAttribute(
278: "exportOutputFolder", "" + jarPackage.areOutputFoldersExported()); //$NON-NLS-2$ //$NON-NLS-1$
279: selectedElements
280: .setAttribute(
281: "exportJavaFiles", "" + jarPackage.areJavaFilesExported()); //$NON-NLS-2$ //$NON-NLS-1$
282: Object[] elements = jarPackage.getElements();
283: for (int i = 0; i < elements.length; i++) {
284: Object element = elements[i];
285: if (element instanceof IResource)
286: add((IResource) element, selectedElements, document);
287: else if (element instanceof IJavaElement)
288: add((IJavaElement) element, selectedElements, document);
289: // Note: Other file types are not handled by this writer
290: }
291: }
292:
293: private void xmlWriteSelectedProjects(JarPackageData jarPackage,
294: Document document, Element xmlJarDesc) throws DOMException {
295: Element selectedElements = document
296: .createElement("selectedProjects"); //$NON-NLS-1$
297: xmlJarDesc.appendChild(selectedElements);
298: Object[] elements = jarPackage.getRefactoringProjects();
299: for (int index = 0; index < elements.length; index++) {
300: Object element = elements[index];
301: if (element instanceof IResource)
302: add((IResource) element, selectedElements, document);
303: }
304: }
305:
306: /**
307: * Closes this stream.
308: * It is the client's responsibility to close the stream.
309: *
310: * @throws CoreException
311: */
312: public void close() throws CoreException {
313: if (fOutputStream != null) {
314: try {
315: fOutputStream.close();
316: } catch (IOException ex) {
317: String message = (ex.getLocalizedMessage() != null ? ex
318: .getLocalizedMessage() : ""); //$NON-NLS-1$
319: throw new CoreException(new Status(IStatus.ERROR,
320: JavaPlugin.getPluginId(),
321: IJavaStatusConstants.INTERNAL_ERROR, message,
322: ex));
323: }
324: }
325: }
326:
327: private void add(IResource resource, Element parent,
328: Document document) {
329: if (resource.getType() == IResource.PROJECT) {
330: Element element = document.createElement("project"); //$NON-NLS-1$
331: parent.appendChild(element);
332: element.setAttribute("name", resource.getName()); //$NON-NLS-1$
333: } else if (resource.getType() == IResource.FILE) {
334: Element element = document.createElement("file"); //$NON-NLS-1$
335: parent.appendChild(element);
336: element.setAttribute(
337: "path", resource.getFullPath().toString()); //$NON-NLS-1$
338: } else if (resource.getType() == IResource.FOLDER) {
339: Element element = document.createElement("folder"); //$NON-NLS-1$
340: parent.appendChild(element);
341: element.setAttribute(
342: "path", resource.getFullPath().toString()); //$NON-NLS-1$
343: }
344: }
345:
346: private void add(IJavaElement javaElement, Element parent,
347: Document document) {
348: Element element = document.createElement("javaElement"); //$NON-NLS-1$
349: parent.appendChild(element);
350: element.setAttribute(
351: "handleIdentifier", javaElement.getHandleIdentifier()); //$NON-NLS-1$
352: }
353:
354: private void add(IPackageFragment[] packages, Element parent,
355: Document document) {
356: for (int i = 0; i < packages.length; i++) {
357: Element pkg = document.createElement("package"); //$NON-NLS-1$
358: parent.appendChild(pkg);
359: pkg
360: .setAttribute(
361: "handleIdentifier", packages[i].getHandleIdentifier()); //$NON-NLS-1$
362: }
363: }
364:
365: /*
366: * This writer always returns OK
367: */
368: public IStatus getStatus() {
369: return new Status(IStatus.OK, JavaPlugin.getPluginId(), 0,
370: "", null); //$NON-NLS-1$
371: }
372: }
|