| /******************************************************************************* |
| * Copyright (c) 2001, 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.wst.xml.ui.internal.wizards; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Vector; |
| |
| import javax.xml.parsers.DocumentBuilderFactory; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Preferences; |
| import org.eclipse.core.runtime.content.IContentType; |
| import org.eclipse.jface.util.Assert; |
| import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver; |
| import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin; |
| import org.eclipse.wst.common.uriresolver.internal.util.URIHelper; |
| import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames; |
| import org.eclipse.wst.xml.core.internal.XMLCorePlugin; |
| import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry; |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument; |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration; |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap; |
| import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager; |
| import org.eclipse.wst.xml.core.internal.contentmodel.util.ContentBuilder; |
| import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMContentBuilderImpl; |
| import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMWriter; |
| import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| |
| public class NewXMLGenerator { |
| |
| protected String grammarURI; |
| protected CMDocument cmDocument; |
| protected int buildPolicy; |
| protected String rootElementName; |
| |
| protected ICatalogEntry xmlCatalogEntry; |
| |
| // info for dtd |
| protected String publicId; |
| protected String systemId; |
| protected String defaultSystemId; |
| |
| // info for xsd |
| public List namespaceInfoList; |
| |
| public NewXMLGenerator() { |
| super(); |
| } |
| |
| public NewXMLGenerator(String grammarURI, CMDocument cmDocument) { |
| this.grammarURI = grammarURI; |
| this.cmDocument = cmDocument; |
| } |
| |
| |
| public static CMDocument createCMDocument(String uri, String[] errorInfo) { |
| String title = null; |
| String message = null; |
| List errorList = new Vector(); |
| CMDocument cmDocument = null; |
| |
| if (URIHelper.isReadableURI(uri, true)) { |
| // (cs) assume the uri has been provided in a normalized form |
| cmDocument = ContentModelManager.getInstance().createCMDocument(uri, null); |
| |
| if (uri.endsWith(".dtd")) { //$NON-NLS-1$ |
| if (errorList.size() > 0) { |
| title = XMLWizardsMessages._UI_INVALID_GRAMMAR_ERROR; |
| message = XMLWizardsMessages._UI_LABEL_ERROR_DTD_INVALID_INFO; |
| } |
| } |
| else // ".xsd" |
| { |
| // To be consistent with the schema editor validation |
| XMLSchemaValidationChecker validator = new XMLSchemaValidationChecker(); |
| if (!validator.isValid(uri)) { |
| title = XMLWizardsMessages._UI_INVALID_GRAMMAR_ERROR; |
| message = XMLWizardsMessages._UI_LABEL_ERROR_SCHEMA_INVALID_INFO; |
| } |
| else if (cmDocument != null) { |
| int globalElementCount = cmDocument.getElements().getLength(); |
| if (globalElementCount == 0) { |
| title = XMLWizardsMessages._UI_WARNING_TITLE_NO_ROOT_ELEMENTS; |
| message = XMLWizardsMessages._UI_WARNING_MSG_NO_ROOT_ELEMENTS; |
| } |
| } |
| } |
| } |
| else { |
| title = XMLWizardsMessages._UI_WARNING_TITLE_NO_ROOT_ELEMENTS; |
| message = XMLWizardsMessages._UI_WARNING_URI_NOT_FOUND_COLON + " " + uri; //$NON-NLS-1$ |
| } |
| errorInfo[0] = title; |
| errorInfo[1] = message; |
| |
| return cmDocument; |
| } |
| |
| |
| public void createEmptyXMLDocument(IFile newFile) throws Exception { |
| ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
| String charSet = getUserPreferredCharset(); |
| |
| PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, charSet)); |
| writer.println("<?xml version=\"1.0\" encoding=\"" + charSet + "\"?>"); //$NON-NLS-1$ //$NON-NLS-2$ |
| writer.flush(); |
| outputStream.close(); |
| |
| ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); |
| newFile.setContents(inputStream, true, true, null); |
| inputStream.close(); |
| } |
| |
| private String getUserPreferredCharset() { |
| Preferences preference = XMLCorePlugin.getDefault().getPluginPreferences(); |
| String charSet = preference.getString(CommonEncodingPreferenceNames.OUTPUT_CODESET); |
| return charSet; |
| } |
| |
| public void createXMLDocument(String xmlFileName) throws Exception { |
| IContentType contentType = Platform.getContentTypeManager().findContentTypeFor(xmlFileName); |
| String charset = null; |
| if (contentType != null) { |
| charset = contentType.getDefaultCharset(); |
| } |
| ByteArrayOutputStream outputStream = createXMLDocument(xmlFileName, charset); |
| |
| File file = new File(xmlFileName); |
| FileOutputStream fos = new FileOutputStream(file); |
| outputStream.writeTo(fos); |
| fos.close(); |
| } |
| |
| |
| public void createXMLDocument(IFile newFile, String xmlFileName) throws Exception { |
| String charset = newFile.getCharset(); |
| ByteArrayOutputStream outputStream = createXMLDocument(xmlFileName, charset); |
| |
| ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); |
| newFile.setContents(inputStream, true, true, null); |
| inputStream.close(); |
| } |
| |
| |
| public ByteArrayOutputStream createXMLDocument(String xmlFileName, String charset) throws Exception { |
| if (charset == null) { |
| charset = getUserPreferredCharset(); |
| if (charset == null) { |
| charset = "UTF-8"; //$NON-NLS-1$ |
| } |
| } |
| CMDocument cmDocument = getCMDocument(); |
| |
| Assert.isNotNull(cmDocument); |
| Assert.isNotNull(getRootElementName()); |
| |
| // create the xml model |
| CMNamedNodeMap nameNodeMap = cmDocument.getElements(); |
| CMElementDeclaration cmElementDeclaration = (CMElementDeclaration) nameNodeMap.getNamedItem(getRootElementName()); |
| |
| Document xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); |
| DOMContentBuilderImpl contentBuilder = new DOMContentBuilderImpl(xmlDocument); |
| |
| // this 'uglyTempHack' flag is required in order to supress the |
| // creation a default encoding |
| // we'll handle this later in the domWriter.print() method used below |
| // |
| contentBuilder.supressCreationOfDoctypeAndXMLDeclaration = true; |
| contentBuilder.setBuildPolicy(buildPolicy); |
| contentBuilder.setExternalCMDocumentSupport(new MyExternalCMDocumentSupport(namespaceInfoList, xmlFileName)); |
| contentBuilder.createDefaultRootContent(cmDocument, cmElementDeclaration, namespaceInfoList); |
| |
| ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
| OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, charset); |
| |
| DOMWriter domWriter = new DOMWriter(outputStreamWriter); |
| |
| // TODO... instead of relying on file extensions, we need to keep |
| // track of the grammar type |
| // better yet we should reate an SSE document so that we can format it |
| // nicely before saving |
| // then we won't need the DOMWriter at all |
| // |
| domWriter.print(xmlDocument, charset, cmDocument.getNodeName(), getNonWhitespaceString(getPublicId()), getNonWhitespaceString(getSystemId())); |
| outputStream.flush(); |
| outputStream.close(); |
| |
| return outputStream; |
| } |
| |
| |
| public void createNamespaceInfoList() { |
| List result = new Vector(); |
| if (cmDocument != null) { |
| result = (List) cmDocument.getProperty("http://org.eclipse.wst/cm/properties/namespaceInfo"); //$NON-NLS-1$ |
| if (result != null) { |
| int size = result.size(); |
| for (int i = 0; i < size; i++) { |
| NamespaceInfo info = (NamespaceInfo) result.get(i); |
| if (i == 0) { |
| String locationInfo = null; |
| if (xmlCatalogEntry != null) { |
| if (xmlCatalogEntry.getEntryType() == ICatalogEntry.ENTRY_TYPE_PUBLIC) { |
| locationInfo = xmlCatalogEntry.getAttributeValue(ICatalogEntry.ATTR_WEB_URL); |
| } |
| else { |
| locationInfo = xmlCatalogEntry.getKey(); |
| } |
| } |
| if (locationInfo == null) { |
| locationInfo = defaultSystemId; |
| } |
| info.locationHint = locationInfo; |
| info.setProperty("locationHint-readOnly", "true"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| info.setProperty("uri-readOnly", "true"); //$NON-NLS-1$ //$NON-NLS-2$ |
| info.setProperty("unremovable", "true"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| NamespaceInfoContentBuilder builder = new NamespaceInfoContentBuilder(); |
| builder.setBuildPolicy(ContentBuilder.BUILD_ONLY_REQUIRED_CONTENT); |
| builder.visitCMNode(cmDocument); |
| result.addAll(builder.list); |
| } |
| namespaceInfoList = result; |
| } |
| |
| |
| public boolean isMissingNamespaceLocation() { |
| boolean result = false; |
| for (Iterator i = namespaceInfoList.iterator(); i.hasNext();) { |
| NamespaceInfo info = (NamespaceInfo) i.next(); |
| if (info.locationHint == null) { |
| result = true; |
| break; |
| } |
| } |
| return result; |
| } |
| |
| |
| public String[] getNamespaceInfoErrors() { |
| String[] errorList = null; |
| |
| if ((namespaceInfoList != null) && isMissingNamespaceLocation()) { |
| String title = XMLWizardsMessages._UI_LABEL_NO_LOCATION_HINT; |
| String message = XMLWizardsMessages._UI_WARNING_MSG_NO_LOCATION_HINT_1 + " " + XMLWizardsMessages._UI_WARNING_MSG_NO_LOCATION_HINT_2 + "\n\n" + XMLWizardsMessages._UI_WARNING_MSG_NO_LOCATION_HINT_3; //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| errorList = new String[2]; |
| errorList[0] = title; |
| errorList[1] = message; |
| } |
| |
| return errorList; |
| } |
| |
| |
| public void setXMLCatalogEntry(ICatalogEntry catalogEntry) { |
| xmlCatalogEntry = catalogEntry; |
| } |
| |
| public ICatalogEntry getXMLCatalogEntry() { |
| return xmlCatalogEntry; |
| } |
| |
| |
| public void setBuildPolicy(int policy) { |
| buildPolicy = policy; |
| } |
| |
| |
| public void setDefaultSystemId(String sysId) { |
| defaultSystemId = sysId; |
| } |
| |
| public String getDefaultSystemId() { |
| return defaultSystemId; |
| } |
| |
| public void setSystemId(String sysId) { |
| systemId = sysId; |
| } |
| |
| public String getSystemId() { |
| return systemId; |
| } |
| |
| public void setPublicId(String pubId) { |
| publicId = pubId; |
| } |
| |
| public String getPublicId() { |
| return publicId; |
| } |
| |
| public void setGrammarURI(String gramURI) { |
| grammarURI = gramURI; |
| } |
| |
| public String getGrammarURI() { |
| return grammarURI; |
| } |
| |
| public void setCMDocument(CMDocument cmDoc) { |
| cmDocument = cmDoc; |
| } |
| |
| public CMDocument getCMDocument() { |
| return cmDocument; |
| } |
| |
| public void setRootElementName(String rootName) { |
| rootElementName = rootName; |
| } |
| |
| public String getRootElementName() { |
| return rootElementName; |
| } |
| |
| |
| protected class MyExternalCMDocumentSupport implements DOMContentBuilderImpl.ExternalCMDocumentSupport { |
| protected List namespaceInfoList1; |
| protected URIResolver idResolver; |
| protected String resourceLocation; |
| |
| protected MyExternalCMDocumentSupport(List namespaceInfoListParam, String resourceLocation) { |
| this.namespaceInfoList1 = namespaceInfoListParam; |
| this.resourceLocation = resourceLocation; |
| idResolver = URIResolverPlugin.createResolver(); |
| } |
| |
| public CMDocument getCMDocument(Element element, String namespaceURI) { |
| CMDocument result = null; |
| if ((namespaceURI != null) && (namespaceURI.trim().length() > 0)) { |
| String locationHint = null; |
| for (Iterator i = namespaceInfoList1.iterator(); i.hasNext();) { |
| NamespaceInfo info = (NamespaceInfo) i.next(); |
| if (namespaceURI.equals(info.uri)) { |
| locationHint = info.locationHint; |
| break; |
| } |
| } |
| if (locationHint != null) { |
| grammarURI = idResolver.resolve(resourceLocation, locationHint, locationHint); |
| result = ContentModelManager.getInstance().createCMDocument(getGrammarURI(), null); |
| } |
| } |
| else { |
| result = cmDocument; |
| } |
| return result; |
| } |
| } |
| |
| public static String getNonWhitespaceString(String string) { |
| String result = null; |
| if (string != null) { |
| if (string.trim().length() > 0) { |
| result = string; |
| } |
| } |
| return result; |
| } |
| |
| |
| } |