All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.atomikos.icatch.provider.imp.AssemblerImp Maven / Gradle / Ivy

/**
 * Copyright (C) 2000-2023 Atomikos 
 *
 * LICENSE CONDITIONS
 *
 * See http://www.atomikos.com/Main/WhichLicenseApplies for details.
 */

package com.atomikos.icatch.provider.imp;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.ServiceLoader;

import com.atomikos.icatch.CompositeTransactionManager;
import com.atomikos.icatch.SysException;
import com.atomikos.icatch.config.Configuration;
import com.atomikos.icatch.event.EventListener;
import com.atomikos.icatch.imp.CompositeTransactionManagerImp;
import com.atomikos.icatch.imp.TransactionServiceImp;
import com.atomikos.icatch.provider.Assembler;
import com.atomikos.icatch.provider.ConfigProperties;
import com.atomikos.icatch.provider.TransactionServiceProvider;
import com.atomikos.logging.LoggerFactory;
import com.atomikos.persistence.imp.StateRecoveryManagerImp;
import com.atomikos.publish.EventPublisher;
import com.atomikos.recovery.LogException;
import com.atomikos.recovery.OltpLog;
import com.atomikos.recovery.OltpLogFactory;
import com.atomikos.recovery.RecoveryLog;
import com.atomikos.recovery.fs.CachedRepository;
import com.atomikos.recovery.fs.FileSystemRepository;
import com.atomikos.recovery.fs.InMemoryRepository;
import com.atomikos.recovery.fs.OltpLogImp;
import com.atomikos.recovery.fs.RecoveryLogImp;
import com.atomikos.recovery.fs.Repository;
import com.atomikos.util.Atomikos;
import com.atomikos.util.ClassLoadingHelper;
import com.atomikos.util.UniqueIdMgr;

public class AssemblerImp implements Assembler {
	
	private static final String DEFAULT_PROPERTIES_FILE_NAME = "transactions-defaults.properties";

	private static final String JTA_PROPERTIES_FILE_NAME = "jta.properties";

	private static final String TRANSACTIONS_PROPERTIES_FILE_NAME = "transactions.properties";

	private static final int MAX_TID_LENGTH = 64; //XID limitation
	
	private static com.atomikos.logging.Logger LOGGER = LoggerFactory.createLogger(AssemblerImp.class);
	
	
    private void loadPropertiesFromClasspath(Properties p, String fileName){
    		URL url = null;
    		
    		//first look in application classpath (cf ISSUE 10091)
    		url = ClassLoadingHelper.loadResourceFromClasspath(getClass(), fileName);		
    		if (url == null) {
    			url = getClass().getClassLoader().getSystemResource ( fileName );
    		}
    		if (url != null) {
    			loadPropertiesFromUrl(p, url);
    		} else {
    			LOGGER.logTrace("Could not find expected property file: " + fileName);
    		}
    }

	private void loadPropertiesFromUrl(Properties p, URL url) {
		InputStream in;
		try {
			in = url.openStream();
			p.load(in);
			in.close();
			LOGGER.logInfo("Loaded " + url.toString());
		} catch (IOException e) {
			LOGGER.logTrace("Failed to load property file: " + url.toString(), e);
		}
	}

	/**
	 * Called by ServiceLoader.
	 */
	public AssemblerImp() {
	}

	@Override
	public ConfigProperties initializeProperties() {
		Properties defaults = new Properties();
		loadPropertiesFromClasspath(defaults, DEFAULT_PROPERTIES_FILE_NAME);
		Properties transactionsProperties = new Properties(defaults);
		loadPropertiesFromClasspath(transactionsProperties, TRANSACTIONS_PROPERTIES_FILE_NAME);
		Properties jtaProperties = new Properties(transactionsProperties);
		loadPropertiesFromClasspath(jtaProperties, JTA_PROPERTIES_FILE_NAME);
		Properties customProperties = new Properties(jtaProperties);
		loadPropertiesFromCustomFilePath(customProperties);
		Properties finalProperties = new Properties(customProperties);
		ConfigProperties configProperties = new ConfigProperties(finalProperties);
		checkRegistration(configProperties);
		return configProperties;
	}
	private void checkRegistration(ConfigProperties configProperties) {
		if (configProperties.getCompletedProperties().getProperty("com.atomikos.icatch.registered") == null) {
			String message =
			        "Thanks for using Atomikos! This installation is not registered yet. \n" + 
			        "REGISTER FOR FREE at http://www.atomikos.com/Main/RegisterYourDownload and receive:\n" + 
			        "- tips & advice \n" + 
			        "- working demos \n" + 
			        "- access to the full documentation \n" + 
			        "- special exclusive bonus offers not available to others \n" + 
			        "- everything you need to get the most out of using Atomikos!";
			
			LOGGER.logWarning(message);
			System.out.println(message);
		}
		if (Atomikos.isEvaluationVersion()) {
			String message ="This product (ExtremeTransactions) is licensed for DEVELOPMENT ONLY - for production use you need to purchase a subscription via https://www.atomikos.com/Main/BuyOnline";
			LOGGER.logWarning(message);
			System.err.println(message);
		}
	}

