/* * * * Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com) * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * * For more information: http://www.orientechnologies.com * */ package com.orientechnologies.orient.core.entity; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.orientechnologies.common.exception.OException; import com.orientechnologies.common.log.OLogManager; import com.orientechnologies.common.reflection.OReflectionHelper; import com.orientechnologies.orient.core.exception.OConfigurationException; import com.orientechnologies.orient.core.exception.ODatabaseException; import com.orientechnologies.orient.core.metadata.security.ORole; import com.orientechnologies.orient.core.metadata.security.OUser; public class OEntityManager { private static Map<String, OEntityManager> databaseInstances = new HashMap<String, OEntityManager>(); private OEntityManagerClassHandler classHandler = new OEntityManagerClassHandler(); protected OEntityManager() { OLogManager.instance().debug(this, "Registering entity manager"); classHandler.registerEntityClass(OUser.class); classHandler.registerEntityClass(ORole.class); } public static synchronized OEntityManager getEntityManagerByDatabaseURL(final String iURL) { OEntityManager instance = databaseInstances.get(iURL); if (instance == null) { instance = new OEntityManager(); databaseInstances.put(iURL, instance); } return instance; } /** * Create a POJO by its class name. * * @see #registerEntityClasses(String) */ public synchronized Object createPojo(final String iClassName) throws OConfigurationException { if (iClassName == null) throw new IllegalArgumentException("Cannot create the object: class name is empty"); final Class<?> entityClass = classHandler.getEntityClass(iClassName); try { if (entityClass != null) return createInstance(entityClass); } catch (Exception e) { throw OException.wrapException(new OConfigurationException("Error while creating new pojo of class '" + iClassName + "'"), e); } try { // TRY TO INSTANTIATE THE CLASS DIRECTLY BY ITS NAME return createInstance(Class.forName(iClassName)); } catch (Exception e) { throw OException.wrapException(new OConfigurationException("The class '" + iClassName + "' was not found between the entity classes. Ensure registerEntityClasses(package) has been called first"), e); } } /** * Returns the Java class by its name * * @param iClassName * Simple class name without the package * @return Returns the Java class by its name */ public synchronized Class<?> getEntityClass(final String iClassName) { return classHandler.getEntityClass(iClassName); } public synchronized void deregisterEntityClass(final Class<?> iClass) { classHandler.deregisterEntityClass(iClass); } public synchronized void deregisterEntityClasses(final String iPackageName) { deregisterEntityClasses(iPackageName, Thread.currentThread().getContextClassLoader()); } /** * Scans all classes accessible from the context class loader which belong to the given package and subpackages. * * @param iPackageName * The base package */ public synchronized void deregisterEntityClasses(final String iPackageName, final ClassLoader iClassLoader) { OLogManager.instance().debug(this, "Discovering entity classes inside package: %s", iPackageName); List<Class<?>> classes = null; try { classes = OReflectionHelper.getClassesFor(iPackageName, iClassLoader); } catch (ClassNotFoundException e) { throw OException.wrapException(new ODatabaseException("Class cannot be found in package " + iPackageName), e); } for (Class<?> c : classes) { deregisterEntityClass(c); } if (OLogManager.instance().isDebugEnabled()) { for (Entry<String, Class<?>> entry : classHandler.getClassesEntrySet()) { OLogManager.instance().debug(this, "Unloaded entity class '%s' from: %s", entry.getKey(), entry.getValue()); } } } public synchronized void registerEntityClass(final Class<?> iClass) { registerEntityClass(iClass, true); } public synchronized void registerEntityClass(final Class<?> iClass, boolean forceSchemaReload) { classHandler.registerEntityClass(iClass, forceSchemaReload); } /** * Registers provided classes * * @param iClassNames * to be registered */ public synchronized void registerEntityClasses(final Collection<String> iClassNames) { registerEntityClasses(iClassNames, Thread.currentThread().getContextClassLoader()); } /** * Registers provided classes * * @param iClassNames * to be registered * @param iClassLoader */ public synchronized void registerEntityClasses(final Collection<String> iClassNames, final ClassLoader iClassLoader) { OLogManager.instance().debug(this, "Discovering entity classes for class names: %s", iClassNames); try { registerEntityClasses(OReflectionHelper.getClassesFor(iClassNames, iClassLoader)); } catch (ClassNotFoundException e) { throw OException.wrapException(new ODatabaseException("Entity class cannot be found"), e); } } /** * Scans all classes accessible from the context class loader which belong to the given package and subpackages. * * @param iPackageName * The base package */ public synchronized void registerEntityClasses(final String iPackageName) { registerEntityClasses(iPackageName, Thread.currentThread().getContextClassLoader()); } /** * Scans all classes accessible from the context class loader which belong to the given package and subpackages. * * @param iPackageName * The base package * @param iClassLoader */ public synchronized void registerEntityClasses(final String iPackageName, final ClassLoader iClassLoader) { OLogManager.instance().debug(this, "Discovering entity classes inside package: %s", iPackageName); try { registerEntityClasses(OReflectionHelper.getClassesFor(iPackageName, iClassLoader)); } catch (ClassNotFoundException e) { throw OException.wrapException(new ODatabaseException("Entity class cannot be found"), e); } } protected synchronized void registerEntityClasses(final List<Class<?>> classes) { for (Class<?> c : classes) { if (!classHandler.containsEntityClass(c)) { if (c.isAnonymousClass()) { OLogManager.instance().debug(this, "Skip registration of anonymous class '%s'", c.getName()); continue; } classHandler.registerEntityClass(c); } } if (OLogManager.instance().isDebugEnabled()) { for (Entry<String, Class<?>> entry : classHandler.getClassesEntrySet()) { OLogManager.instance().debug(this, "Loaded entity class '%s' from: %s", entry.getKey(), entry.getValue()); } } } /** * Scans all classes accessible from the context class loader which belong to the given class and all it's attributes - classes. * * @param aClass * The class to start from * @param recursive * Beginning from the class, it will register all classes that are direct or indirect a attribute class * */ public synchronized void registerEntityClasses(Class<?> aClass, boolean recursive) { if (recursive) { classHandler.registerEntityClass(aClass); Field[] declaredFields = aClass.getDeclaredFields(); for (Field declaredField : declaredFields) { Class<?> declaredFieldType = declaredField.getType(); if (!classHandler.containsEntityClass(declaredFieldType)) { registerEntityClasses(declaredFieldType, recursive); } } } else { classHandler.registerEntityClass(aClass); } } /** * Sets the received handler as default and merges the classes all together. * * @param iClassHandler */ public synchronized void setClassHandler(final OEntityManagerClassHandler iClassHandler) { Iterator<Entry<String, Class<?>>> iterator = classHandler.getClassesEntrySet().iterator(); while (iterator.hasNext()){ Entry<String, Class<?>> entry = iterator.next(); boolean forceSchemaReload = !iterator.hasNext(); iClassHandler.registerEntityClass(entry.getValue(), forceSchemaReload); } this.classHandler = iClassHandler; } public synchronized Collection<Class<?>> getRegisteredEntities() { return classHandler.getRegisteredEntities(); } protected Object createInstance(final Class<?> iClass) throws InstantiationException, IllegalAccessException, InvocationTargetException { return classHandler.createInstance(iClass); } }