/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package Sirius.server.localserver._class;
import Sirius.server.AbstractShutdownable;
import Sirius.server.ServerExitError;
import Sirius.server.Shutdown;
import Sirius.server.localserver.attribute.ClassAttribute;
import Sirius.server.localserver.attribute.MemberAttributeInfo;
import Sirius.server.newuser.UserGroup;
import Sirius.server.newuser.permission.Permission;
import Sirius.server.newuser.permission.PermissionHolder;
import Sirius.server.newuser.permission.Policy;
import Sirius.server.newuser.permission.PolicyHolder;
import Sirius.server.property.ServerProperties;
import Sirius.server.sql.DBConnection;
import Sirius.server.sql.DBConnectionPool;
import Sirius.server.sql.ExceptionHandler;
import Sirius.util.image.Image;
import Sirius.util.image.IntMapsImage;
import org.apache.log4j.Logger;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
public class ClassCache extends Shutdown {
//~ Static fields/initializers ---------------------------------------------
private static final transient Logger LOG = Logger.getLogger(ClassCache.class);
//~ Instance fields --------------------------------------------------------
/** contains all cached objects. */
protected ClassMap classes;
protected HashMap<String, Sirius.server.localserver._class.Class> classesByTableName;
protected HashMap classAttribs;
protected PolicyHolder policyHolder;
/**
* conatains this local servers class and object icons load with the method loadIcons which is called in the
* constructor.
*/
protected IntMapsImage icons = new IntMapsImage(20, 0.7f);
protected ServerProperties properties;
//~ Constructors -----------------------------------------------------------
/**
* -----------------------------------
*
* @param conPool DOCUMENT ME!
* @param properties DOCUMENT ME!
* @param policyHolder DOCUMENT ME!
*
* @throws Throwable DOCUMENT ME!
*/
public ClassCache(final DBConnectionPool conPool,
final ServerProperties properties,
final PolicyHolder policyHolder) throws Throwable {
this.properties = properties;
this.policyHolder = policyHolder;
loadIcons(conPool);
classes = new ClassMap(20); // allocation of the hashtable
classesByTableName = new HashMap<String, Sirius.server.localserver._class.Class>();
classAttribs = new HashMap(200);
final DBConnection con = conPool.getDBConnection();
try {
final ResultSet classTable = con.submitQuery("get_all_classes", new Object[0]); // getAllClasses //NOI18N
if (classTable == null) {
LOG.error(
"<LS> ERROR :: Fatal Error: classes could not be loaded. Program exits"); // NOI18N
throw new ServerExitError(
"Fatal Error: classes could not be loaded. Program exits"); // NOI18N
}
while (classTable.next()) // add all objects to the hashtable
{
Image object_i = null;
Image class_i = null;
try {
object_i = icons.getImageValue(classTable.getInt("object_icon_id")); // NOI18N
} catch (Exception e) {
LOG.error("<LS> ERROR :: !!Setting objectIcon to default!!", e); // NOI18N
object_i = new Image();
if (e instanceof java.sql.SQLException) {
throw e;
}
}
try {
class_i = icons.getImageValue(classTable.getInt("class_icon_id")); // NOI18N
} catch (Exception e) {
LOG.error("<LS> ERROR :: !!Setting classIcon to default!!!!", e); // NOI18N
class_i = new Image();
if (e instanceof java.sql.SQLException) {
throw e;
}
}
final String toStringQualifier = classTable.getString("tostringqualifier"); // NOI18N
final String className = classTable.getString("name").trim(); // NOI18N
final Object policyTester = classTable.getObject("policy"); // NOI18N
final boolean indexed = classTable.getBoolean("indexed");
Policy policy = null;
if (policyTester == null) {
policy = policyHolder.getServerPolicy(properties.getServerPolicy());
} else {
final int policyId = classTable.getInt("policy"); // NOI18N
policy = policyHolder.getServerPolicy(policyId);
}
final Object attrPolicyTester = classTable.getObject("attribute_policy"); // NOI18N
Policy attributePolicy = null;
if (attrPolicyTester == null) {
attributePolicy = policyHolder.getServerPolicy(properties.getAttributePolicy());
} else {
final int policyId = classTable.getInt("attribute_policy"); // NOI18N
attributePolicy = policyHolder.getServerPolicy(policyId);
}
if (attributePolicy == null) {
attributePolicy = policyHolder.getServerPolicy(properties.getServerPolicy());
}
final Class tmp = new Class(
classTable.getInt("id"), // NOI18N
className,
classTable.getString("descr"), // NOI18N
class_i,
object_i,
classTable.getString("table_name"), // NOI18N
classTable.getString("primary_key_field"), // NOI18N
toStringQualifier,
policy,
attributePolicy,
indexed);
if (LOG.isDebugEnabled()) {
LOG.debug("to string for Class :" + className + " :: " + toStringQualifier); // NOI18N
}
// Hell
tmp.setEditor(classTable.getString("editorqualifier")); // NOI18N
tmp.setRenderer(classTable.getString("RendererQualifier")); // NOI18N
try {
final boolean arrayElementLink = classTable.getBoolean("array_link"); // NOI18N
tmp.setArrayElementLink(arrayElementLink);
if (LOG.isDebugEnabled()) {
LOG.debug("isArrayElementLink set to :" + arrayElementLink); // NOI18N
}
} catch (Exception e) {
LOG.error("Error at arrayElementLink probably old DB version", e); // NOI18N
}
classes.add(tmp.getID(), tmp);
classesByTableName.put(tmp.getTableName().toLowerCase(), tmp);
}
classTable.close();
} catch (java.lang.Exception e) {
ExceptionHandler.handle(e);
}
addClassPermissions(conPool);
addAttributes(conPool);
addMemberInfos(conPool);
addShutdown(new AbstractShutdownable() {
@Override
protected void internalShutdown() throws ServerExitError {
if (LOG.isDebugEnabled()) {
LOG.debug("shutting down ClassCache"); // NOI18N
}
classes.clear();
classesByTableName.clear();
classAttribs.clear();
icons.clear();
}
});
}
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final int size() {
return classes.size();
}
/**
* DOCUMENT ME!
*
* @param id DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final Class getClass(final int id) {
return classes.getClass(id);
}
/**
* DOCUMENT ME!
*
* @param tableName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
public final Class getClassByTableName(final String tableName) throws Exception {
return classesByTableName.get(tableName);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final List getAllClasses() {
return classes.getAll();
}
/**
* DOCUMENT ME!
*
* @param ug DOCUMENT ME!
* @param id DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final Class getClass(final UserGroup ug, final int id) {
final Class c = classes.getClass(id);
if ((c != null) && c.getPermissions().hasPermission(ug.getKey(), PermissionHolder.READPERMISSION)) {
return c;
}
return null;
}
/**
* DOCUMENT ME!
*
* @param ug DOCUMENT ME!
* @param tableName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
public final Class getClassNyTableName(final UserGroup ug, final String tableName) throws Exception {
final Class c = getClassByTableName(tableName);
if ((c != null) && c.getPermissions().hasPermission(ug.getKey(), PermissionHolder.READPERMISSION)) {
return c;
}
return null;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public HashMap getClassHashMap() {
return classes;
}
/**
* DOCUMENT ME!
*
* @param ug DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final List getAllClasses(final UserGroup ug) {
final List all = getAllClasses();
final List cs = new ArrayList(all.size());
for (int i = 0; i < all.size(); i++) {
final Class c = (Class)all.get(i);
if (c.getPermissions().hasReadPermission(ug)) {
cs.add(c);
}
}
return cs;
}
/**
* Only to be called by the constructor.
*
* @param conPool DOCUMENT ME!
*/
private void addAttributes(final DBConnectionPool conPool) {
final DBConnection con = conPool.getDBConnection();
try {
final ResultSet attribTable = con.submitQuery("get_all_class_attributes", new Object[0]); // NOI18N
int id = 0;
int classID = 0;
int typeID = 0;
while (attribTable.next()) {
String name = null;
java.lang.Object value = null;
ClassAttribute attrib = null;
id = attribTable.getInt("id"); // NOI18N
classID = attribTable.getInt("class_id"); // NOI18N
name = attribTable.getString("attr_key"); // NOI18N
typeID = attribTable.getInt("type_id"); // NOI18N
value = attribTable.getString("attr_value"); // NOI18N
attrib = new ClassAttribute(id + "", classID, name, typeID, classes.getClass(classID).getPolicy()); // NOI18N
attrib.setValue(value);
classes.getClass(attrib.getClassID()).addAttribute(attrib);
classAttribs.put(new Integer(attrib.getID()), attrib);
}
attribTable.close();
} catch (final Exception e) {
ExceptionHandler.handle(e);
LOG.error("<LS> ERROR :: classcache get_all_class_attributes", e); // NOI18N
}
}
/**
* DOCUMENT ME!
*
* @param conPool DOCUMENT ME!
*/
private void addMemberInfos(final DBConnectionPool conPool) {
final DBConnection con = conPool.getDBConnection();
final HashMap<Integer, HashMap<String, String>> classfieldtypes =
new HashMap<Integer, HashMap<String, String>>();
final List<Sirius.server.localserver._class.Class> vc = getAllClasses();
try {
for (final Sirius.server.localserver._class.Class c : vc) {
HashMap<String, String> fieldtypes = classfieldtypes.get(c.getID());
if (fieldtypes == null) {
fieldtypes = new HashMap<String, String>();
classfieldtypes.put(c.getID(), fieldtypes);
}
final Statement s = con.getConnection().createStatement();
final String sql = c.getGetDefaultInstanceStmnt();
sql.replaceAll("\\?", "1=2"); // NOI18N
final ResultSet resultset = s.executeQuery(sql);
final ResultSetMetaData rsmd = resultset.getMetaData();
for (int i = 1; i <= rsmd.getColumnCount(); ++i) {
final String fieldname = rsmd.getColumnName(i);
final String javaclassname = rsmd.getColumnClassName(i);
fieldtypes.put(fieldname.toLowerCase(), javaclassname);
}
resultset.close();
s.close();
}
final ResultSet rs = con.submitQuery("get_attribute_info", new Object[0]); // NOI18N
MemberAttributeInfo mai = null;
// konstruktor paramters
int id;
int classId;
int typeId;
boolean foreignKey;
boolean substitute;
int foreignKeyClassId;
boolean visible = true;
// boolean permission;
boolean indexed = false;
boolean array = false;
boolean optional = false;
int position = 0;
while (rs.next()) {
final String name;
String fieldName;
String arrayKey;
String editor;
String toString; // toString
String defaultValue;
String fromString;
// String renderer;
// Hell
String complexEditor;
boolean extensionAttribute = false;
id = rs.getInt("id"); // NOI18N
name = rs.getString("name"); // NOI18N
classId = rs.getInt("class_id"); // NOI18N
typeId = rs.getInt("type_id"); // NOI18N
position = rs.getInt("pos"); // NOI18N
fieldName = rs.getString("field_name"); // NOI18N
if (fieldName != null) {
fieldName = fieldName.trim();
}
arrayKey = rs.getString("array_key"); // NOI18N
if (arrayKey != null) {
arrayKey = arrayKey.trim();
}
toString = rs.getString("toStringString"); // NOI18N
if (toString != null) {
toString = toString.trim();
}
editor = rs.getString("editor_class"); // NOI18N
if (editor != null) {
editor = editor.trim();
}
complexEditor = rs.getString("complexeditorclass"); // NOI18N
if (complexEditor != null) {
complexEditor = complexEditor.trim();
}
defaultValue = rs.getString("default_value"); // NOI18N
if (defaultValue != null) {
defaultValue = defaultValue.trim();
}
fromString = rs.getString("from_string_class"); // NOI18N
if (fromString != null) {
fromString = fromString.trim();
}
foreignKey = rs.getBoolean("foreign_key"); // NOI18N
substitute = rs.getBoolean("substitute"); // NOI18N
visible = rs.getBoolean("visible"); // NOI18N
optional = rs.getBoolean("optional"); // NOI18N
indexed = rs.getBoolean("indexed"); // NOI18N
foreignKeyClassId = rs.getInt("foreign_key_references_to"); // NOI18N
array = rs.getBoolean("isarray"); // NOI18N
try {
extensionAttribute = rs.getBoolean("extension_attr"); // NOI18N
} catch (Exception skip) {
}
// xxx array stuff to be added
mai = new MemberAttributeInfo(
id,
classId,
typeId,
name,
fieldName,
foreignKey,
substitute,
foreignKeyClassId,
visible,
indexed,
array,
arrayKey,
fromString,
toString,
position);
mai.setOptional(optional);
mai.setEditor(editor);
mai.setComplexEditor(complexEditor);
mai.setJavaclassname(classfieldtypes.get(classId).get(fieldName.toLowerCase()));
if ((mai.getJavaclassname() != null)
&& mai.getJavaclassname().equals(org.postgis.PGgeometry.class.getName())) {
mai.setJavaclassname(com.vividsolutions.jts.geom.Geometry.class.getName());
}
mai.setExtensionAttribute(extensionAttribute);
if (mai.isExtensionAttribute()) {
mai.setJavaclassname(java.lang.Object.class.getCanonicalName());
}
final Sirius.server.localserver._class.Class c = classes.getClass(classId);
if (c != null) {
c.addMemberAttributeInfo(mai);
} else {
LOG.warn("Wrong addMemberInfos entry for class::" + classId); // NOI18N
}
}
rs.close();
} catch (final Exception e) {
ExceptionHandler.handle(e);
LOG.error("<LS> ERROR :: addMemberinfos", e); // NOI18N
}
}
/**
* DOCUMENT ME!
*
* @param conPool DOCUMENT ME!
*/
protected final void loadIcons(final DBConnectionPool conPool) {
String iconDirectory;
String separator;
Image tmpImage;
try {
iconDirectory = properties.getIconDirectory();
} catch (Exception e) {
LOG.error(
"<LS> ERROR :: Keyvalue ICONDIRECTORY in ConfigFile is missing\n<LS> ERROR :: set ICONDIRECTORY to . ", // NOI18N
e);
iconDirectory = "."; // NOI18N
}
try {
separator = System.getProperty("file.separator"); // NOI18N
} catch (Exception e) {
LOG.error(
"<LS> ERROR :: KeyValue SEPARATOR in ConfigFile is missing\n<LS> ERROR :: set DEFAULTSEPARATOR = \\", // NOI18N
e);
separator = "\\"; // NOI18N
}
final DBConnection con = conPool.getDBConnection();
try {
final ResultSet imgTable = con.submitQuery("get_all_images", new Object[0]); // NOI18N
while (imgTable.next()) {
tmpImage = new Image(iconDirectory + separator + imgTable.getString("file_name").trim()); // NOI18N
icons.add(imgTable.getInt("id"), tmpImage); // NOI18N
}
imgTable.close();
} catch (final Exception e) {
ExceptionHandler.handle(e);
LOG.error("<LS> ERROR :: get_all_icons", e); // NOI18N
}
}
/**
* DOCUMENT ME!
*
* @param conPool DOCUMENT ME!
*/
private void addClassPermissions(final DBConnectionPool conPool) {
final DBConnection con = conPool.getDBConnection();
try {
final ResultSet permTable = con.submitQuery("get_all_class_permissions", new Object[0]); // NOI18N
final String lsName = properties.getServerName();
while (permTable.next()) {
final int ug_id = permTable.getInt("ug_id"); // NOI18N
final String ug_name = permTable.getString("ug_name"); // NOI18N
String lsHome = permTable.getString("domainname").trim(); // NOI18N
final int permId = permTable.getInt("permission"); // NOI18N
final String permKey = permTable.getString("key");
if (lsHome.equalsIgnoreCase("local")) { // NOI18N
lsHome = String.valueOf(lsName);
}
if (LOG.isDebugEnabled()) {
LOG.debug("==permId set ======! " + permId); // NOI18N
}
final Class clazz = classes.getClass(permTable.getInt("class_id")); // NOI18N
if (clazz == null) {
LOG.warn("illegal class_id in cs_ug_class_perm: " + permTable.getInt("class_id")); // NOI18N
} else {
final UserGroup ug = new UserGroup(ug_id, ug_name, lsHome);
final Permission perm = new Permission(permId, permKey);
clazz.getPermissions().addPermission(ug, perm);
}
}
permTable.close();
} catch (final Exception e) {
ExceptionHandler.handle(e);
LOG.error("<LS> ERROR :: addClassPermissions", e); // NOI18N
}
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public ServerProperties getProperties() {
return properties;
}
}