	private void loadPropertiesFromCustomFilePath(Properties customProperties) {
		String customFilePath = System.getProperty(ConfigProperties.FILE_PATH_PROPERTY_NAME);
		if (customFilePath != null) {
			File file = new File(customFilePath);
			URL url;
			try {
				url = file.toURL();
				loadPropertiesFromUrl(customProperties, url);
			} catch (MalformedURLException e) {
				LOGGER.logFatal("File not found: " + customFilePath);
			}
		}
	}


	private void logProperties(Properties properties) {
		LOGGER.logInfo("USING core version: " + Atomikos.VERSION);
		for (Entry entry : properties.entrySet()) {
			LOGGER.logInfo("USING: " + entry.getKey() + " = " + entry.getValue());
		}
	}

	private void findAllEventListenersInClassPath() {
		ServiceLoader loader = ServiceLoader.load(EventListener.class, EventPublisher.class.getClassLoader());
		for (EventListener l : loader) {
			EventPublisher.INSTANCE.registerEventListener(l);
		}
	}

	@Override
	public TransactionServiceProvider assembleTransactionService(ConfigProperties configProperties) {
		findAllEventListenersInClassPath();
		RecoveryLog recoveryLog =null;
		logProperties(configProperties.getCompletedProperties());
		String tmUniqueName = configProperties.getTmUniqueName();
		
		long maxTimeout = configProperties.getMaxTimeout();
		int maxActives = configProperties.getMaxActives();
		
		OltpLog oltpLog = createOltpLogFromClasspath();
		if (oltpLog == null) {
			LOGGER.logInfo("Using default (local) logging and recovery..."); 
			Repository repository = createRepository(configProperties);		
			oltpLog = createOltpLog(repository);
			//??? Assemble recoveryLog
			recoveryLog = createRecoveryLog(repository);			
		} else {
		    //logcloud
		    if (oltpLog instanceof RecoveryLog) {
		        recoveryLog = (RecoveryLog) oltpLog;
		    }
		}
		StateRecoveryManagerImp	recoveryManager = new StateRecoveryManagerImp();
		recoveryManager.setOltpLog(oltpLog);
		UniqueIdMgr idMgr = new UniqueIdMgr ( tmUniqueName );
		int overflow = idMgr.getMaxIdLengthInBytes() - MAX_TID_LENGTH;
		if ( overflow > 0 ) {
			// see case 73086
			String msg = "Value too long : " + tmUniqueName;
			LOGGER.logFatal ( msg );
			throw new SysException(msg);
		}
		return new TransactionServiceImp(tmUniqueName, recoveryManager, idMgr, maxTimeout, maxActives, true, recoveryLog);
	}

	private Repository createRepository(ConfigProperties configProperties) {
		boolean enableLogging = configProperties.getEnableLogging();
		Repository repository;
		if (enableLogging) {
			try {
				repository = createCoordinatorLogEntryRepository(configProperties);
			} catch ( LogException le ) {
				throw new SysException ( "Error in init: " + le.getMessage (), le );
			}
		} else {
			repository = createInMemoryCoordinatorLogEntryRepository(configProperties);
		}
		return repository;
	}

	private OltpLog createOltpLogFromClasspath() {
		OltpLog ret = null;
		ServiceLoader loader = ServiceLoader.load(OltpLogFactory.class,Configuration.class.getClassLoader());
		int i = 0;
        for (OltpLogFactory l : loader ) {
			ret = l.createOltpLog();
			i++;
		}
        if (i > 1) {
			String msg = "More than one OltpLogFactory found in classpath - error in configuration!";
			LOGGER.logFatal(msg);
			throw new SysException(msg);
        }
        return ret;
	}

	private Repository createInMemoryCoordinatorLogEntryRepository(
			ConfigProperties configProperties) {
		InMemoryRepository inMemoryCoordinatorLogEntryRepository = new InMemoryRepository();
		inMemoryCoordinatorLogEntryRepository.init();
		return inMemoryCoordinatorLogEntryRepository;
	}

	private RecoveryLog createRecoveryLog(Repository repository) {
		RecoveryLogImp recoveryLog = new RecoveryLogImp();
		recoveryLog.setRepository(repository);
		return recoveryLog;
	}

	private OltpLog createOltpLog(Repository repository) {
		OltpLogImp oltpLog = new OltpLogImp();
		oltpLog.setRepository(repository);
		return oltpLog;
	}

	private CachedRepository createCoordinatorLogEntryRepository(
			ConfigProperties configProperties) throws LogException {
		InMemoryRepository inMemoryCoordinatorLogEntryRepository = new InMemoryRepository();
		inMemoryCoordinatorLogEntryRepository.init();
		FileSystemRepository backupCoordinatorLogEntryRepository = new FileSystemRepository();
		backupCoordinatorLogEntryRepository.init();
		CachedRepository repository = new CachedRepository(inMemoryCoordinatorLogEntryRepository, backupCoordinatorLogEntryRepository);
		repository.init();
		return repository;
	}


	@Override
	public CompositeTransactionManager assembleCompositeTransactionManager() {
		return new CompositeTransactionManagerImp();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy