Java tutorial
/* Copyright (C) 2011 Alasdair Mercer, http://neocotic.com/ * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.neocotic.blingaer.common.dao; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import com.neocotic.blingaer.common.Locator; import com.neocotic.blingaer.common.exception.BlingaerRuntimeException; /** * Singleton {@code class} which provides clients with the functionality to * lookup {@link DAO} implementations. * <p> * Clients need to retrieve an instance of this {@code class} and invoke * {@link #getDAO(Class)} to get the desired {@code DAO} implementation. * * @author Alasdair Mercer */ // TODO: Confirm that caching DAO lookups has a negative impact on objectify public class DAOLocator extends Locator { /** The {@code Logger} instance for {@link DAOLocator}. */ private static final Logger LOG = Logger.getLogger(DAOLocator.class); /** The name of the property declaring the datastore to be used. */ protected static final String DATA_STORE_PROPERTY = "com.neocotic.blingaer.datastore"; /** The suffix appended to {@link DAO} implementations. */ protected static final String IMPL_CLASS_SUFFIX = "Impl"; /** The singleton instance of {@link DAOLocator}. */ private static DAOLocator instance; /** * Returns a singleton instance of {@link DAOLocator}. * * @return the {@code DAOLocator} instance * @throws BlingaerRuntimeException * If datastore property could not be found. */ public static DAOLocator getInstance() throws BlingaerRuntimeException { if (instance == null) { instance = new DAOLocator(); } return instance; } private String dataStore; /** * Prevents external invocation to support singleton pattern. * * @throws BlingaerRuntimeException * If datastore property could not be found. */ DAOLocator() throws BlingaerRuntimeException { dataStore = StringUtils.trimToNull(System.getProperty(DATA_STORE_PROPERTY)); if (dataStore == null) { throw new BlingaerRuntimeException("Could not locate datastore property: " + DATA_STORE_PROPERTY); } } /** * Retrieves the POJO implementation of the {@link DAO} {@code class} * provided. * <p> * Reflection is used to lookup the POJO implementation and delegate calls * to it. * * @param cls * the {@code DAO class} whose POJO implementation is to be * located * @return the POJO implementation of the specified {@code class} * @throws BlingaerRuntimeException * If an error occurs while loading/instantiating the new * {@code Service class}. */ @SuppressWarnings("unchecked") public <T extends DAO> T getDAO(Class<T> cls) throws BlingaerRuntimeException { LOG.trace("Entered method - getDAO"); String className = cls.getName() + IMPL_CLASS_SUFFIX; // Injects datastore package name in to String[] arr = StringUtils.split(className, ClassUtils.PACKAGE_SEPARATOR_CHAR); arr = ArrayUtils.add(arr, arr.length - 1, dataStore); className = StringUtils.join(arr, ClassUtils.PACKAGE_SEPARATOR_CHAR); DAO impl = newDAOImpl(className); /* * Currently not caching these results as I'm not sure if it will have a * negative affect on objectify */ LOG.trace("Exiting method - getDAO"); return (T) impl; } /** * Creates a new instance of the {@link DAO} implementation {@code class}. * * @param className * the name of the {@code class} to be loaded and instantiated * @return an instance of the specified {@code class} * @throws BlingaerRuntimeException * If an error occurs while loading/instantiating the new * {@code Service class}. */ private DAO newDAOImpl(String className) throws BlingaerRuntimeException { LOG.trace("Entered method - newDAO"); DAO dao = null; try { dao = (DAO) getDefaultClassLoader().loadClass(className).newInstance(); } catch (Exception e) { LOG.error("Throwing exception", e); throw new BlingaerRuntimeException(e); } LOG.trace("Exiting method - newDAO"); return dao; } }