// ============================================================================ // // Copyright (C) 2006-2012 Talend Inc. - www.talend.com // // This source code is available under agreement available at // %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt // // You should have received a copy of the agreement // along with this program; if not, write to Talend SA // 9 rue Pages 92150 Suresnes, France // // ============================================================================ package org.talend.repository.model.migration; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import org.apache.log4j.Logger; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.m2m.atl.core.ATLCoreException; import org.talend.commons.ui.runtime.exception.ExceptionHandler; import org.talend.core.GlobalServiceRegister; import org.talend.core.database.EDatabaseTypeName; import org.talend.core.model.metadata.builder.connection.DatabaseConnection; import org.talend.core.model.metadata.builder.database.EDatabaseSchemaOrCatalogMapping; import org.talend.core.model.metadata.builder.database.ExtractMetaDataUtils; import org.talend.core.model.migration.AbstractItemMigrationTask; import org.talend.core.model.properties.ConnectionItem; import org.talend.core.model.properties.Item; import org.talend.core.model.properties.Property; import org.talend.core.model.repository.ERepositoryObjectType; import org.talend.core.repository.utils.URIHelper; import org.talend.cwm.helper.CatalogHelper; import org.talend.cwm.helper.ConnectionHelper; import org.talend.cwm.helper.SwitchHelpers; import org.talend.designer.core.model.utils.emf.talendfile.ContextType; import org.talend.model.migration.TosMetadataMigrationFrom400to410; import org.talend.repository.ProjectManager; import org.talend.repository.constants.FileConstants; import org.talend.repository.model.IRepositoryService; import org.talend.repository.ui.utils.ConnectionContextHelper; import orgomg.cwm.resource.relational.Catalog; import orgomg.cwm.resource.relational.RelationalFactory; import orgomg.cwm.resource.relational.Schema; /** * DOC hywang class global comment. Detailled comment */ public class MergeTosMetadataMigrationTask extends AbstractItemMigrationTask { private static Logger log = Logger.getLogger(MergeTosMetadataMigrationTask.class); TosMetadataMigrationFrom400to410 metadata400to410 = new TosMetadataMigrationFrom400to410(); IRepositoryService service = (IRepositoryService) GlobalServiceRegister.getDefault().getService(IRepositoryService.class); static final HashMap<String, Object> XML_SAVE_OTIONS_1_0 = new HashMap<String, Object>(2); static final HashMap<String, Object> XML_SAVE_OTIONS_1_1 = new HashMap<String, Object>(2); static { XML_SAVE_OTIONS_1_0.put(XMLResource.OPTION_ENCODING, "UTF-8"); //$NON-NLS-1$ XML_SAVE_OTIONS_1_0.put(XMLResource.OPTION_XML_VERSION, "1.0"); //$NON-NLS-1$ XML_SAVE_OTIONS_1_1.put(XMLResource.OPTION_ENCODING, "UTF-8"); //$NON-NLS-1$ XML_SAVE_OTIONS_1_1.put(XMLResource.OPTION_XML_VERSION, "1.1"); //$NON-NLS-1$ } public ResourceSet resourceSet = new ResourceSetImpl(); @Override public ExecutionResult execute(Item item) { if (item instanceof ConnectionItem) { try { URI itemURI = getItemURI(item); if (itemURI != null) { URI itemResourceURI = getItemResourceURI(itemURI); Resource migratedResource = metadata400to410.migrate(itemResourceURI.toString(), new NullProgressMonitor()); HashMap<String, Object> xmlSaveOtions = XML_SAVE_OTIONS_1_0; if (migratedResource != null) { // check for DB connection caus we need to setup Schema and Catalog properly EObject content = migratedResource.getContents().get(0); if (content != null && "DatabaseConnection".equals(content.eClass().getName())) { // resource is dynamic EMF so convert it to static model by serialising it and reloading it ByteArrayOutputStream tempStream = new ByteArrayOutputStream(); try { // serialize into memory try { migratedResource.save(tempStream, XML_SAVE_OTIONS_1_0); } catch (Exception e) { // try with version 1.1 tempStream = new ByteArrayOutputStream(); xmlSaveOtions = XML_SAVE_OTIONS_1_1; migratedResource.save(tempStream, xmlSaveOtions); } finally { tempStream.close(); } // create a resource to laod the inmemory resource that should be a static EMF model migratedResource = resourceSet.createResource(URI .createURI("http://talend/dummy_static.metadata")); //$NON-NLS-1$ migratedResource.load(new ByteArrayInputStream(tempStream.toByteArray()), xmlSaveOtions); // check that DBConnection is firdt element DatabaseConnection databaseConnection = SwitchHelpers.DATABASECONNECTION_SWITCH .doSwitch(migratedResource.getContents().get(0)); // do not check for null caus DB connection is already check above String databaseType = databaseConnection.getDatabaseType(); databaseConnection.setDriverClass(ExtractMetaDataUtils.getDriverClassByDbType(databaseType)); EDatabaseTypeName currentType = EDatabaseTypeName.getTypeFromDbType(databaseType); EDatabaseSchemaOrCatalogMapping curCatalog = currentType.getCatalogMappingField(); EDatabaseSchemaOrCatalogMapping curSchema = currentType.getSchemaMappingField(); // all the DB connection are migrated with a Schema by default if (!curCatalog.equals(EDatabaseSchemaOrCatalogMapping.None)) { List<Schema> schemas = ConnectionHelper.getSchema(databaseConnection); if (!curSchema.equals(EDatabaseSchemaOrCatalogMapping.None)) { // we need to place the current schemas into a catalogs ConnectionHelper.removeSchemas(schemas, databaseConnection); for (Schema schema : schemas) { // compute the name of the schema and the catalogs String schemaName = computeSchemaName(schema, databaseConnection, curSchema); String catalogName = computeCatalogName(databaseConnection, curCatalog); schema.setName(schemaName); Catalog catalog = RelationalFactory.eINSTANCE.createCatalog(); // catalogs are not in a contained reference migratedResource.getContents().add(catalog); catalog.setName(catalogName); // add the schema to the catalog and the the catalog to the connection CatalogHelper.addSchemas(Collections.singleton(schema), catalog); ConnectionHelper.addCatalog(catalog, databaseConnection); } } else { // we need to replace the Schemas with a Catalogs for (Schema schema : schemas) { // compute the name the catalog String catalogName = computeCatalogName(databaseConnection, curCatalog); // use owned elements to get everything regardless of tables or views or // else Catalog catalog = RelationalFactory.eINSTANCE.createCatalog(); // catalogs are not in a contained reference migratedResource.getContents().add(catalog); catalog.setName(catalogName); catalog.getOwnedElement().addAll(schema.getOwnedElement()); ConnectionHelper.addCatalog(catalog, databaseConnection); ConnectionHelper.removeSchemas(Collections.singleton(schema), databaseConnection); } } } else if (!curSchema.equals(EDatabaseSchemaOrCatalogMapping.None)) { List<Schema> schemas = ConnectionHelper.getSchema(databaseConnection); for (Schema schema : schemas) { String schemaName = computeSchemaName(schema, databaseConnection, curSchema); schema.setName(schemaName); } } // else no catalog so we keep the schema as is } catch (Exception e) { // we have an exception finalising the migration but we trap it caus we still try to // save it log.error("Cannot complete merge metadata migration on file:" + itemResourceURI.toString(), e); ExceptionHandler.process(e); } finally { tempStream.close(); } } // else not a DB connection so persist OutputStream outputStream = item.eResource().getResourceSet().getURIConverter() .createOutputStream(itemResourceURI, null); try { migratedResource.save(outputStream, xmlSaveOtions); } finally { outputStream.close(); } } return ExecutionResult.SUCCESS_WITH_ALERT; } } catch (ATLCoreException e) { log.error(e); ExceptionHandler.process(e); return ExecutionResult.SUCCESS_NO_ALERT; } catch (IOException e) { log.error(e); ExceptionHandler.process(e); return ExecutionResult.SUCCESS_NO_ALERT; } finally { resourceSet.getResources().clear(); } } return ExecutionResult.NOTHING_TO_DO; } /** * compute the schema name. * * @param schema the schema to compute the name from * @param databaseConnection the DB connection caus some of the name are issued from the DB connection * @param curSchema, the type of name for the schema * @return string corresponding to the naming convention of schemaNameType */ private String computeSchemaName(Schema schema, DatabaseConnection connection, EDatabaseSchemaOrCatalogMapping schemaNameType) { String result = ""; //$NON-NLS-1$ ContextType contextType = ConnectionContextHelper.getContextTypeForContextMode(null, connection, null, true); switch (schemaNameType) { case Login: result = connection.getUsername(); break; case Schema: if (contextType != null) { result = ConnectionContextHelper.getOriginalValue(contextType, schema.getName()); } else { /* if schema name is null,return a empty string is required,bug 0017244 */ if (schema.getName() != null) { result = schema.getName(); } } break; case Sid: result = connection.getSID(); break; case Default_Name: result = connection.getName(); break; case None: // return an empty string break; default:// return an empty string break; } return result; } /** * compute the catalog name. * * @param databaseConnection the DB connection caus some of the name are issued from the DB connection * @param catalogNameType, the type of name for the catalog * @return the string corresponding to the naming convention of catalogNameType */ private String computeCatalogName(DatabaseConnection connection, EDatabaseSchemaOrCatalogMapping catalogNameType) { String result = ""; //$NON-NLS-1$ ContextType contextType = ConnectionContextHelper.getContextTypeForContextMode(null, connection, null, true); switch (catalogNameType) { case Login: result = connection.getUsername(); break; case Sid: if (contextType != null) { result = ConnectionContextHelper.getOriginalValue(contextType, connection.getSID()); } else { result = connection.getSID(); } break; case Default_Name: result = connection.getName(); break; case Schema: case None: default:// return an empty string break; } return result; } private URI getItemURI(Item item) { ProjectManager pManager = ProjectManager.getInstance(); org.talend.core.model.general.Project project = new org.talend.core.model.general.Project(pManager.getProject(item)); // referenced item if (project != null && !project.equals(pManager.getCurrentProject())) { String folder = ERepositoryObjectType.getFolderName(ERepositoryObjectType.getItemType(item)); if (folder != null) { IPath path = new Path(project.getTechnicalLabel()); path = path.append(folder); path = path.append(item.getState().getPath()); Property property = item.getProperty(); String itemStr = property.getLabel() + "_" + property.getVersion() + "." + FileConstants.PROPERTIES_EXTENSION; //$NON-NLS-1$ //$NON-NLS-2$ path = path.append(itemStr); return URIHelper.convert(path); } } if (item.eResource() != null) { // the migrationtask execute two times,after reload in first tiem,this one will // be null return item.eResource().getURI(); } return null; } private URI getItemResourceURI(URI propertyResourceURI) { return propertyResourceURI.trimFileExtension().appendFileExtension(FileConstants.ITEM_EXTENSION); } // // private Resource getItemResource(Item item) { // URI itemResourceURI = getItemResourceURI(getItemURI(item)); // Resource itemResource = resourceSet.getResource(itemResourceURI, false); // // if (itemResource == null) { // if (item instanceof FileItem) { // itemResource = new ByteArrayResource(itemResourceURI); // resourceSet.getResources().add(itemResource); // } // itemResource = resourceSet.getResource(itemResourceURI, true); // } // // return itemResource; // } public Date getOrder() { // TODO Auto-generated method stub GregorianCalendar gc = new GregorianCalendar(2000, 6, 29, 10, 20, 0); return gc.getTime(); } }