/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.runtime.client.admin; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.teiid.adminapi.Model; import org.teiid.adminapi.impl.DataPolicyMetadata; import org.teiid.adminapi.impl.DataPolicyMetadata.PermissionMetaData; import org.teiid.adminapi.impl.ModelMetaData; import org.teiid.adminapi.impl.SourceMappingMetadata; import org.teiid.adminapi.impl.VDBImportMetadata; import org.teiid.adminapi.impl.VDBMetaData; import org.teiid.adminapi.impl.VDBTranslatorMetaData; import org.teiid.designer.runtime.spi.ITeiidServer; /** * Visitor that will walk a vdb node tree and convert it to * the dynamic vdb xml syntax. */ public class VdbManifestGenerator implements StringConstants { /** * Companion XML tag for permission condition */ public static String DATA_ROLE_PERMISSION_CONDITION_XML = "condition"; //$NON-NLS-1$ private static final String UNDEFINED = "undefined"; //$NON-NLS-1$ private interface ElementTabValue { int VIRTUAL_DATABASE = 0; int VDB_PROPERTY = 1; int DESCRIPTION = 1; int CONNECTION_TYPE = 1; int IMPORT_VDB = 1; int MODEL = 1; int MODEL_PROPERTY = 2; int MODEL_DESCRIPTION = 2; int MODEL_METADATA = 2; int MODEL_VALIDATION = 2; int MODEL_SOURCE = 2; int TRANSLATOR = 1; int TRANSLATOR_PROPERTY = 2; int DATA_ROLE = 1; int DATA_ROLE_DESCRIPTION = 2; int PERMISSION = 2; int MAPPED_ROLE_NAME = 2; int RESOURCE_NAME = 3; int PERMISSION_ALLOW = 3; int CONDITION = 3; int MASK = 3; int ENTRY = 1; int ENTRY_PROPERTY = 2; int ENTRY_DESCRIPTION = 2; } private final StringWriter strWriter; private XMLStreamWriter writer; private final ITeiidServer teiidServer; private final VDBMetaData vdb; /** * Create new visitor that writes to the given xml stream writer * * @param version teiid version * @param writer output for the xml */ public VdbManifestGenerator(ITeiidServer server, VDBMetaData vdb) { super(); this.teiidServer = server; this.vdb = vdb; this.strWriter = new StringWriter(); this.writer = null; try { final XMLOutputFactory xof = XMLOutputFactory.newInstance(); this.writer = xof.createXMLStreamWriter(strWriter); virtualDatabase(vdb); } catch (FactoryConfigurationError e) { e.printStackTrace(); } catch (XMLStreamException e) { e.printStackTrace(); } } public String getManifest() { if( strWriter != null ) { return this.strWriter.toString(); } return EMPTY_STRING; } protected String undefined() { return UNDEFINED; } private void writeNewLine(int total) throws XMLStreamException { for (int i = 0; i < total; ++i) writer.writeCharacters(NEW_LINE); } private void writeNewLine() throws XMLStreamException { writeNewLine(1); } private void writeTab(int total) throws XMLStreamException { for (int i = 0; i < total; ++i) writer.writeCharacters(TAB); } private void writeStartDocument() throws XMLStreamException { writer.writeStartDocument("UTF-8", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$ writeNewLine(); } private void writeStartElement(String tag) throws XMLStreamException { writer.writeStartElement(tag); } private void writeAttribute(String name, String value) throws XMLStreamException { writer.writeAttribute(name, value); } private void writeCData(String data) throws XMLStreamException { writer.writeCData(data); } private void writeCharacters(String characters) throws XMLStreamException { writer.writeCharacters(characters); } private void writeEndElement() throws XMLStreamException { writer.writeEndElement(); writeNewLine(); } private void writeElementWithText(String name, String text) throws XMLStreamException { writeStartElement(name); writeCharacters(text); writeEndElement(); } private void writeEndDocument() throws XMLStreamException { writer.writeEndDocument(); writer.close(); } // private boolean isPrimaryNodeType(Node node, NodeTypeName nodeTypeName) throws RepositoryException { // NodeType nodeType = node.getPrimaryNodeType(); // return nodeTypeName.getId().equals(nodeType.getName()); // } // protected Property property(Node node, String propName) { // if (node == null || propName == null) // return null; // // if (! node.hasProperty(propName)) // return null; // // Property property = node.getProperty(propName); // return property; // } private void properties(int numTabs, Properties exportableProps) throws XMLStreamException { for( Object key : exportableProps.keySet() ) { String name = (String)key; String value = (String)exportableProps.getProperty(name); writeTab(numTabs); writeStartElement(VdbLexicon.ManifestIds.PROPERTY); writeAttribute(VdbLexicon.ManifestIds.NAME, name); writeAttribute(VdbLexicon.ManifestIds.VALUE, value); writeEndElement(); } } private void mask(PermissionMetaData permission ) throws XMLStreamException { String mask = permission.getMask(); if( isNotEmpty(mask) ) { writeTab(ElementTabValue.MASK); // Condition element writeStartElement(VdbLexicon.ManifestIds.MASK); if( permission.getOrder() > 0 ) { writeAttribute(VdbLexicon.ManifestIds.ORDER, Integer.toString(permission.getOrder())); } writeCharacters(mask); writeEndElement(); } } private void condition(PermissionMetaData permission) throws XMLStreamException { String condition = permission.getCondition(); if( isNotEmpty(condition) ) { // Condition element writeTab(ElementTabValue.CONDITION); writeStartElement(VdbLexicon.ManifestIds.CONDITION); if( ! permission.getConstraint() ) { writeAttribute(VdbLexicon.ManifestIds.CONSTRAINT, Boolean.toString(false)); } writeCharacters(condition); writeEndElement(); } } private void permission(PermissionMetaData permission) throws XMLStreamException { // Permission element // writeNewLine(); writeTab(ElementTabValue.PERMISSION); writeStartElement(VdbLexicon.ManifestIds.PERMISSION); // Resource name element writeNewLine(); writeTab(ElementTabValue.RESOURCE_NAME); writeElementWithText(VdbLexicon.ManifestIds.RESOURCE_NAME, permission.getResourceName()); writeTab(ElementTabValue.PERMISSION_ALLOW); try { writeElementWithText(VdbLexicon.ManifestIds.ALLOW_ALTER, Boolean.toString(permission.getAllowAlter())); } catch (NullPointerException e) { // NPE can be ignored writeElementWithText(VdbLexicon.ManifestIds.ALLOW_ALTER, Boolean.toString(false)); } writeTab(ElementTabValue.PERMISSION_ALLOW); try { writeElementWithText(VdbLexicon.ManifestIds.ALLOW_CREATE, Boolean.toString(permission.getAllowCreate())); } catch (NullPointerException e) { // NPE can be ignored writeElementWithText(VdbLexicon.ManifestIds.ALLOW_CREATE, Boolean.toString(false)); } writeTab(ElementTabValue.PERMISSION_ALLOW); try { writeElementWithText(VdbLexicon.ManifestIds.ALLOW_DELETE, Boolean.toString(permission.getAllowDelete())); } catch (NullPointerException e) { // NPE can be ignored writeElementWithText(VdbLexicon.ManifestIds.ALLOW_DELETE, Boolean.toString(false)); } writeTab(ElementTabValue.PERMISSION_ALLOW); try { writeElementWithText(VdbLexicon.ManifestIds.ALLOW_EXECUTE, Boolean.toString(permission.getAllowExecute())); } catch (NullPointerException e) { // NPE can be ignored writeElementWithText(VdbLexicon.ManifestIds.ALLOW_EXECUTE, Boolean.toString(false)); } writeTab(ElementTabValue.PERMISSION_ALLOW); try { writeElementWithText(VdbLexicon.ManifestIds.ALLOW_READ, Boolean.toString(permission.getAllowRead())); } catch (NullPointerException e) { // NPE can be ignored writeElementWithText(VdbLexicon.ManifestIds.ALLOW_READ, Boolean.toString(false)); } writeTab(ElementTabValue.PERMISSION_ALLOW); try { writeElementWithText(VdbLexicon.ManifestIds.ALLOW_UPDATE, Boolean.toString(permission.getAllowUpdate())); } catch (NullPointerException e) { // NPE can be ignored writeElementWithText(VdbLexicon.ManifestIds.ALLOW_UPDATE, Boolean.toString(false)); } writeTab(ElementTabValue.PERMISSION_ALLOW); try { writeElementWithText(VdbLexicon.ManifestIds.ALLOW_LANGUAGE, Boolean.toString(permission.getAllowLanguage())); } catch (NullPointerException e) { // NPE can be ignored writeElementWithText(VdbLexicon.ManifestIds.ALLOW_LANGUAGE, Boolean.toString(false)); } // Conditions condition(permission); // Masks mask(permission); // End Permission writeTab(ElementTabValue.PERMISSION); writeEndElement(); } private void dataRole(List<DataPolicyMetadata> dataPolicies) throws XMLStreamException { for( DataPolicyMetadata policy : dataPolicies ) { // Data Role element writeTab(ElementTabValue.DATA_ROLE); writeStartElement(VdbLexicon.ManifestIds.DATA_ROLE); // Process data role attributes writeAttribute(VdbLexicon.ManifestIds.NAME, policy.getName()); writeAttribute(VdbLexicon.ManifestIds.ANY_AUTHENTICATED, Boolean.toString(policy.isAnyAuthenticated())); writeAttribute(VdbLexicon.ManifestIds.ALLOW_CREATE_TEMP_TABLES, Boolean.toString(policy.isAllowCreateTemporaryTables())); writeAttribute(VdbLexicon.ManifestIds.GRANT_ALL, Boolean.toString(policy.isGrantAll())); writeNewLine(); description(policy.getDescription(), ElementTabValue.DATA_ROLE_DESCRIPTION); // Permissions for( PermissionMetaData permission : policy.getPermissionMap().values()) { permission(permission); } // Mapped Role Names for ( String mrName : policy.getMappedRoleNames()) { writeTab(ElementTabValue.MAPPED_ROLE_NAME); writeElementWithText(VdbLexicon.ManifestIds.MAPPED_ROLE_NAME, mrName); } writeTab(ElementTabValue.DATA_ROLE); writeEndElement(); } } private void translator(List<VDBTranslatorMetaData> translators) throws XMLStreamException { for( VDBTranslatorMetaData translator : translators ) { // Translator element writeTab(ElementTabValue.TRANSLATOR); writeStartElement(VdbLexicon.ManifestIds.TRANSLATOR); // Process translator attributes writeAttribute(VdbLexicon.ManifestIds.NAME, translator.getName()); writeAttribute(VdbLexicon.ManifestIds.TYPE, translator.getType()); if( translator.getDescription() != null ) { writeAttribute(VdbLexicon.ManifestIds.DESCRIPTION, translator.getDescription()); } writeNewLine(); // Process property attributes // TODO: ADD TRANSLATOR PROPERTIES // Properties exportableProps = filterExportableProperties(node.getProperties(), VdbLexicon.Translator.TYPE, VdbLexicon.Translator.DESCRIPTION); // properties(node, ElementTabValue.TRANSLATOR_PROPERTY, exportableProps); writeTab(ElementTabValue.TRANSLATOR); writeEndElement(); } } private void source( SourceMappingMetadata source) throws XMLStreamException { // Translator element writeTab(ElementTabValue.MODEL_SOURCE); writeStartElement(VdbLexicon.ManifestIds.SOURCE); // Process source attributes writeAttribute(VdbLexicon.ManifestIds.NAME, source.getName()); writeAttribute(VdbLexicon.ManifestIds.TRANSLATOR_NAME, source.getTranslatorName()); writeAttribute(VdbLexicon.ManifestIds.JNDI_NAME, source.getConnectionJndiName()); writeEndElement(); } private void model(ModelMetaData model) throws XMLStreamException { writeTab(ElementTabValue.MODEL); writeStartElement(VdbLexicon.ManifestIds.MODEL); writeAttribute(VdbLexicon.ManifestIds.NAME, model.getName()); boolean isVirtual = model.getModelType().equals(Model.Type.VIRTUAL); writeAttribute(VdbLexicon.ManifestIds.TYPE, model.getModelType().toString()); // If PATH is not null, then it's an EMF-based .vdb file and we throw it away // if (isNotEmpty(model.getPath()) ) { // writeAttribute(VdbLexicon.ManifestIds.PATH, model.getPath()); // } if (! model.isVisible() ) { // True is the default value so no need to include if true writeAttribute(VdbLexicon.ManifestIds.VISIBLE, Boolean.toString(false)); } writeNewLine(); description(model.getDescription(), ElementTabValue.MODEL_DESCRIPTION); // TODO: HANDLE MODEL PROPERTIES // Properties exportableProps = filterExportableProperties(node.getProperties(), CoreLexicon.JcrId.MODEL_TYPE); // // properties(node, ElementTabValue.MODEL_PROPERTY, exportableProps); // Properties elements Properties exportableProps = new Properties(); for(Object key : model.getProperties().keySet() ) { String keyStr = (String)key; if( ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.TYPE) && ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.MODEL_UUID) && ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.MODEL_CLASS) && ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.INDEX_NAME) && ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.BUILT_IN) && ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.IMPORTS) && ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.CHECKSUM)) { exportableProps.put(keyStr, model.getProperties().get(key)); } } properties(ElementTabValue.VDB_PROPERTY, exportableProps); // Sources for( SourceMappingMetadata source : model.getSourceMappings()) { source(source); } // Metadata TAB ONLY if( model.getSchemaText() != null && model.getSchemaText().length() > 0) { writeTab(ElementTabValue.MODEL_METADATA); writeStartElement(VdbLexicon.ManifestIds.METADATA); writeAttribute(VdbLexicon.ManifestIds.TYPE, "DDL"); writeNewLine(); writeTab(ElementTabValue.MODEL_METADATA + 1); writeCData(model.getSchemaText()); // end metadata tag writeNewLine(); writeTab(ElementTabValue.MODEL_METADATA + 1); writeNewLine(); writeTab(ElementTabValue.MODEL_METADATA); writeEndElement(); } else { // if( isVirtual ) { try { String ddl = teiidServer.getSchema(vdb.getName(), vdb.getVersion(), model.getName()); if( ddl != null ) { writeTab(ElementTabValue.MODEL_METADATA); writeStartElement(VdbLexicon.ManifestIds.METADATA); writeAttribute(VdbLexicon.ManifestIds.TYPE, "DDL"); writeNewLine(); writeTab(ElementTabValue.MODEL_METADATA + 1); String filteredDdl = TeiidOptionsUtil.filterUuidsFromOptions(ddl); writeCData(filteredDdl); // end metadata tag writeNewLine(); writeTab(ElementTabValue.MODEL_METADATA + 1); writeNewLine(); writeTab(ElementTabValue.MODEL_METADATA); writeEndElement(); } } catch (Exception e) { e.printStackTrace(); } // } } // End model tag writeTab(ElementTabValue.MODEL); writeEndElement(); } private void importVdbs(List<VDBImportMetadata> vdbImports) throws XMLStreamException { for( VDBImportMetadata vdbImport : vdbImports ) { // Import-vdb element writeTab(ElementTabValue.IMPORT_VDB); writeStartElement(VdbLexicon.ManifestIds.IMPORT_VDB); // Process import-vdb attributes writeAttribute(VdbLexicon.ManifestIds.NAME, vdbImport.getName()); writeAttribute(VdbLexicon.ManifestIds.VERSION, vdbImport.getVersion()); writeAttribute(VdbLexicon.ManifestIds.IMPORT_DATA_POLICIES, Boolean.toString(vdbImport.isImportDataPolicies())); writeTab(ElementTabValue.IMPORT_VDB); writeEndElement(); } } private void description(String description, int numTabs) throws XMLStreamException { if (isNotEmpty(description)) { writeTab(numTabs); writeElementWithText(VdbLexicon.ManifestIds.DESCRIPTION, description); } } // private Properties filterExportableProperties(PropertyIterator propIter, String... propertiesToIgnore) { // Properties exportableProps = new Properties(); // List<String> propsToIgnore = Arrays.asList(propertiesToIgnore); // // while(propIter.hasNext()) { // Property property = propIter.nextProperty(); // String name = property.getName(); // if (name == null) // continue; // // if (propsToIgnore.contains(name)) // continue; // // // Ignore jcr properties since these are internal to modeshape // if (name.startsWith(JcrLexicon.Namespace.PREFIX)) // continue; // // // String value = toString(property); // // // // // Ignore modeshape vdb properties as <property> type properties will // // not have a vdb prefix but simply be the property name on its own, eg. // // UseConnectedMetadata or vdb-property1. // // // if (name.startsWith(VdbLexicon.Namespace.PREFIX + COLON)) { // // // // Preview is actually converted into a vdb property so need to special-case // // turn it back into a simple property name but we only care if the property // // is actually true. // // // if (name.equals(VdbLexicon.Vdb.PREVIEW) && Boolean.parseBoolean(value)) { // name = VdbLexicon.ManifestIds.PREVIEW; // } else { // continue; // } // } // // // // exportableProps.put(name, value); // } // // return exportableProps; // } private void virtualDatabase(VDBMetaData vdb) throws XMLStreamException { // Start new document writeStartDocument(); // Vdb element writeTab(ElementTabValue.VIRTUAL_DATABASE); writeStartElement(VdbLexicon.ManifestIds.VDB); // Name attribute writeAttribute(VdbLexicon.ManifestIds.NAME, vdb.getName()); // Version attribute writeAttribute(VdbLexicon.ManifestIds.VERSION, vdb.getVersion()); writeNewLine(2); // Description element description(vdb.getDescription(), ElementTabValue.DESCRIPTION); // Connection Type element if (vdb.getConnectionType() != null) { writeTab(ElementTabValue.CONNECTION_TYPE); writeElementWithText(VdbLexicon.ManifestIds.CONNECTION_TYPE, vdb.getConnectionType().toString()); } // Properties elements Properties exportableProps = new Properties(); for(Object key : vdb.getProperties().keySet() ) { String keyStr = (String)key; if( ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.DESCRIPTION) && ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.CONNECTION_TYPE) && ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.VERSION) && ! keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.DEPLOYMENT_NAME) ) { if( keyStr.equalsIgnoreCase(VdbLexicon.ManifestIds.PREVIEW)) { String value = vdb.getPropertyValue(keyStr); if( Boolean.FALSE.toString().toUpperCase().equalsIgnoreCase(value)) { continue; } } exportableProps.put(keyStr, vdb.getProperties().get(key)); } } properties(ElementTabValue.VDB_PROPERTY, exportableProps); writeNewLine(); // // Visit vdb children by name since the xsd demands them in a specific order // // Import Vdbs importVdbs(vdb.getVDBImports()); // Models for( ModelMetaData model : vdb.getModelMetaDatas().values()) { model(model); } // Translators List<VDBTranslatorMetaData> overrides = new ArrayList<VDBTranslatorMetaData>(); for( VDBTranslatorMetaData override : vdb.getOverrideTranslatorsMap().values() ) { overrides.add(override); } translator(overrides); // Data Roles List<DataPolicyMetadata> dataroles = new ArrayList<DataPolicyMetadata>(); for( DataPolicyMetadata datarole : vdb.getDataPolicyMap().values() ) { dataroles.add(datarole); } dataRole(dataroles); writeNewLine(); // Close out the xml document writeTab(ElementTabValue.VIRTUAL_DATABASE); writeEndElement(); writeEndDocument(); } private boolean isNotEmpty(String str) { return str != null && str.trim().length() > 0; } }