/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.vdb; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.nio.file.Files; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.teiid.core.designer.util.CoreArgCheck; import org.teiid.core.designer.util.FileUtil; import org.teiid.core.designer.util.FileUtils; import org.teiid.core.designer.util.ModelType; import org.teiid.core.designer.util.OperationUtil; import org.teiid.core.designer.util.OperationUtil.Unreliable; import org.teiid.core.designer.util.StringConstants; import org.teiid.core.designer.util.StringUtilities; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.builder.VdbModelBuilder; import org.teiid.designer.core.util.VdbHelper; import org.teiid.designer.core.util.VdbHelper.VdbFolders; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelUtil; import org.teiid.designer.core.workspace.ModelWorkspaceManager; import org.teiid.designer.roles.DataRole; import org.teiid.designer.transformation.ddl.TeiidModelToDdlGenerator; import org.teiid.designer.vdb.VdbEntry.Synchronization; import org.teiid.designer.vdb.VdbFileEntry.FileEntryType; import org.teiid.designer.vdb.dynamic.DynamicModel; import org.teiid.designer.vdb.dynamic.DynamicVdb; import org.teiid.designer.vdb.dynamic.Metadata; import org.teiid.designer.vdb.manifest.DataRoleElement; import org.teiid.designer.vdb.manifest.EntryElement; import org.teiid.designer.vdb.manifest.ImportVdbElement; import org.teiid.designer.vdb.manifest.ModelElement; import org.teiid.designer.vdb.manifest.PropertyElement; import org.teiid.designer.vdb.manifest.TranslatorElement; import org.teiid.designer.vdb.manifest.VdbElement; import net.jcip.annotations.ThreadSafe; /** * * * @since 8.0 */ @ThreadSafe public final class XmiVdb extends BasicVdb { private static final String WORKING_FILES = "working-files"; //$NON-NLS-1$ /** * @param resource the resource whose Preview VDB prefix is being requested (cannot be <code>null</code>) * @return the Preview VDB prefix (never <code>null</code>) */ public static String getPreviewVdbPrefix( IResource resource ) { CoreArgCheck.isNotNull(resource, "resource is null"); //$NON-NLS-1$ char delim = '_'; StringBuilder name = new StringBuilder(PREVIEW_PREFIX + ModelerCore.workspaceUuid().toString() + delim); if (resource instanceof IFile) { IPath path = resource.getParent().getFullPath(); for (String segment : path.segments()) { name.append(segment).append(delim); } } String prefix = name.toString(); if (prefix.contains(StringConstants.SPACE)) { prefix = prefix.replaceAll(StringConstants.SPACE, StringConstants.UNDERSCORE); } return prefix; } // // All lazily initialised through their own internal methods // private CopyOnWriteArraySet<VdbFileEntry> fileEntries; private CopyOnWriteArraySet<VdbFileEntry> udfJarEntries; private CopyOnWriteArraySet<VdbSchemaEntry> schemaEntries; private CopyOnWriteArraySet<VdbModelEntry> modelEntries; private VdbModelBuilder builder; private boolean excludeSourceMetadata; /** * Default constructor */ public XmiVdb() { super(); } /** * @param file * @param preview indicates if this is a Preview VDB * @throws Exception */ public XmiVdb( final IFile file, final boolean preview ) throws Exception { super(file); setPreview(preview); } /** * @param file * @throws Exception */ public XmiVdb( final IFile file) throws Exception { this(file, false); } private Set<VdbFileEntry> fileEntries() { if (fileEntries == null) fileEntries = new CopyOnWriteArraySet<VdbFileEntry>(); return fileEntries; } private Set<VdbFileEntry> udfJarEntries() { if (udfJarEntries == null) udfJarEntries = new CopyOnWriteArraySet<VdbFileEntry>(); return udfJarEntries; } private Set<VdbSchemaEntry> schemaEntries() { if (schemaEntries == null) schemaEntries = new CopyOnWriteArraySet<VdbSchemaEntry>(); return schemaEntries; } private Set<VdbModelEntry> modelEntries() { if (modelEntries == null) modelEntries = new CopyOnWriteArraySet<VdbModelEntry>(); return modelEntries; } private VdbModelBuilder builder() { if (builder == null) builder = new VdbModelBuilder(); return builder; } @Override public void read(final IFile file) throws Exception { CoreArgCheck.isNotNull(file); if (! file.exists()) return; // Open archive and populate model entries if (file.getLocation().toFile().length() == 0L) { return; } setSourceFile(file); final boolean[] previewable = new boolean[1]; final String[] vdbVersion = new String[1]; final int[] queryTimeout = new int[1]; final String[] valDateTime = new String[1]; final String[] valVersion = new String[1]; final boolean[] autoGen = new boolean[1]; final String[] secDomain = new String[1]; final String[] gssPatt = new String[1]; final String[] pwdPatt = new String[1]; final String[] authType = new String[1]; OperationUtil.perform(new Unreliable() { ZipFile archive = null; InputStream entryStream = null; @Override public void doIfFails() { //TODO } @Override public void finallyDo() throws Exception { if (entryStream != null) entryStream.close(); if (archive != null) archive.close(); } @Override public void tryToDo() throws Exception { XmiVdb vdb = XmiVdb.this; archive = new ZipFile(file.getLocation().toString()); for (final Enumeration<? extends ZipEntry> iter = archive.entries(); iter.hasMoreElements();) { final ZipEntry zipEntry = iter.nextElement(); try { entryStream = archive.getInputStream(zipEntry); if (zipEntry.getName().equals(MANIFEST)) { // Initialize using manifest final Unmarshaller unmarshaller = getJaxbContext().createUnmarshaller(); unmarshaller.setSchema(getManifestSchema()); final VdbElement manifest = (VdbElement)unmarshaller.unmarshal(entryStream); setDescription(manifest.getDescription()); vdbVersion[0] = manifest.getVersion(); vdb.setName(manifest.getName()); // VDB properties for (final PropertyElement property : manifest.getProperties()) { final String name = property.getName(); final String value = property.getValue(); if (Xml.PREVIEW.equals(name)) { previewable[0] = Boolean.parseBoolean(value); // The stored timeout is in milliseconds. We // are converting to seconds for display in // Designer } else if (Xml.QUERY_TIMEOUT.equals(name)) { int timeoutMillis = Integer.parseInt(value); if (timeoutMillis > 0) { queryTimeout[0] = timeoutMillis / 1000; } } else if (Xml.ALLOWED_LANGUAGES.equals(name)) { /* * EXAMPLE XML FRAGMENT multiple properties * allowed with SAME KEY different values * Need to discover and treat these * differently <property * name="allowed-languages" value= * "javascript, perl, php"/> */ String[] langs = StringUtilities.parseCommaDelimitedString(value); for (String lang : langs) { addAllowedLanguage(lang); } } else if (Xml.VALIDATION_DATETIME.equals(name)) { valDateTime[0] = value; } else if (Xml.VALIDATION_VERSION.equals(name)) { valVersion[0] = value; } else if (Xml.SECURITY_DOMAIN.equals(name)) { secDomain[0] = value; } else if (Xml.GSS_PATTERN.equals(name)) { gssPatt[0] = value; } else if (Xml.PASSWORD_PATTERN.equals(name)) { pwdPatt[0] = value; } else if (Xml.AUTHENTICATION_TYPE.equals(name)) { authType[0] = value; } else if (Xml.AUTO_GENERATE_REST_WAR.equals(name)) { autoGen[0] = Boolean.parseBoolean(value); // The stored timeout is in milliseconds. We // are converting to seconds for display in // Designer } else { setProperty(name, value); } } for (final ModelElement element : manifest.getModels()) { IPath path = null; if (element.getPath() != null) { path = Path.fromPortableString(element.getPath()); } /* * Allows migration from old vdbs where xsd * files were considered models */ if (path != null && ModelUtil.isXsdFile(path)) { VdbSchemaEntry vdbSchemaEntry = new VdbSchemaEntry(XmiVdb.this, element); schemaEntries().add(vdbSchemaEntry); } else { modelEntries().add(new VdbModelEntry(XmiVdb.this, element)); } } // Initialize model entry imports only after all // model entries have been created for (final VdbModelEntry entry : modelEntries()) { entry.initializeImports(); } for (final EntryElement element : manifest.getEntries()) { IPath path = Path.fromPortableString(element.getPath()); /* * Xsd files were be added to the manifest as * entries but they should become schema entries * in this runtime instance. */ if (ModelUtil.isXsdFile(path)) { VdbSchemaEntry vdbSchemaEntry = new VdbSchemaEntry(XmiVdb.this, element); schemaEntries().add(vdbSchemaEntry); } else { VdbFileEntry vdbFileEntry = new VdbFileEntry(XmiVdb.this, element); switch (vdbFileEntry.getFileType()) { case UDFJar: udfJarEntries().add(vdbFileEntry); break; case UserFile: fileEntries().add(vdbFileEntry); } } } // Vdb Import entries for (final ImportVdbElement element : manifest.getImportVdbEntries()) { if( getImportVdbEntry(element.getName()) == null ) { addImport(new VdbImportVdbEntry(XmiVdb.this, element)); } } // load translator overrides for (final TranslatorElement translatorElement : manifest.getTranslators()) { addTranslator(new TranslatorOverride(XmiVdb.this, translatorElement)); } for (final DataRoleElement element : manifest.getDataPolicies()) { DataRole dataRole = new DataRole(element); addDataRole(dataRole); } } else if (!zipEntry.isDirectory()) { FileUtils.copy(entryStream, new File(getStagingFolder(), zipEntry.getName())); } } finally { if (entryStream != null) entryStream.close(); } } setChanged(false); } }); setPreview(previewable[0]); setVersion(vdbVersion[0]); setQueryTimeout(queryTimeout[0]); setAutoGenerateRESTWar(autoGen[0]); setSecurityDomain(secDomain[0]); setGssPattern(gssPatt[0]); setPasswordPattern(pwdPatt[0]); setAuthenticationType(authType[0]); if( valDateTime[0] != null ) { SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", java.util.Locale.ENGLISH); //$NON-NLS-1$ setValidationDateTime(format.parse(valDateTime[0])); //new Date(valDateTime[0]); //DateUtil.convertStringToDate(valDateTime[0]); } setValidationVersion(valVersion[0]); } /** * @param path * * @return the newly added {@link VdbEntry entry}, or the existing entry with the supplied name. * @throws Exception */ @Override public final <T extends VdbEntry> T addEntry( final IPath path) throws Exception { CoreArgCheck.isNotNull(path); if (ModelUtil.isXsdFile(path)) { return (T) addSchemaEntry(path); } else if (ModelUtil.isModelFile(path) && !ModelUtil.isXsdFile(path)) return (T) addModelEntry(path); else { String fileType = FileUtil.guessFileType(path.toFile()); FileEntryType fileEntryType = FileEntryType.UserFile; if(VdbHelper.JAR_MIME_TYPE.equals(fileType)) { fileEntryType = FileEntryType.UDFJar; } return (T) addFileEntry(path, fileEntryType); } } /** * @param path * @return the newly added {@link VdbEntry entry}, or the existing entry with the supplied name. * @throws Exception */ private VdbSchemaEntry addSchemaEntry( final IPath path) throws Exception { VdbSchemaEntry schemaEntry = new VdbSchemaEntry(this, path); VdbSchemaEntry addedEntry = addEntry(schemaEntry, schemaEntries()); // entry did not exist in VDB if (schemaEntry == addedEntry) { schemaEntry.synchronizeSchemaEntry(); } else { // entry already existed in VDB schemaEntry = addedEntry; } return schemaEntry; } /** * @param name * @param entryType the type of file entry being added * @return the newly added {@link VdbEntry entry}, or the existing entry with the supplied name. * @throws Exception */ private VdbFileEntry addFileEntry( final IPath name, final VdbFileEntry.FileEntryType entryType) throws Exception { CoreArgCheck.isNotNull(entryType); Set<VdbFileEntry> entries = null; switch (entryType) { case UDFJar: entries = udfJarEntries(); break; case UserFile: entries = fileEntries(); } return addEntry(new VdbFileEntry(this, name, entryType), entries); } private <T extends VdbEntry> T addEntry( final T entry, final Set<T> entries) { // Return existing entry if it exists if (!entries.add(entry)) { for (final T existingEntry : entries) { if (existingEntry.equals(entry)) return existingEntry; } } // Mark VDB as modified setModified(this, Event.ENTRY_ADDED, null, entry); return entry; } /** * @param name * @return the newly added {@link VdbModelEntry model entry}, or the existing entry with the supplied name. * @throws Exception */ private VdbModelEntry addModelEntry( final IPath name) throws Exception { VdbModelEntry modelEntry = new VdbModelEntry(this, name); VdbModelEntry addedEntry = addEntry(modelEntry, modelEntries()); // entry did not exist in VDB if (modelEntry == addedEntry) { modelEntry.synchronizeModelEntry(); } else { // entry already existed in VDB modelEntry = addedEntry; } return modelEntry; } /** * Synchronize the Vdb file entries. The supplied entries must be included - it's VdbModelEntry * may not exist in the vdb yet. * @param newJarEntries the supplied new entries which must exist */ @Override public final void synchronizeUdfJars(Set<VdbFileEntry> newJarEntries) { // Init list of all required Udf jars with supplied list Set<VdbFileEntry> allRequiredUdfJars = new HashSet<VdbFileEntry>(newJarEntries); // Add other Udf jars used by current Model entries for(VdbModelEntry entry: modelEntries()) { Set<VdbFileEntry> jarEntries = entry.getUdfJars(); allRequiredUdfJars.addAll(jarEntries); } // Create map of required jarName to its jar entry Map<String,VdbFileEntry> allRequiredJarsMap = new HashMap<String,VdbFileEntry>(); for(VdbFileEntry fileEntry: allRequiredUdfJars) { allRequiredJarsMap.put(fileEntry.getPath().toOSString(), fileEntry); } // Get the current Udf jar names for this vdb Set<String> currentUdfJarNames = getUdfJarNames(); boolean jarsAdded = false; // Add any missing Udf jars to the vdb that are required for(VdbFileEntry modelUdfJar: allRequiredUdfJars) { if(!currentUdfJarNames.contains(modelUdfJar.getPath().toString())) { udfJarEntries().add(modelUdfJar); jarsAdded = true; } } // Remove any Udf jars that are no longer needed boolean jarsRemoved = false; currentUdfJarNames = getUdfJarNames(); for(String currentJarName: currentUdfJarNames) { Set<String> allRequiredJarNames = allRequiredJarsMap.keySet(); if(!allRequiredJarNames.contains(currentJarName)) { for(VdbEntry entry: udfJarEntries()) { String entryPath = entry.getPath().toOSString(); if(entryPath!=null && entryPath.equals(currentJarName)) { udfJarEntries().remove(entry); break; } } jarsRemoved = true; } } if(jarsAdded || jarsRemoved) { setModified(this, Event.UDF_JARS_MODIFIED, null, null); } } /** * */ @Override public final void close() { fileEntries().clear(); udfJarEntries().clear(); schemaEntries().clear(); modelEntries().clear(); // Clean up state folder FileUtils.removeDirectoryAndChildren(VdbPlugin.singleton().getStateLocation().append(getSourceFile().getFullPath().segment(0)).toFile()); super.close(); } /** * @return the immutable set of entries, not including {@link #getModelEntries() model entries}, within this VDB */ @Override public final Set<VdbEntry> getEntries() { Set<VdbEntry> entries = new HashSet<VdbEntry>(); entries.addAll(schemaEntries()); entries.addAll(fileEntries()); entries.addAll(udfJarEntries()); return Collections.unmodifiableSet(entries); } /** * Get the current set of schema entries. * @return the set of VdbSchemaEntry objects */ @Override public final Set<VdbSchemaEntry> getSchemaEntries() { return Collections.unmodifiableSet(schemaEntries()); } /** * Get the current set of UDF jar entries. * @return the set of VdbFileEntry UDF jar objects */ @Override public final Set<VdbFileEntry> getUdfJarEntries() { return Collections.unmodifiableSet(udfJarEntries()); } /** * Get the current set of UDF jar entries. * @return the set of VdbEntry UDF jar objects */ @Override public final Set<String> getUdfJarNames() { Set<String> udfJarNames = new HashSet<String>(); // The list of UserFiles are those that begin with the UDF path prefix for(VdbFileEntry entry: udfJarEntries()) { // Name of VDB entry String entryPath = entry.getPath().toOSString(); udfJarNames.add(entryPath); } return Collections.unmodifiableSet(udfJarNames); } /** * Get the current set of UserFile entries. * @return the set of VdbFileEntry userFile objects */ @Override public final Set<VdbFileEntry> getUserFileEntries() { return Collections.unmodifiableSet(fileEntries()); } /** * @return the immutable set of model entries within this VDB */ @Override public final Set<VdbModelEntry> getModelEntries() { final Set<VdbModelEntry> entries = new HashSet<VdbModelEntry>(); for (final VdbModelEntry entry : modelEntries()) if (!entry.isBuiltIn()) entries.add(entry); return Collections.unmodifiableSet(entries); } /** * @param entries * @return entries as files */ private final Collection<File> convertEntries(Collection<? extends VdbEntry> entries) { final Collection<File> entryFiles = new ArrayList<File>(); for (VdbEntry entry : entries) { entryFiles.add(new File(getStagingFolder().getAbsolutePath(), entry.getPath().toOSString())); } return Collections.unmodifiableCollection(entryFiles); } /** * Method to return the File objects associated with each model in this VDB. * The intention is to allow the Data Policy wizard to display contents of these models in EMF form so users can * pick/chose and set-up their data entitlements. * * Note: This will no longer return the schema files since they have their own * collection and convert getter method. * * @return the immutable list of model files within this VDB */ @Override public final Collection<File> getModelFiles() { return convertEntries(getModelEntries()); } /** * @return the immutable list of schema files within this VDB */ @Override public final Collection<File> getSchemaFiles() { return convertEntries(getSchemaEntries()); } /** * @param vdbName the name of the imported vdb * @return the <code>VdbImportVdbEntry</code> */ private final VdbImportVdbEntry getImportVdbEntry(String vdbName) { for( VdbImportVdbEntry entry : getImports()) { if( entry.getName().equalsIgnoreCase(vdbName)) { return entry; } } return null; } private final void handleRemovedVdbModelEntry(String vdbModelEntryName) { removeStaleVdbImports(); } /** * @return <code>true</code> if all model entries in this VDB are either synchronized with their associated models or no * associated model exists.. */ @Override public final boolean isSynchronized() { for (final VdbModelEntry entry : modelEntries()) if (entry.getSynchronization() == Synchronization.NotSynchronized) return false; for (final VdbEntry entry : getEntries()) if (entry.getSynchronization() == Synchronization.NotSynchronized) return false; return true; } /** * This method provides VdbModelEntry's the ability to register any dependent import VDB objects * * The VDB contains a list of VdbImportVdbEntry objects (VDB name and version) * * As models are added to the VDB, they are checked to see if there are model imports that are * VDB source models that contain VDB name and VDB Version properties. This is done in the * synchronize method of the VdbModelEntry * * When a model is removed from a VDB (deleted), the VDB needs to be smart enough to check the Import VDB objects * against the remaining models in the VDB to check for VDB References and remove any STALE VDB imports that are not * used anymore. * * * The responsibility of this method is to look at the current map of import VDBs and * * @param importVdbNames the list of imported vdb names * @param modelName the model name (<code>IPath</code>) from the <code>VdbModelEntry</code> */ public final void registerImportVdbs(Collection<VdbImportInfo> vdbImports, String modelName) { removeStaleVdbImports(); // Only add the import if it doesn't already exist for( VdbImportInfo vdbImport : vdbImports ) { if( getImportVdbEntry(vdbImport.getName()) == null ) { addImport(vdbImport.getName(), vdbImport.getVersion()); } } } /** check for VDB References and remove any STALE VDB imports that are not * used anymore. * */ private final void removeStaleVdbImports() { // Collect import vdb names from VdbModelEntries Set<String> allImportVdbNames = new HashSet<String>(); for( VdbModelEntry entry : getModelEntries() ) { allImportVdbNames.addAll(entry.getImportVdbNames()); } // Now check each VdbImportVdbEntry and see if it's name is in this list // Collect any stale VdbImportVdbEntry's Set<VdbImportVdbEntry> staleImports = new HashSet<VdbImportVdbEntry>(); for( VdbImportVdbEntry entry : getImports() ) { if( ! allImportVdbNames.contains(entry.getName())) { staleImports.add(entry); } } for( VdbImportVdbEntry entry : staleImports ) { removeImport(entry); } } /** * @param entry */ @Override public final boolean removeEntry( final VdbEntry entry ) { boolean removed = false; entry.dispose(); if (entry instanceof VdbModelEntry) { String entryPath = entry.getPath().toOSString(); removed = modelEntries().remove(entry); synchronizeUdfJars(new HashSet<VdbFileEntry>()); handleRemovedVdbModelEntry(entryPath); } else if (entry instanceof VdbSchemaEntry) { String entryName = entry.getPath().toOSString(); removed = schemaEntries().remove(entry); handleRemovedVdbModelEntry(entryName); } else { removed = fileEntries().remove(entry); if (!removed) removed = udfJarEntries().remove(entry); } if (removed) setModified(this, Event.ENTRY_REMOVED, entry, null); return removed; } /** * Must not be called unless this VDB has been {@link #isModified() modified} * * @throws Exception */ @Override public void save() throws Exception { // Build JAXB model final VdbElement vdbElement = new VdbElement(this); // Save archive final File tmpFolder = VdbPlugin.singleton().getStateLocation().toFile(); OperationUtil.perform(new Unreliable() { ZipOutputStream out = null; @Override public void doIfFails() { // Do Nothing } @Override public void finallyDo() throws Exception { if (out != null) out.close(); } @Override public void tryToDo() throws Exception { IPath path = getSourceFile().getFullPath(); final File tmpArchive = File.createTempFile(path.removeFileExtension().toString(), '.' + path.getFileExtension(), tmpFolder); tmpArchive.getParentFile().mkdirs(); out = new ZipOutputStream(new FileOutputStream(tmpArchive)); try { // Create VDB manifest final ZipEntry zipEntry = new ZipEntry(MANIFEST); zipEntry.setComment(getDescription()); out.putNextEntry(zipEntry); try { final Marshaller marshaller = getJaxbContext().createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.setSchema(getManifestSchema()); marshaller.marshal(vdbElement, out); } finally { out.closeEntry(); } // Clear all problem markers on VDB file IFile file = getSourceFile(); if (file != null && file.exists()) { IMarker[] markers = file.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); if (markers != null) { for (final IMarker marker : markers) marker.delete(); } } // Save entries for (final VdbEntry entry : getEntries()) entry.save(out); for (final VdbModelEntry entry : modelEntries()) entry.save(out); } finally { // Close zip output stream so its fully writen and any locks are removed. out.close(); out = null; } // Replace archive in workspace with temporary archive File archiveFile = getSourceFile().getLocation().toFile(); try { Files.deleteIfExists(archiveFile.toPath()); } catch (Exception ex) { throw new Exception(VdbPlugin.UTIL.getString("unableToDelete", archiveFile), ex); //$NON-NLS-1$ } if (!tmpArchive.renameTo(archiveFile)) throw new Exception( VdbPlugin.UTIL.getString("unableToRename", tmpArchive, archiveFile)); //$NON-NLS-1$ // Mark as unmodified if (isModified()) setChanged(false); // Notify change listeners notifyChangeListeners(this, Event.SAVED, null, null); } }); } private final void synchronize( final Collection<VdbEntry> entries) throws Exception { for (final VdbEntry entry : entries) if (entry.getSynchronization() == Synchronization.NotSynchronized) entry.synchronize(); } /** * @throws Exception */ @Override public final void synchronize() throws Exception { getBuilder().start(); synchronize(new HashSet<VdbEntry>(modelEntries())); synchronize(getEntries()); getBuilder().stop(); } /** * @return builder */ public VdbModelBuilder getBuilder() { return this.builder(); } /** * @return */ public boolean excludeSourceMetadata() { return excludeSourceMetadata; } /** * @param excludeSourceMetadata */ public void setExcludeSourceMetadata(boolean excludeSourceMetadata) { this.excludeSourceMetadata = excludeSourceMetadata; } @Override public void addDynamicModel(DynamicModel model) { throw new UnsupportedOperationException(); } @Override public Collection<DynamicModel> getDynamicModels() { throw new UnsupportedOperationException(); } @Override public void removeDynamicModel(String modelToRemove) { throw new UnsupportedOperationException(); } @Override public XmiVdb xmiVdbConvert(IFile destination, Properties options) throws Exception { // // TODO copy this vdb to the new destination // return this; } @Override public DynamicVdb dynVdbConvert(IFile destination, Properties options) throws Exception { try { // // Broadcast that a conversion is underway // VdbPlugin.singleton().setConversionInProgress(true); DynamicVdb dynVdb = new DynamicVdb(destination); // // Populate the new vdb with the basic specification // populateVdb(dynVdb); // Remove non-relevant VDB properties // preview true/false dynVdb.getProperties().remove(Xml.PREVIEW); this.getProperties().remove(Xml.PREVIEW); MultiStatus generateStatus = new MultiStatus(VdbConstants.PLUGIN_ID, IStatus.OK, "Exported Dynamic VDB", null); //$NON-NLS-1$ // // Is possible to deploy udf jar archives separately and drop in // a property that references the udf. // for (VdbFileEntry entry : getUdfJarEntries()) { dynVdb.getProperties().setProperty(VdbFolders.UDF.getWriteFolder(), entry.getName()); generateStatus.add(new Status(IStatus.WARNING, PLUGIN_ID, VdbPlugin.UTIL.getString("XmiVdb.udfPropertyAdded", entry.getName())) ); //$NON-NLS-1$ } // // Convert model entries to DynamicModels // for (VdbModelEntry entry : getModelEntries()) { VdbSourceInfo sourceInfo = entry.getSourceInfo(); DynamicModel model = new DynamicModel(); model.setName(entry.getName()); model.setDescription(entry.getDescription()); model.setVisible(entry.isVisible()); for (Map.Entry<Object, Object> prop : entry.getProperties().entrySet()) { String name = prop.getKey().toString(); // // Not applicable to dynamic vdb models since index files are not used // if (EntryElement.INDEX_NAME.equals(name)) continue; // // Not applicable to dynamic vdb models since models are declarative // within the vdb rather than in their own files // if (EntryElement.CHECKSUM.equals(name)) continue; model.setProperty(name, prop.getValue().toString()); } DynamicModel.Type type = DynamicModel.Type.fromString(entry.getType()); model.setModelType(type); model.setAllowMultiSource(sourceInfo.isMultiSource()); model.setAddColumn(sourceInfo.isAddColumn()); model.setColumnAlias(sourceInfo.getColumnAlias()); for (VdbSource source : sourceInfo.getSources()) { VdbSource clone = source.clone(); model.addSource(clone); } boolean isNonRelationalModel = false; if( entry.getType().equals(ModelType.Type.VIRTUAL.getName()) || !excludeSourceMetadata ) { TeiidModelToDdlGenerator generator = new TeiidModelToDdlGenerator(); IFile entryFile = null; if (Synchronization.Synchronized == entry.getSynchronization()) { entryFile = entry.findFileInWorkspace(); } else { entryFile = createEntryFile(entry); } ModelWorkspaceManager workspaceManager = ModelWorkspaceManager.getModelWorkspaceManager(); ModelResource modelResource = (ModelResource) workspaceManager.findModelWorkspaceItem(entryFile, true); if (modelResource == null) throw new Exception("Failed to get model resource for " + entryFile.getLocation().toOSString()); //$NON-NLS-1$ if( ModelUtil.URI_WEB_SERVICES_VIEW_MODEL.equalsIgnoreCase(modelResource.getPrimaryMetamodelUri()) || ModelUtil.URI_FUNCTION_MODEL.equalsIgnoreCase(modelResource.getPrimaryMetamodelUri()) || ModelUtil.URI_XML_SCHEMA_MODEL.equalsIgnoreCase(modelResource.getPrimaryMetamodelUri()) || ModelUtil.URI_XML_VIEW_MODEL.equalsIgnoreCase(modelResource.getPrimaryMetamodelUri()) || ModelUtil.URI_EXTENSION_MODEL.equalsIgnoreCase(modelResource.getPrimaryMetamodelUri())) { isNonRelationalModel = true; generateStatus.add(new Status(IStatus.WARNING, PLUGIN_ID, VdbPlugin.UTIL.getString("XmiVdb.modelNotIncludedMessage", entry.getName())) ); //$NON-NLS-1$ } if( ! isNonRelationalModel ) { String ddl = generator.generate(modelResource); Metadata metadata = new Metadata(ddl, Metadata.Type.DDL); model.setMetadata(metadata); } } if( ! isNonRelationalModel ) { dynVdb.addDynamicModel(model); } } // Check other remaining entries (Xsd, flles etc...) Set<VdbEntry> otherEntries = new HashSet<VdbEntry>(); otherEntries.addAll(getSchemaEntries()); otherEntries.addAll(getUserFileEntries()); for (VdbEntry entry : otherEntries) { generateStatus.add( new Status(IStatus.WARNING, PLUGIN_ID, VdbPlugin.UTIL.getString("XmiVdb.fileNotIncludedMessage", entry.getPath()))); //$NON-NLS-1$ } dynVdb.setStatus(generateStatus); return dynVdb; } finally { VdbPlugin.singleton().setConversionInProgress(false); } } private IFile createEntryFile(VdbModelEntry entry) throws Exception { File realFile = new File(getStagingFolder(), entry.getPath().toOSString()); if (! realFile.exists()) { throw new FileNotFoundException(realFile.getAbsolutePath()); } IProject vdbProject = getSourceFile().getProject(); IFolder workingFolder = vdbProject.getFolder(WORKING_FILES); if (!workingFolder.exists()) workingFolder.create(IResource.HIDDEN, true, null); IFile entryFile = workingFolder.getFile(entry.getPathName()); if (entryFile.exists()) entryFile.delete(true, null); entryFile.createLink(new Path(realFile.getAbsolutePath()), IResource.HIDDEN, null); return entryFile; } @Override public XmiVdb clone() { try { XmiVdb clone = new XmiVdb(getSourceFile()); return clone; } catch (Exception ex) { VdbPlugin.UTIL.log(ex); return null; } } }