Merged in changes from helma_1_2 branch
This commit is contained in:
parent
9d73c836ed
commit
ed15173b8c
32 changed files with 1056 additions and 632 deletions
|
@ -8,7 +8,7 @@
|
||||||
<target name="init">
|
<target name="init">
|
||||||
<property name="Name" value="helma"/>
|
<property name="Name" value="helma"/>
|
||||||
<property name="year" value="1998-${year}"/>
|
<property name="year" value="1998-${year}"/>
|
||||||
<property name="version" value="1.2-rc2"/>
|
<property name="version" value="1.2.2"/>
|
||||||
<property name="project" value="helma"/>
|
<property name="project" value="helma"/>
|
||||||
<property name="build.compiler" value="classic"/>
|
<property name="build.compiler" value="classic"/>
|
||||||
|
|
||||||
|
|
BIN
lib/village.jar
BIN
lib/village.jar
Binary file not shown.
|
@ -432,11 +432,7 @@ public abstract class ESLoader extends ESObject {
|
||||||
debugInfo = " rejected (not widening numbers)";
|
debugInfo = " rejected (not widening numbers)";
|
||||||
}
|
}
|
||||||
// Handle String of length 1 as a Char, which can be converted to a number
|
// Handle String of length 1 as a Char, which can be converted to a number
|
||||||
} else if ((targetClass == Character.class ||
|
} else if (targetClass == Character.class
|
||||||
targetClass == Integer.class ||
|
|
||||||
targetClass == Long.class ||
|
|
||||||
targetClass == Float.class ||
|
|
||||||
targetClass == Double.class)
|
|
||||||
&& params[i] instanceof String) {
|
&& params[i] instanceof String) {
|
||||||
if (((String) params[i]).length()==1) {
|
if (((String) params[i]).length()==1) {
|
||||||
accepted = true; // will require conversion of parameter
|
accepted = true; // will require conversion of parameter
|
||||||
|
|
|
@ -74,11 +74,11 @@ public class ClassInfo {
|
||||||
* @return the ClassInfo of cls, added to the cache if needed
|
* @return the ClassInfo of cls, added to the cache if needed
|
||||||
*/
|
*/
|
||||||
private static ClassInfo ensureClassInfo(Class cls) {
|
private static ClassInfo ensureClassInfo(Class cls) {
|
||||||
boolean debug = ESLoader.isDebugJavaAccess();
|
// boolean debug = ESLoader.isDebugJavaAccess();
|
||||||
ClassInfo classInfo = (ClassInfo) allClassInfo.get(cls);
|
ClassInfo classInfo = (ClassInfo) allClassInfo.get(cls);
|
||||||
if (classInfo == null) {
|
if (classInfo == null) {
|
||||||
if (debug) System.out.println("** Class info for class '" +
|
// if (debug) System.out.println("** Class info for class '" +
|
||||||
cls + "' not found in cache, created");
|
// cls + "' not found in cache, created");
|
||||||
classInfo = new ClassInfo();
|
classInfo = new ClassInfo();
|
||||||
allClassInfo.put(cls, classInfo);
|
allClassInfo.put(cls, classInfo);
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ public class ClassInfo {
|
||||||
* @param cls The class for which we look for the property.
|
* @param cls The class for which we look for the property.
|
||||||
* @return The PropertyDescriptor or null if not found or in case of error
|
* @return The PropertyDescriptor or null if not found or in case of error
|
||||||
*/
|
*/
|
||||||
synchronized public static PropertyDescriptor lookupBeanField(String fieldName, Class cls) {
|
public static PropertyDescriptor lookupBeanField(String fieldName, Class cls) {
|
||||||
ClassInfo classInfo = ClassInfo.ensureClassInfo(cls);
|
ClassInfo classInfo = ClassInfo.ensureClassInfo(cls);
|
||||||
return classInfo.cachedBeanFieldLookup(fieldName, cls);
|
return classInfo.cachedBeanFieldLookup(fieldName, cls);
|
||||||
}
|
}
|
||||||
|
@ -110,29 +110,29 @@ public class ClassInfo {
|
||||||
* @return The PropertyDescriptor or null if not found or in case of error
|
* @return The PropertyDescriptor or null if not found or in case of error
|
||||||
*/
|
*/
|
||||||
private PropertyDescriptor cachedBeanFieldLookup(String propertyName, Class cls) {
|
private PropertyDescriptor cachedBeanFieldLookup(String propertyName, Class cls) {
|
||||||
boolean debug = ESLoader.isDebugJavaAccess();
|
// boolean debug = ESLoader.isDebugJavaAccess();
|
||||||
|
|
||||||
// Check that there is a bean properties cache, chech if the property was cached
|
// Check that there is a bean properties cache, chech if the property was cached
|
||||||
if (beanProperties != null) {
|
if (beanProperties != null) {
|
||||||
if (debug) System.out.println("** Bean properties for class '" +
|
// if (debug) System.out.println("** Bean properties for class '" +
|
||||||
cls + "' found in cache");
|
// cls + "' found in cache");
|
||||||
PropertyDescriptor descriptor =
|
PropertyDescriptor descriptor =
|
||||||
(PropertyDescriptor) beanProperties.get(propertyName);
|
(PropertyDescriptor) beanProperties.get(propertyName);
|
||||||
if (descriptor!= null) {
|
if (descriptor!= null) {
|
||||||
if (debug) System.out.println("** property descriptor '" + propertyName + "' found in cache");
|
// if (debug) System.out.println("** property descriptor '" + propertyName + "' found in cache");
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Not in cache
|
// Not in cache
|
||||||
if (debug) System.out.println("** No property named '" +
|
// if (debug) System.out.println("** No property named '" +
|
||||||
propertyName + "' found in cache, lookup started");
|
// propertyName + "' found in cache, lookup started");
|
||||||
|
|
||||||
// Do we have a cached BeanInfo ? create it if no
|
// Do we have a cached BeanInfo ? create it if no
|
||||||
if (beanInfo == null) {
|
if (beanInfo == null) {
|
||||||
try {
|
try {
|
||||||
beanInfo = Introspector.getBeanInfo(cls);
|
beanInfo = Introspector.getBeanInfo(cls);
|
||||||
} catch (IntrospectionException e) {
|
} catch (IntrospectionException e) {
|
||||||
if (debug) System.out.println(" ** Error getting beaninfo: " + e);
|
// if (debug) System.out.println(" ** Error getting beaninfo: " + e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ public class ClassInfo {
|
||||||
PropertyDescriptor descriptor = null; // none found
|
PropertyDescriptor descriptor = null; // none found
|
||||||
for (int i=0; i<allProperties.length; i++) {
|
for (int i=0; i<allProperties.length; i++) {
|
||||||
PropertyDescriptor property = allProperties[i];
|
PropertyDescriptor property = allProperties[i];
|
||||||
if (debug) System.out.println("** Property examined: " + property.getName());
|
// if (debug) System.out.println("** Property examined: " + property.getName());
|
||||||
if (!property.getName().equals(propertyName)) continue;
|
if (!property.getName().equals(propertyName)) continue;
|
||||||
descriptor = property;
|
descriptor = property;
|
||||||
break;
|
break;
|
||||||
|
@ -238,13 +238,13 @@ public class ClassInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to cache
|
// Add to cache
|
||||||
if (debug) System.out.println("** property '" + propertyName + "' + found, add to cache");
|
// if (debug) System.out.println("** property '" + propertyName + "' + found, add to cache");
|
||||||
if (beanProperties==null) {
|
if (beanProperties==null) {
|
||||||
beanProperties = new Hashtable();
|
beanProperties = new Hashtable();
|
||||||
}
|
}
|
||||||
beanProperties.put(propertyName, descriptor);
|
beanProperties.put(propertyName, descriptor);
|
||||||
} else {
|
} else {
|
||||||
if (debug) System.out.println("** No method named '" + propertyName + "' found");
|
// if (debug) System.out.println("** No method named '" + propertyName + "' found");
|
||||||
}
|
}
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ public class ClassInfo {
|
||||||
* @param cls The class of the method being looked up
|
* @param cls The class of the method being looked up
|
||||||
* @return The method array or null if none found or in case of error
|
* @return The method array or null if none found or in case of error
|
||||||
*/
|
*/
|
||||||
synchronized public static Method[] lookupPublicMethod(String functionName, Class cls) throws EcmaScriptException {
|
public static Method[] lookupPublicMethod(String functionName, Class cls) throws EcmaScriptException {
|
||||||
ClassInfo classInfo = ClassInfo.ensureClassInfo(cls);
|
ClassInfo classInfo = ClassInfo.ensureClassInfo(cls);
|
||||||
return classInfo.cachedPublicMethodLookup(functionName, cls);
|
return classInfo.cachedPublicMethodLookup(functionName, cls);
|
||||||
}
|
}
|
||||||
|
@ -274,52 +274,52 @@ public class ClassInfo {
|
||||||
* @return The method if found, null otherwise
|
* @return The method if found, null otherwise
|
||||||
*/
|
*/
|
||||||
private Method getInInterfaces(String functionName, Class [] interfaces, Class[] paramTypes) {
|
private Method getInInterfaces(String functionName, Class [] interfaces, Class[] paramTypes) {
|
||||||
boolean debug = ESLoader.isDebugJavaAccess();
|
// boolean debug = ESLoader.isDebugJavaAccess();
|
||||||
|
|
||||||
if (debug && interfaces.length>0) {
|
// if (debug && interfaces.length>0) {
|
||||||
System.out.println("** Looking in " + interfaces.length + " interfaces");
|
// System.out.println("** Looking in " + interfaces.length + " interfaces");
|
||||||
}
|
// }
|
||||||
SEARCHININTERFACE:
|
SEARCHININTERFACE:
|
||||||
for (int ix=0; ix<interfaces.length; ix++) {
|
for (int ix=0; ix<interfaces.length; ix++) {
|
||||||
Class theInterface=interfaces[ix];
|
Class theInterface=interfaces[ix];
|
||||||
if (Modifier.isPublic(theInterface.getModifiers())) {
|
if (Modifier.isPublic(theInterface.getModifiers())) {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** Looking in public interface: " + theInterface);
|
// System.out.println("** Looking in public interface: " + theInterface);
|
||||||
}
|
// }
|
||||||
try {
|
try {
|
||||||
Method method = theInterface.getDeclaredMethod(functionName,paramTypes);
|
Method method = theInterface.getDeclaredMethod(functionName,paramTypes);
|
||||||
if (Modifier.isPublic(method.getModifiers())) {
|
if (Modifier.isPublic(method.getModifiers())) {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** Public method found: " + functionName);
|
// System.out.println("** Public method found: " + functionName);
|
||||||
}
|
// }
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** The method has no public declaration in the interface: "+ functionName);
|
// System.out.println("** The method has no public declaration in the interface: "+ functionName);
|
||||||
}
|
// }
|
||||||
// throw new ProgrammingError("The method has no public declaration in a public class: "+ functionName);
|
// throw new ProgrammingError("The method has no public declaration in a public class: "+ functionName);
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
throw new ProgrammingError("Access error inspecting method "+ functionName + ": " + e);
|
throw new ProgrammingError("Access error inspecting method "+ functionName + ": " + e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** Interface " + theInterface + " is not public - not searching for method");
|
// System.out.println("** Interface " + theInterface + " is not public - not searching for method");
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not found, try super interfaces
|
// Not found, try super interfaces
|
||||||
Class [] superInterfaces = theInterface.getInterfaces();
|
Class [] superInterfaces = theInterface.getInterfaces();
|
||||||
Method method = getInInterfaces(functionName, superInterfaces, paramTypes);
|
Method method = getInInterfaces(functionName, superInterfaces, paramTypes);
|
||||||
if (method!=null) {
|
if (method!=null) {
|
||||||
if (debug) System.out.println("** Method found in super interfaces");
|
// if (debug) System.out.println("** Method found in super interfaces");
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** No method found in interface and super interfaces");
|
// System.out.println("** No method found in interface and super interfaces");
|
||||||
}
|
// }
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,26 +337,26 @@ public class ClassInfo {
|
||||||
* @return The list of methods or null in case of error or if none found.
|
* @return The list of methods or null in case of error or if none found.
|
||||||
*/
|
*/
|
||||||
private Method [] cachedPublicMethodLookup(String functionName, Class cls) throws EcmaScriptException {
|
private Method [] cachedPublicMethodLookup(String functionName, Class cls) throws EcmaScriptException {
|
||||||
boolean debug = ESLoader.isDebugJavaAccess();
|
// boolean debug = ESLoader.isDebugJavaAccess();
|
||||||
if (publicMethods != null) {
|
if (publicMethods != null) {
|
||||||
if (debug) System.out.println("** Method descriptor for class '" +
|
// if (debug) System.out.println("** Method descriptor for class '" +
|
||||||
cls + "' found in cache");
|
// cls + "' found in cache");
|
||||||
Method [] methods = (Method []) publicMethods.get(functionName);
|
Method [] methods = (Method []) publicMethods.get(functionName);
|
||||||
if (methods!= null) {
|
if (methods!= null) {
|
||||||
if (debug) System.out.println("** " + methods.length +
|
// if (debug) System.out.println("** " + methods.length +
|
||||||
" method(s) named '" + functionName + "' found in cache");
|
// " method(s) named '" + functionName + "' found in cache");
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Not in cache, find if any matching the same name can be found
|
// Not in cache, find if any matching the same name can be found
|
||||||
if (debug) System.out.println("** No method named '" +
|
// if (debug) System.out.println("** No method named '" +
|
||||||
functionName + "' found in class cache, lookup started");
|
// functionName + "' found in class cache, lookup started");
|
||||||
Method [] allMethods = cls.getMethods();
|
Method [] allMethods = cls.getMethods();
|
||||||
Vector methodVector = new Vector(allMethods.length);
|
Vector methodVector = new Vector(allMethods.length);
|
||||||
boolean wasFound = false;
|
boolean wasFound = false;
|
||||||
for (int i=0; i<allMethods.length; i++) {
|
for (int i=0; i<allMethods.length; i++) {
|
||||||
Method method = allMethods[i];
|
Method method = allMethods[i];
|
||||||
if (debug) System.out.println("** Method examined: " + method.toString());
|
// if (debug) System.out.println("** Method examined: " + method.toString());
|
||||||
if (!method.getName().equals(functionName)) continue;
|
if (!method.getName().equals(functionName)) continue;
|
||||||
// Method has same name, some closer examination is needed:
|
// Method has same name, some closer examination is needed:
|
||||||
// If the class itself is not public, there is an access error if
|
// If the class itself is not public, there is an access error if
|
||||||
|
@ -365,8 +365,8 @@ public class ClassInfo {
|
||||||
// I am not too sure of what happens if the method is defined in an
|
// I am not too sure of what happens if the method is defined in an
|
||||||
// interface...
|
// interface...
|
||||||
if (!Modifier.isStatic(cls.getModifiers()) && !Modifier.isPublic(cls.getModifiers())) {
|
if (!Modifier.isStatic(cls.getModifiers()) && !Modifier.isPublic(cls.getModifiers())) {
|
||||||
if (debug) System.out.println("** Class " + cls +
|
// if (debug) System.out.println("** Class " + cls +
|
||||||
" is not public, examining superclasses and interfaces to find proper method descriptor");
|
// " is not public, examining superclasses and interfaces to find proper method descriptor");
|
||||||
|
|
||||||
Class[] paramTypes = method.getParameterTypes();
|
Class[] paramTypes = method.getParameterTypes();
|
||||||
SEARCHPUBLIC:
|
SEARCHPUBLIC:
|
||||||
|
@ -383,31 +383,31 @@ public class ClassInfo {
|
||||||
|
|
||||||
// Look in the class
|
// Look in the class
|
||||||
if (Modifier.isPublic(theClass.getModifiers())) {
|
if (Modifier.isPublic(theClass.getModifiers())) {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** Looking in public class: " + theClass);
|
// System.out.println("** Looking in public class: " + theClass);
|
||||||
}
|
// }
|
||||||
try {
|
try {
|
||||||
m = theClass.getDeclaredMethod(functionName,paramTypes);
|
m = theClass.getDeclaredMethod(functionName,paramTypes);
|
||||||
if (Modifier.isPublic(method.getModifiers())) {
|
if (Modifier.isPublic(method.getModifiers())) {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** Public method found: " + functionName);
|
// System.out.println("** Public method found: " + functionName);
|
||||||
}
|
// }
|
||||||
method = m;
|
method = m;
|
||||||
wasFound = true;
|
wasFound = true;
|
||||||
break SEARCHPUBLIC;
|
break SEARCHPUBLIC;
|
||||||
}
|
}
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** The method has no public declaration in the public class: "+ functionName);
|
// System.out.println("** The method has no public declaration in the public class: "+ functionName);
|
||||||
}
|
// }
|
||||||
// throw new ProgrammingError("The method has no public declaration in a public class: "+ functionName);
|
// throw new ProgrammingError("The method has no public declaration in a public class: "+ functionName);
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
throw new ProgrammingError("Access error inspecting method "+ functionName + ": " + e);
|
throw new ProgrammingError("Access error inspecting method "+ functionName + ": " + e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** Class " + theClass + " is not public - not searching for method");
|
// System.out.println("** Class " + theClass + " is not public - not searching for method");
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
} // for SEARCHPUBLIC
|
} // for SEARCHPUBLIC
|
||||||
|
@ -427,7 +427,7 @@ public class ClassInfo {
|
||||||
Method [] methods = null;
|
Method [] methods = null;
|
||||||
int nmbMethods = methodVector.size();
|
int nmbMethods = methodVector.size();
|
||||||
if (nmbMethods>0) {
|
if (nmbMethods>0) {
|
||||||
if (debug) System.out.println("** " + nmbMethods + " methods named: '" + functionName + "' + found, add to class cache");
|
// if (debug) System.out.println("** " + nmbMethods + " methods named: '" + functionName + "' + found, add to class cache");
|
||||||
methods = new Method[nmbMethods];
|
methods = new Method[nmbMethods];
|
||||||
methodVector.copyInto(methods);
|
methodVector.copyInto(methods);
|
||||||
if (publicMethods==null) {
|
if (publicMethods==null) {
|
||||||
|
@ -435,7 +435,7 @@ public class ClassInfo {
|
||||||
}
|
}
|
||||||
publicMethods.put(functionName, methods);
|
publicMethods.put(functionName, methods);
|
||||||
} else {
|
} else {
|
||||||
if (debug) System.out.println("** No method named '" + functionName + "' found");
|
// if (debug) System.out.println("** No method named '" + functionName + "' found");
|
||||||
}
|
}
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ public class ClassInfo {
|
||||||
* @param cls The class of the method being looked up
|
* @param cls The class of the method being looked up
|
||||||
* @return The method array or null if none found or in case of error
|
* @return The method array or null if none found or in case of error
|
||||||
*/
|
*/
|
||||||
synchronized public static Method[] lookupBeanMethod(String functionName, Class cls) {
|
public static Method[] lookupBeanMethod(String functionName, Class cls) {
|
||||||
ClassInfo classInfo = ClassInfo.ensureClassInfo(cls);
|
ClassInfo classInfo = ClassInfo.ensureClassInfo(cls);
|
||||||
return classInfo.cachedBeanMethodLookup(functionName, cls);
|
return classInfo.cachedBeanMethodLookup(functionName, cls);
|
||||||
}
|
}
|
||||||
|
@ -469,27 +469,27 @@ public class ClassInfo {
|
||||||
* @return The list of methods or null in case of error or if none found.
|
* @return The list of methods or null in case of error or if none found.
|
||||||
*/
|
*/
|
||||||
private Method [] cachedBeanMethodLookup(String functionName, Class cls) {
|
private Method [] cachedBeanMethodLookup(String functionName, Class cls) {
|
||||||
boolean debug = ESLoader.isDebugJavaAccess();
|
// boolean debug = ESLoader.isDebugJavaAccess();
|
||||||
if (beanMethods != null) {
|
if (beanMethods != null) {
|
||||||
if (debug) System.out.println("** Method descriptor for bean '" +
|
// if (debug) System.out.println("** Method descriptor for bean '" +
|
||||||
cls + "' found in cache");
|
// cls + "' found in cache");
|
||||||
Method [] methods = (Method []) beanMethods.get(functionName);
|
Method [] methods = (Method []) beanMethods.get(functionName);
|
||||||
if (methods!= null) {
|
if (methods!= null) {
|
||||||
if (debug) System.out.println("** " + methods.length +
|
// if (debug) System.out.println("** " + methods.length +
|
||||||
" method(s) named '" + functionName + "' found in cache");
|
// " method(s) named '" + functionName + "' found in cache");
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Not in cache, find if any matching the same name can be found
|
// Not in cache, find if any matching the same name can be found
|
||||||
if (debug) System.out.println("** No method named '" +
|
// if (debug) System.out.println("** No method named '" +
|
||||||
functionName + "' found in bean cache, lookup started");
|
// functionName + "' found in bean cache, lookup started");
|
||||||
|
|
||||||
// Do we have a cached BeanInfo ? create it if no
|
// Do we have a cached BeanInfo ? create it if no
|
||||||
if (beanInfo == null) {
|
if (beanInfo == null) {
|
||||||
try {
|
try {
|
||||||
beanInfo = Introspector.getBeanInfo(cls);
|
beanInfo = Introspector.getBeanInfo(cls);
|
||||||
} catch (IntrospectionException e) {
|
} catch (IntrospectionException e) {
|
||||||
if (debug) System.out.println(" ** Error getting beaninfo: " + e);
|
// if (debug) System.out.println(" ** Error getting beaninfo: " + e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,7 +498,7 @@ public class ClassInfo {
|
||||||
Vector methodVector = new Vector(allDescriptors.length);
|
Vector methodVector = new Vector(allDescriptors.length);
|
||||||
for (int i=0; i<allDescriptors.length; i++) {
|
for (int i=0; i<allDescriptors.length; i++) {
|
||||||
Method method = allDescriptors[i].getMethod();
|
Method method = allDescriptors[i].getMethod();
|
||||||
if (debug) System.out.println("** Method examined: " + method.toString());
|
// if (debug) System.out.println("** Method examined: " + method.toString());
|
||||||
if (!allDescriptors[i].getName().equals(functionName)) continue;
|
if (!allDescriptors[i].getName().equals(functionName)) continue;
|
||||||
// Method has same name, some tuning neede:
|
// Method has same name, some tuning neede:
|
||||||
// If the class itself is not public, there is an access error if
|
// If the class itself is not public, there is an access error if
|
||||||
|
@ -507,21 +507,21 @@ public class ClassInfo {
|
||||||
// I am not too sure of what happens if the method is defined in an
|
// I am not too sure of what happens if the method is defined in an
|
||||||
// interface...
|
// interface...
|
||||||
if (!Modifier.isStatic(cls.getModifiers()) && !Modifier.isPublic(cls.getModifiers())) {
|
if (!Modifier.isStatic(cls.getModifiers()) && !Modifier.isPublic(cls.getModifiers())) {
|
||||||
if (debug) System.out.println("** Bean class " + cls +
|
// if (debug) System.out.println("** Bean class " + cls +
|
||||||
" is not public, examining superclasses to find proper method descriptor");
|
// " is not public, examining superclasses to find proper method descriptor");
|
||||||
SEARCHPUBLIC:
|
SEARCHPUBLIC:
|
||||||
for (Class theClass=cls;theClass!=null;theClass=theClass.getSuperclass()) {
|
for (Class theClass=cls;theClass!=null;theClass=theClass.getSuperclass()) {
|
||||||
if (Modifier.isPublic(theClass.getModifiers())) {
|
if (Modifier.isPublic(theClass.getModifiers())) {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** Looking in public superlass: " + theClass);
|
// System.out.println("** Looking in public superlass: " + theClass);
|
||||||
}
|
// }
|
||||||
try {
|
try {
|
||||||
Class[] paramTypes = method.getParameterTypes();
|
Class[] paramTypes = method.getParameterTypes();
|
||||||
Method m = theClass.getDeclaredMethod(functionName,paramTypes);
|
Method m = theClass.getDeclaredMethod(functionName,paramTypes);
|
||||||
if (Modifier.isPublic(method.getModifiers())) {
|
if (Modifier.isPublic(method.getModifiers())) {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** Public method found: " + functionName);
|
// System.out.println("** Public method found: " + functionName);
|
||||||
}
|
// }
|
||||||
method = m;
|
method = m;
|
||||||
break SEARCHPUBLIC;
|
break SEARCHPUBLIC;
|
||||||
}
|
}
|
||||||
|
@ -531,9 +531,9 @@ public class ClassInfo {
|
||||||
throw new ProgrammingError("Acess error inspecting method "+ functionName + ": " + e);
|
throw new ProgrammingError("Acess error inspecting method "+ functionName + ": " + e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
System.out.println("** Superlass " + theClass + " is not public");
|
// System.out.println("** Superlass " + theClass + " is not public");
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
} // for
|
} // for
|
||||||
} // if class not public
|
} // if class not public
|
||||||
|
@ -547,8 +547,8 @@ public class ClassInfo {
|
||||||
Method [] methods = null;
|
Method [] methods = null;
|
||||||
int nmbMethods = methodVector.size();
|
int nmbMethods = methodVector.size();
|
||||||
if (nmbMethods>0) {
|
if (nmbMethods>0) {
|
||||||
if (debug) System.out.println("** " + nmbMethods + " methods named: '"
|
// if (debug) System.out.println("** " + nmbMethods + " methods named: '"
|
||||||
+ functionName + "' + found, add to bean cache");
|
// + functionName + "' + found, add to bean cache");
|
||||||
methods = new Method[nmbMethods];
|
methods = new Method[nmbMethods];
|
||||||
methodVector.copyInto(methods);
|
methodVector.copyInto(methods);
|
||||||
if (beanMethods==null) {
|
if (beanMethods==null) {
|
||||||
|
@ -556,8 +556,8 @@ public class ClassInfo {
|
||||||
}
|
}
|
||||||
beanMethods.put(functionName, methods);
|
beanMethods.put(functionName, methods);
|
||||||
} else {
|
} else {
|
||||||
if (debug) System.out.println("** No bean method named: '" +
|
// if (debug) System.out.println("** No bean method named: '" +
|
||||||
functionName + "' + found");
|
// functionName + "' + found");
|
||||||
}
|
}
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,12 @@ public abstract class HelmaExtension {
|
||||||
*/
|
*/
|
||||||
public abstract void applicationStopped (Application app);
|
public abstract void applicationStopped (Application app);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called when an Application's properties are have been updated.
|
||||||
|
* note that this will be called at startup once *before* applicationStarted().
|
||||||
|
*/
|
||||||
|
public abstract void applicationUpdated (Application app);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called by the ScriptingEngine when it is initizalized. Throws a ConfigurationException
|
* called by the ScriptingEngine when it is initizalized. Throws a ConfigurationException
|
||||||
* when this type of ScriptingEngine is not supported. New methods and prototypes can be
|
* when this type of ScriptingEngine is not supported. New methods and prototypes can be
|
||||||
|
|
|
@ -43,6 +43,10 @@ public class DemoExtension extends HelmaExtension {
|
||||||
app.logEvent ("DemoExtension stopped on app " + app.getName () );
|
app.logEvent ("DemoExtension stopped on app " + app.getName () );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void applicationUpdated (Application app) {
|
||||||
|
app.logEvent ("DemoExtension updated on app " + app.getName () );
|
||||||
|
}
|
||||||
|
|
||||||
public HashMap initScripting (Application app, ScriptingEngine engine) throws ConfigurationException {
|
public HashMap initScripting (Application app, ScriptingEngine engine) throws ConfigurationException {
|
||||||
if (!(engine instanceof FesiEngine))
|
if (!(engine instanceof FesiEngine))
|
||||||
throw new ConfigurationException ("scripting engine " + engine.toString () + " not supported in DemoExtension");
|
throw new ConfigurationException ("scripting engine " + engine.toString () + " not supported in DemoExtension");
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class ResponseBean implements Serializable {
|
||||||
res.writeBinary (what);
|
res.writeBinary (what);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void debug (String message) {
|
public void debug (Object message) {
|
||||||
res.debug (message);
|
res.debug (message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,19 +185,15 @@ public final class ResponseTrans implements Externalizable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of characters written to the response buffer so far.
|
* Get the response buffer, creating it if it doesn't exist
|
||||||
*/
|
*/
|
||||||
public int getBufferLength() {
|
public StringBuffer getBuffer () {
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
return 0;
|
buffer = new StringBuffer (INITIAL_BUFFER_SIZE);
|
||||||
return buffer.length ();
|
return buffer;
|
||||||
}
|
|
||||||
|
|
||||||
public void setBufferLength(int l) {
|
|
||||||
if (buffer != null)
|
|
||||||
buffer.setLength (l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a string to the response unchanged. This is often called
|
* Append a string to the response unchanged. This is often called
|
||||||
* at the end of a request to write out the whole page, so if buffer
|
* at the end of a request to write out the whole page, so if buffer
|
||||||
|
@ -237,10 +233,13 @@ public final class ResponseTrans implements Externalizable {
|
||||||
* that buffer exists and its length is larger than offset. str may be null, in which
|
* that buffer exists and its length is larger than offset. str may be null, in which
|
||||||
* case nothing happens.
|
* case nothing happens.
|
||||||
*/
|
*/
|
||||||
public void debug (String str) {
|
public void debug (Object message) {
|
||||||
if (debugBuffer == null)
|
if (debugBuffer == null)
|
||||||
debugBuffer = new StringBuffer ();
|
debugBuffer = new StringBuffer ();
|
||||||
debugBuffer.append ("<p><span style=\"background: yellow; color: black\">"+str+"</span></p>");
|
String str = message == null ? "null" : message.toString ();
|
||||||
|
debugBuffer.append ("<p><span style=\"background: yellow; color: black\">");
|
||||||
|
debugBuffer.append (str);
|
||||||
|
debugBuffer.append ("</span></p>");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -335,17 +334,25 @@ public final class ResponseTrans implements Externalizable {
|
||||||
if (charset == null)
|
if (charset == null)
|
||||||
charset = "ISO-8859-1";
|
charset = "ISO-8859-1";
|
||||||
boolean encodingError = false;
|
boolean encodingError = false;
|
||||||
|
// only close if the response hasn't been closed yet
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
if (buffer != null) {
|
// if debug buffer exists, append it to main buffer
|
||||||
if (debugBuffer != null)
|
if (debugBuffer != null) {
|
||||||
|
if (buffer == null)
|
||||||
|
buffer = debugBuffer;
|
||||||
|
else
|
||||||
buffer.append (debugBuffer);
|
buffer.append (debugBuffer);
|
||||||
|
}
|
||||||
|
// get the buffer's bytes in the specified encoding
|
||||||
|
if (buffer != null) {
|
||||||
try {
|
try {
|
||||||
response = buffer.toString ().getBytes (charset);
|
response = buffer.toString ().getBytes (charset);
|
||||||
} catch (UnsupportedEncodingException uee) {
|
} catch (UnsupportedEncodingException uee) {
|
||||||
encodingError = true;
|
encodingError = true;
|
||||||
response = buffer.toString ().getBytes ();
|
response = buffer.toString ().getBytes ();
|
||||||
}
|
}
|
||||||
buffer = null; // make sure this is done only once, even with more requsts attached
|
// make sure this is done only once, even with more requsts attached
|
||||||
|
buffer = null;
|
||||||
} else {
|
} else {
|
||||||
response = new byte[0];
|
response = new byte[0];
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,6 +228,11 @@ public final class Application implements IPathElement, Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read the sessions if wanted
|
||||||
|
if ("true".equalsIgnoreCase (getProperty("persistentSessions"))) {
|
||||||
|
loadSessionData (null);
|
||||||
|
}
|
||||||
|
|
||||||
typemgr = new TypeManager (this);
|
typemgr = new TypeManager (this);
|
||||||
typemgr.createPrototypes ();
|
typemgr.createPrototypes ();
|
||||||
// logEvent ("Started type manager for "+name);
|
// logEvent ("Started type manager for "+name);
|
||||||
|
@ -319,6 +324,11 @@ public final class Application implements IPathElement, Runnable {
|
||||||
ext.applicationStopped (this);
|
ext.applicationStopped (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store the sessions if wanted
|
||||||
|
if ("true".equalsIgnoreCase (getProperty("persistentSessions"))) {
|
||||||
|
storeSessionData (null);
|
||||||
|
}
|
||||||
|
|
||||||
// stop logs if they exist
|
// stop logs if they exist
|
||||||
if (eventLog != null) {
|
if (eventLog != null) {
|
||||||
eventLog.close ();
|
eventLog.close ();
|
||||||
|
@ -840,34 +850,31 @@ public final class Application implements IPathElement, Runnable {
|
||||||
*/
|
*/
|
||||||
public String getNodeHref (Object elem, String actionName) {
|
public String getNodeHref (Object elem, String actionName) {
|
||||||
// Object root = getDataRoot ();
|
// Object root = getDataRoot ();
|
||||||
|
|
||||||
// check optional root prototype from app.properties
|
// check optional root prototype from app.properties
|
||||||
String rootProto = props.getProperty ("rootPrototype");
|
String rootProto = props.getProperty ("rootPrototype");
|
||||||
|
|
||||||
String divider = "/";
|
StringBuffer b = new StringBuffer (baseURI);
|
||||||
StringBuffer b = new StringBuffer ();
|
|
||||||
Object parent = null;
|
|
||||||
int loopWatch = 0;
|
|
||||||
|
|
||||||
while (elem != null && (parent = getParentElement (elem)) != null && elem != rootObject) {
|
composeHref (elem, b, rootProto, 0);
|
||||||
|
|
||||||
if (rootProto != null && rootProto.equals (getPrototypeName (elem)))
|
|
||||||
break;
|
|
||||||
b.insert (0, divider);
|
|
||||||
b.insert (0, UrlEncoded.encode (getElementName (elem)));
|
|
||||||
// move down to the element's parent
|
|
||||||
elem = parent;
|
|
||||||
|
|
||||||
if (loopWatch++ > 20)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actionName != null)
|
if (actionName != null)
|
||||||
b.append (UrlEncoded.encode (actionName));
|
b.append (UrlEncoded.encode (actionName));
|
||||||
|
|
||||||
return baseURI + b.toString ();
|
return b.toString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final void composeHref (Object elem, StringBuffer b, String rootProto, int pathCount) {
|
||||||
|
if (elem == null || pathCount > 20)
|
||||||
|
return;
|
||||||
|
if (rootProto != null && rootProto.equals (getPrototypeName (elem)))
|
||||||
|
return;
|
||||||
|
Object parent = getParentElement (elem);
|
||||||
|
if (parent == null)
|
||||||
|
return;
|
||||||
|
composeHref (getParentElement (elem), b, rootProto, pathCount++);
|
||||||
|
b.append (UrlEncoded.encode (getElementName (elem)));
|
||||||
|
b.append ("/");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets the base URL of this application which will be prepended to
|
* This method sets the base URL of this application which will be prepended to
|
||||||
|
@ -1112,9 +1119,8 @@ public final class Application implements IPathElement, Runnable {
|
||||||
NodeHandle userhandle = session.userHandle;
|
NodeHandle userhandle = session.userHandle;
|
||||||
if (userhandle != null) {
|
if (userhandle != null) {
|
||||||
try {
|
try {
|
||||||
String[] str = new String [1];
|
Object[] param = { session.getSessionID() };
|
||||||
str[0] = session.getSessionID ();
|
eval.invokeFunction (userhandle, "onLogout", param);
|
||||||
eval.invokeFunction (userhandle, "onLogout", str);
|
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
destroySession(session);
|
destroySession(session);
|
||||||
|
@ -1143,7 +1149,7 @@ public final class Application implements IPathElement, Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// sleep until we have work to do
|
// sleep until we have work to do
|
||||||
try {
|
try {
|
||||||
worker.sleep (Math.min (cleanupSleep, scheduleSleep));
|
worker.sleep (Math.min (cleanupSleep, scheduleSleep));
|
||||||
} catch (InterruptedException x) {
|
} catch (InterruptedException x) {
|
||||||
logEvent ("Scheduler for "+name+" interrupted");
|
logEvent ("Scheduler for "+name+" interrupted");
|
||||||
|
@ -1256,6 +1262,14 @@ public final class Application implements IPathElement, Runnable {
|
||||||
// if node manager exists, update it
|
// if node manager exists, update it
|
||||||
if (nmgr != null)
|
if (nmgr != null)
|
||||||
nmgr.updateProperties (props);
|
nmgr.updateProperties (props);
|
||||||
|
// update extensions
|
||||||
|
Vector extensions = Server.getServer ().getExtensions ();
|
||||||
|
for (int i=0; i<extensions.size(); i++) {
|
||||||
|
HelmaExtension ext = (HelmaExtension)extensions.get(i);
|
||||||
|
try {
|
||||||
|
ext.applicationUpdated (this);
|
||||||
|
} catch (ConfigurationException e) { }
|
||||||
|
}
|
||||||
// set prop read timestamp
|
// set prop read timestamp
|
||||||
lastPropertyRead = props.lastModified ();
|
lastPropertyRead = props.lastModified ();
|
||||||
}
|
}
|
||||||
|
@ -1388,5 +1402,65 @@ public final class Application implements IPathElement, Runnable {
|
||||||
throw new Exception ("Method "+key+" is not callable via XML-RPC");
|
throw new Exception ("Method "+key+" is not callable via XML-RPC");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void storeSessionData (File f) {
|
||||||
|
if (f==null)
|
||||||
|
f = new File(dbDir, "sessions");
|
||||||
|
try {
|
||||||
|
OutputStream ostream = new BufferedOutputStream (new FileOutputStream(f));
|
||||||
|
ObjectOutputStream p = new ObjectOutputStream(ostream);
|
||||||
|
synchronized (sessions) {
|
||||||
|
p.writeInt (sessions.size ());
|
||||||
|
for (Enumeration e=sessions.elements (); e.hasMoreElements ();) {
|
||||||
|
p.writeObject ((Session) e.nextElement ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.flush();
|
||||||
|
ostream.close();
|
||||||
|
logEvent ("stored " + sessions.size () + " sessions in file");
|
||||||
|
} catch (Exception e) {
|
||||||
|
logEvent ("error storing session data: " + e.toString ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* loads the serialized session table from a given file or from dbdir/sessions
|
||||||
|
*/
|
||||||
|
public void loadSessionData (File f) {
|
||||||
|
if (f==null)
|
||||||
|
f = new File(dbDir, "sessions");
|
||||||
|
// compute session timeout value
|
||||||
|
int sessionTimeout = 30;
|
||||||
|
try {
|
||||||
|
sessionTimeout = Math.max (0, Integer.parseInt (props.getProperty ("sessionTimeout", "30")));
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
System.out.println(ignore.toString());
|
||||||
|
}
|
||||||
|
long now = System.currentTimeMillis ();
|
||||||
|
try {
|
||||||
|
// load the stored data:
|
||||||
|
InputStream istream = new BufferedInputStream (new FileInputStream(f));
|
||||||
|
ObjectInputStream p = new ObjectInputStream(istream);
|
||||||
|
int size = p.readInt ();
|
||||||
|
int ct = 0;
|
||||||
|
Hashtable newSessions = new Hashtable ();
|
||||||
|
while (ct < size) {
|
||||||
|
Session session = (Session) p.readObject ();
|
||||||
|
if (now - session.lastTouched () < sessionTimeout * 60000) {
|
||||||
|
session.setApp (this);
|
||||||
|
newSessions.put (session.getSessionID (), session);
|
||||||
|
}
|
||||||
|
ct++;
|
||||||
|
}
|
||||||
|
p.close ();
|
||||||
|
istream.close ();
|
||||||
|
sessions = newSessions;
|
||||||
|
logEvent ("loaded " + newSessions.size () + " sessions from file");
|
||||||
|
} catch (Exception e) {
|
||||||
|
logEvent ("error loading session data: " + e.toString ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,23 +24,27 @@ public class ApplicationBean implements Serializable {
|
||||||
app.clearCache ();
|
app.clearCache ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void log (String msg) {
|
public void log (Object msg) {
|
||||||
app.logEvent (msg);
|
String str = msg == null ? "null" : msg.toString();
|
||||||
|
app.logEvent (str);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void log (String logname, String msg) {
|
public void log (String logname, Object msg) {
|
||||||
app.getLogger (logname).log (msg);
|
String str = msg == null ? "null" : msg.toString();
|
||||||
|
app.getLogger (logname).log (str);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void debug (String msg) {
|
public void debug (Object msg) {
|
||||||
if (app.debug()) {
|
if (app.debug()) {
|
||||||
app.logEvent (msg);
|
String str = msg == null ? "null" : msg.toString();
|
||||||
|
app.logEvent (str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void debug (String logname, String msg) {
|
public void debug (String logname, Object msg) {
|
||||||
if (app.debug()) {
|
if (app.debug()) {
|
||||||
app.getLogger (logname).log (msg);
|
String str = msg == null ? "null" : msg.toString();
|
||||||
|
app.getLogger (logname).log (str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,8 +269,6 @@ public final class RequestEvaluator implements Runnable {
|
||||||
scriptingEngine.invoke (currentElement, "onRequest", new Object[0], false);
|
scriptingEngine.invoke (currentElement, "onRequest", new Object[0], false);
|
||||||
} catch (RedirectException redir) {
|
} catch (RedirectException redir) {
|
||||||
throw redir;
|
throw redir;
|
||||||
} catch (Exception ignore) {
|
|
||||||
// function is not defined or caused an exception, ignore
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset skin recursion detection counter
|
// reset skin recursion detection counter
|
||||||
|
@ -351,7 +349,7 @@ public final class RequestEvaluator implements Runnable {
|
||||||
break;
|
break;
|
||||||
case XMLRPC:
|
case XMLRPC:
|
||||||
try {
|
try {
|
||||||
localrtx.begin (app.getName()+":xmlrpc/"+method);
|
localrtx.begin (app.getName()+":xmlrpc:"+method);
|
||||||
|
|
||||||
root = app.getDataRoot ();
|
root = app.getDataRoot ();
|
||||||
|
|
||||||
|
@ -386,23 +384,25 @@ public final class RequestEvaluator implements Runnable {
|
||||||
result = scriptingEngine.invoke (currentElement, method, args, true);
|
result = scriptingEngine.invoke (currentElement, method, args, true);
|
||||||
commitTransaction ();
|
commitTransaction ();
|
||||||
|
|
||||||
} catch (Exception wrong) {
|
} catch (Exception x) {
|
||||||
|
|
||||||
abortTransaction (false);
|
abortTransaction (false);
|
||||||
|
|
||||||
|
app.logEvent ("Exception in "+Thread.currentThread()+": "+x);
|
||||||
|
|
||||||
// If the transactor thread has been killed by the invoker thread we don't have to
|
// If the transactor thread has been killed by the invoker thread we don't have to
|
||||||
// bother for the error message, just quit.
|
// bother for the error message, just quit.
|
||||||
if (localrtx != rtx) {
|
if (localrtx != rtx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.exception = wrong;
|
this.exception = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case INTERNAL:
|
case INTERNAL:
|
||||||
// Just a human readable descriptor of this invocation
|
// Just a human readable descriptor of this invocation
|
||||||
String funcdesc = app.getName()+":internal/"+method;
|
String funcdesc = app.getName()+":internal:"+method;
|
||||||
|
|
||||||
// if thisObject is an instance of NodeHandle, get the node object itself.
|
// if thisObject is an instance of NodeHandle, get the node object itself.
|
||||||
if (thisObject != null && thisObject instanceof NodeHandle) {
|
if (thisObject != null && thisObject instanceof NodeHandle) {
|
||||||
|
@ -438,17 +438,19 @@ public final class RequestEvaluator implements Runnable {
|
||||||
result = scriptingEngine.invoke (thisObject, method, args, false);
|
result = scriptingEngine.invoke (thisObject, method, args, false);
|
||||||
commitTransaction ();
|
commitTransaction ();
|
||||||
|
|
||||||
} catch (Exception wrong) {
|
} catch (Exception x) {
|
||||||
|
|
||||||
abortTransaction (false);
|
abortTransaction (false);
|
||||||
|
|
||||||
|
app.logEvent ("Exception in "+Thread.currentThread()+": "+x);
|
||||||
|
|
||||||
// If the transactor thread has been killed by the invoker thread we don't have to
|
// If the transactor thread has been killed by the invoker thread we don't have to
|
||||||
// bother for the error message, just quit.
|
// bother for the error message, just quit.
|
||||||
if (localrtx != rtx) {
|
if (localrtx != rtx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.exception = wrong;
|
this.exception = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,7 +17,7 @@ import helma.objectmodel.db.*;
|
||||||
|
|
||||||
public class Session implements Serializable {
|
public class Session implements Serializable {
|
||||||
|
|
||||||
Application app;
|
transient Application app;
|
||||||
String sessionID;
|
String sessionID;
|
||||||
|
|
||||||
// the unique id (login name) for the user, if logged in
|
// the unique id (login name) for the user, if logged in
|
||||||
|
@ -98,6 +98,10 @@ public class Session implements Serializable {
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setApp (Application app) {
|
||||||
|
this.app = app;
|
||||||
|
}
|
||||||
|
|
||||||
public String getSessionID () {
|
public String getSessionID () {
|
||||||
return sessionID;
|
return sessionID;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import java.util.*;
|
||||||
|
|
||||||
public final class Skin {
|
public final class Skin {
|
||||||
|
|
||||||
private Macro[] parts;
|
private Macro[] macros;
|
||||||
private Application app;
|
private Application app;
|
||||||
private char[] source;
|
private char[] source;
|
||||||
private int sourceLength;
|
private int sourceLength;
|
||||||
|
@ -84,8 +84,8 @@ public final class Skin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parts = new Macro[partBuffer.size()];
|
macros = new Macro[partBuffer.size()];
|
||||||
partBuffer.toArray (parts);
|
partBuffer.toArray (macros);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,7 +104,7 @@ public final class Skin {
|
||||||
if (++reval.skinDepth > 50)
|
if (++reval.skinDepth > 50)
|
||||||
throw new RuntimeException ("Recursive skin invocation suspected");
|
throw new RuntimeException ("Recursive skin invocation suspected");
|
||||||
|
|
||||||
if (parts == null) {
|
if (macros == null) {
|
||||||
reval.res.writeCharArray (source, 0, sourceLength);
|
reval.res.writeCharArray (source, 0, sourceLength);
|
||||||
reval.skinDepth--;
|
reval.skinDepth--;
|
||||||
return;
|
return;
|
||||||
|
@ -113,14 +113,14 @@ public final class Skin {
|
||||||
try {
|
try {
|
||||||
int written = 0;
|
int written = 0;
|
||||||
Map handlerCache = null;
|
Map handlerCache = null;
|
||||||
if (parts.length > 3) {
|
if (macros.length > 3) {
|
||||||
handlerCache = new HashMap();
|
handlerCache = new HashMap();
|
||||||
}
|
}
|
||||||
for (int i=0; i<parts.length; i++) {
|
for (int i=0; i<macros.length; i++) {
|
||||||
if (parts[i].start > written)
|
if (macros[i].start > written)
|
||||||
reval.res.writeCharArray (source, written, parts[i].start-written);
|
reval.res.writeCharArray (source, written, macros[i].start-written);
|
||||||
parts[i].render (reval, thisObject, paramObject, handlerCache);
|
macros[i].render (reval, thisObject, paramObject, handlerCache);
|
||||||
written = parts[i].end;
|
written = macros[i].end;
|
||||||
}
|
}
|
||||||
if (written < sourceLength)
|
if (written < sourceLength)
|
||||||
reval.res.writeCharArray (source, written, sourceLength-written);
|
reval.res.writeCharArray (source, written, sourceLength-written);
|
||||||
|
@ -133,9 +133,9 @@ public final class Skin {
|
||||||
* Check if a certain macro is present in this skin. The macro name is in handler.name notation
|
* Check if a certain macro is present in this skin. The macro name is in handler.name notation
|
||||||
*/
|
*/
|
||||||
public boolean containsMacro (String macroname) {
|
public boolean containsMacro (String macroname) {
|
||||||
for (int i=0; i<parts.length; i++) {
|
for (int i=0; i<macros.length; i++) {
|
||||||
if (parts[i] instanceof Macro) {
|
if (macros[i] instanceof Macro) {
|
||||||
Macro m = (Macro) parts[i];
|
Macro m = (Macro) macros[i];
|
||||||
if (macroname.equals (m.fullName))
|
if (macroname.equals (m.fullName))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -158,6 +158,13 @@ public final class Skin {
|
||||||
static final int PARAMNAME = 2;
|
static final int PARAMNAME = 2;
|
||||||
static final int PARAMVALUE = 3;
|
static final int PARAMVALUE = 3;
|
||||||
|
|
||||||
|
static final int ENCODE_NONE = 0;
|
||||||
|
static final int ENCODE_HTML = 1;
|
||||||
|
static final int ENCODE_XML = 2;
|
||||||
|
static final int ENCODE_FORM = 3;
|
||||||
|
static final int ENCODE_URL = 4;
|
||||||
|
static final int ENCODE_ALL = 5;
|
||||||
|
|
||||||
class Macro {
|
class Macro {
|
||||||
|
|
||||||
final int start, end;
|
final int start, end;
|
||||||
|
@ -166,8 +173,8 @@ public final class Skin {
|
||||||
String fullName;
|
String fullName;
|
||||||
String prefix;
|
String prefix;
|
||||||
String suffix;
|
String suffix;
|
||||||
String encoding;
|
|
||||||
String defaultValue;
|
String defaultValue;
|
||||||
|
int encoding = ENCODE_NONE;
|
||||||
Map parameters = null;
|
Map parameters = null;
|
||||||
|
|
||||||
public Macro (int start, int end) {
|
public Macro (int start, int end) {
|
||||||
|
@ -264,7 +271,7 @@ public final class Skin {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean setSpecialParameter (String name, String value) {
|
private boolean setSpecialParameter (String name, String value) {
|
||||||
if ("prefix".equals (name)) {
|
if ("prefix".equals (name)) {
|
||||||
prefix = value;
|
prefix = value;
|
||||||
|
@ -273,7 +280,16 @@ public final class Skin {
|
||||||
suffix = value;
|
suffix = value;
|
||||||
return true;
|
return true;
|
||||||
} else if ("encoding".equals (name)) {
|
} else if ("encoding".equals (name)) {
|
||||||
encoding = value;
|
if ("html".equalsIgnoreCase (value))
|
||||||
|
encoding = ENCODE_HTML;
|
||||||
|
else if ("xml".equalsIgnoreCase (value))
|
||||||
|
encoding = ENCODE_XML;
|
||||||
|
else if ("form".equalsIgnoreCase (value))
|
||||||
|
encoding = ENCODE_FORM;
|
||||||
|
else if ("url".equalsIgnoreCase (value))
|
||||||
|
encoding = ENCODE_URL;
|
||||||
|
else if ("all".equalsIgnoreCase (value))
|
||||||
|
encoding = ENCODE_ALL;
|
||||||
return true;
|
return true;
|
||||||
} else if ("default".equals (name)) {
|
} else if ("default".equals (name)) {
|
||||||
defaultValue = value;
|
defaultValue = value;
|
||||||
|
@ -347,16 +363,9 @@ public final class Skin {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlerObject == null) {
|
if (handlerObject == null) {
|
||||||
// eiter because thisObject == null or the right object wasn't found in the object's parent path
|
// eiter because thisObject == null or the right object wasn't found
|
||||||
// go check request path for an object with matching prototype
|
// in the object's parent path. Check if a matching macro handler
|
||||||
/* int l = reval.requestPath.size();
|
// is registered with the response object (res.handlers).
|
||||||
for (int i=l-1; i>=0; i--) {
|
|
||||||
Object pathelem = reval.requestPath.get (i);
|
|
||||||
if (handler.equals (app.getPrototypeName (pathelem))) {
|
|
||||||
handlerObject = pathelem;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
handlerObject = reval.res.getMacroHandlers().get (handler);
|
handlerObject = reval.res.getMacroHandlers().get (handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,12 +389,14 @@ public final class Skin {
|
||||||
|
|
||||||
String funcName = name+"_macro";
|
String funcName = name+"_macro";
|
||||||
if (reval.scriptingEngine.hasFunction (handlerObject, funcName)) {
|
if (reval.scriptingEngine.hasFunction (handlerObject, funcName)) {
|
||||||
|
|
||||||
|
StringBuffer buffer = reval.res.getBuffer();
|
||||||
// remember length of response buffer before calling macro
|
// remember length of response buffer before calling macro
|
||||||
int bufLength = reval.res.getBufferLength ();
|
int bufLength = buffer.length();
|
||||||
// remember length of buffer with prefix written out
|
// remember length of buffer with prefix written out
|
||||||
int preLength = 0;
|
int preLength = 0;
|
||||||
if (prefix != null) {
|
if (prefix != null) {
|
||||||
reval.res.write (prefix);
|
buffer.append (prefix);
|
||||||
preLength = prefix.length();
|
preLength = prefix.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,24 +407,36 @@ public final class Skin {
|
||||||
// parameters = new HashMap ();
|
// parameters = new HashMap ();
|
||||||
Object[] arguments = { parameters == null ?
|
Object[] arguments = { parameters == null ?
|
||||||
new HashMap () :
|
new HashMap () :
|
||||||
new HashMap (parameters) };
|
new HashMap (parameters)
|
||||||
|
};
|
||||||
|
|
||||||
|
Object value = reval.scriptingEngine.invoke (handlerObject, funcName, arguments, false);
|
||||||
|
|
||||||
Object v = reval.scriptingEngine.invoke (handlerObject, funcName, arguments, false);
|
|
||||||
// check if macro wrote out to response buffer
|
// check if macro wrote out to response buffer
|
||||||
if (reval.res.getBufferLength () == bufLength + preLength) {
|
if (buffer.length () == bufLength + preLength) {
|
||||||
// function didn't write out anything itself
|
// function didn't write out anything itself.
|
||||||
|
// erase previously written prefix
|
||||||
if (preLength > 0)
|
if (preLength > 0)
|
||||||
reval.res.setBufferLength (bufLength);
|
buffer.setLength (bufLength);
|
||||||
writeToResponse (v, reval.res, true);
|
// write out macro's return value
|
||||||
|
writeResponse (value, buffer, true);
|
||||||
} else {
|
} else {
|
||||||
if (suffix != null)
|
if (encoding != ENCODE_NONE) {
|
||||||
reval.res.write (suffix);
|
// if an encoding is specified, re-encode the macro's output
|
||||||
writeToResponse (v, reval.res, false);
|
String output = buffer.substring (bufLength + preLength);
|
||||||
|
buffer.setLength (bufLength);
|
||||||
|
writeResponse (output, buffer, false);
|
||||||
|
} else {
|
||||||
|
// no re-encoding needed, just append suffix
|
||||||
|
if (suffix != null)
|
||||||
|
buffer.append (suffix);
|
||||||
|
}
|
||||||
|
writeResponse (value, buffer, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// System.err.println ("Getting macro from property");
|
// System.err.println ("Getting macro from property");
|
||||||
Object v = reval.scriptingEngine.get (handlerObject, name);
|
Object value = reval.scriptingEngine.get (handlerObject, name);
|
||||||
writeToResponse (v, reval.res, true);
|
writeResponse (value, reval.res.getBuffer(), true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String msg = "[HopMacro unhandled: "+fullName+"]";
|
String msg = "[HopMacro unhandled: "+fullName+"]";
|
||||||
|
@ -445,21 +468,21 @@ public final class Skin {
|
||||||
value = reval.res.error;
|
value = reval.res.error;
|
||||||
if (value == null)
|
if (value == null)
|
||||||
value = reval.res.get (name);
|
value = reval.res.get (name);
|
||||||
writeToResponse (value, reval.res, true);
|
writeResponse (value, reval.res.getBuffer(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFromRequest (RequestEvaluator reval) {
|
private void renderFromRequest (RequestEvaluator reval) {
|
||||||
if (reval.req == null)
|
if (reval.req == null)
|
||||||
return;
|
return;
|
||||||
Object value = reval.req.get (name);
|
Object value = reval.req.get (name);
|
||||||
writeToResponse (value, reval.res, true);
|
writeResponse (value, reval.res.getBuffer(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFromSession (RequestEvaluator reval) {
|
private void renderFromSession (RequestEvaluator reval) {
|
||||||
if (reval.session == null)
|
if (reval.session == null)
|
||||||
return;
|
return;
|
||||||
Object value = reval.session.getCacheNode().getString (name);
|
Object value = reval.session.getCacheNode().getString (name);
|
||||||
writeToResponse (value, reval.res, true);
|
writeResponse (value, reval.res.getBuffer(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFromParam (RequestEvaluator reval, Map paramObject) {
|
private void renderFromParam (RequestEvaluator reval, Map paramObject) {
|
||||||
|
@ -467,14 +490,14 @@ public final class Skin {
|
||||||
reval.res.write ("[HopMacro error: Skin requires a parameter object]");
|
reval.res.write ("[HopMacro error: Skin requires a parameter object]");
|
||||||
else {
|
else {
|
||||||
Object value = paramObject.get (name);
|
Object value = paramObject.get (name);
|
||||||
writeToResponse (value, reval.res, true);
|
writeResponse (value, reval.res.getBuffer(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility method for writing text out to the response object.
|
* Utility method for writing text out to the response object.
|
||||||
*/
|
*/
|
||||||
void writeToResponse (Object value, ResponseTrans res, boolean useDefault) {
|
void writeResponse (Object value, StringBuffer buffer, boolean useDefault) {
|
||||||
String text;
|
String text;
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
if (useDefault)
|
if (useDefault)
|
||||||
|
@ -484,36 +507,39 @@ public final class Skin {
|
||||||
} else {
|
} else {
|
||||||
text = value.toString ();
|
text = value.toString ();
|
||||||
}
|
}
|
||||||
if (text == null || text.length() == 0)
|
if (text != null && text.length() > 0) {
|
||||||
return;
|
if (prefix != null)
|
||||||
if (encoding != null)
|
buffer.append (prefix);
|
||||||
text = encode (text, encoding);
|
switch (encoding) {
|
||||||
res.write (prefix);
|
case ENCODE_NONE:
|
||||||
res.write (text);
|
buffer.append (text);
|
||||||
res.write (suffix);
|
break;
|
||||||
}
|
case ENCODE_HTML:
|
||||||
|
HtmlEncoder.encode (text, buffer);
|
||||||
/**
|
break;
|
||||||
* Utility method for performing different kind of character
|
case ENCODE_XML:
|
||||||
* encodings on the macro output.
|
HtmlEncoder.encodeXml (text, buffer);
|
||||||
*/
|
break;
|
||||||
String encode (String text, String encoding) {
|
case ENCODE_FORM:
|
||||||
if ("html".equalsIgnoreCase (encoding))
|
HtmlEncoder.encodeFormValue (text, buffer);
|
||||||
return HtmlEncoder.encode (text);
|
break;
|
||||||
if ("xml".equalsIgnoreCase (encoding))
|
case ENCODE_URL:
|
||||||
return HtmlEncoder.encodeXml (text);
|
buffer.append (URLEncoder.encode (text));
|
||||||
if ("form".equalsIgnoreCase (encoding))
|
break;
|
||||||
return HtmlEncoder.encodeFormValue (text);
|
case ENCODE_ALL:
|
||||||
if ("url".equalsIgnoreCase (encoding))
|
HtmlEncoder.encodeAll (text, buffer);
|
||||||
return URLEncoder.encode (text);
|
break;
|
||||||
return text;
|
}
|
||||||
|
if (suffix != null)
|
||||||
|
buffer.append (suffix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
return "[HopMacro: "+fullName+"]";
|
return "[HopMacro: "+fullName+"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the full name of the macro in handler.name notation
|
* Return the full name of the macro in handler.name notation
|
||||||
|
|
|
@ -9,10 +9,10 @@ import java.net.URL;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This creates an invisible frame in order to be able to create images
|
* Factory class for generating Image objects from various sources.
|
||||||
* from Java. (Java needs a window context in order to user the Image class).
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ImageGenerator {
|
public class ImageGenerator {
|
||||||
|
|
||||||
public ImageGenerator () {
|
public ImageGenerator () {
|
||||||
|
@ -20,10 +20,9 @@ public class ImageGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageWrapper createPaintableImage (int w, int h) {
|
public ImageWrapper createPaintableImage (int w, int h) {
|
||||||
Image img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
|
BufferedImage img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
|
||||||
Graphics g = img.getGraphics ();
|
Graphics g = img.getGraphics ();
|
||||||
ImageWrapper rimg = null;
|
ImageWrapper rimg = new SunImageWrapper (img, g, w, h, this);
|
||||||
rimg = new SunImageWrapper (img, g, w, h, this);
|
|
||||||
return rimg;
|
return rimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,13 +30,17 @@ public class ImageGenerator {
|
||||||
ImageWrapper rimg = null;
|
ImageWrapper rimg = null;
|
||||||
Image img1 = Toolkit.getDefaultToolkit ().createImage (src);
|
Image img1 = Toolkit.getDefaultToolkit ().createImage (src);
|
||||||
ImageLoader loader = new ImageLoader (img1);
|
ImageLoader loader = new ImageLoader (img1);
|
||||||
loader.load ();
|
try {
|
||||||
int w = loader.getWidth ();
|
loader.getDimensions ();
|
||||||
int h = loader.getHeight ();
|
int w = loader.getWidth ();
|
||||||
Image img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
|
int h = loader.getHeight ();
|
||||||
Graphics g = img.getGraphics ();
|
Image img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
|
||||||
g.drawImage (img1, 0, 0, null);
|
Graphics g = img.getGraphics ();
|
||||||
rimg = new SunImageWrapper (img, g, w, h, this);
|
g.drawImage (img1, 0, 0, null);
|
||||||
|
rimg = new SunImageWrapper (img, g, w, h, this);
|
||||||
|
} finally {
|
||||||
|
loader.done();
|
||||||
|
}
|
||||||
return rimg;
|
return rimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,10 +48,14 @@ public class ImageGenerator {
|
||||||
ImageWrapper rimg = null;
|
ImageWrapper rimg = null;
|
||||||
Image img = Toolkit.getDefaultToolkit ().createImage (src);
|
Image img = Toolkit.getDefaultToolkit ().createImage (src);
|
||||||
ImageLoader loader = new ImageLoader (img);
|
ImageLoader loader = new ImageLoader (img);
|
||||||
loader.load ();
|
try {
|
||||||
int w = loader.getWidth ();
|
loader.getDimensions ();
|
||||||
int h = loader.getHeight ();
|
int w = loader.getWidth ();
|
||||||
rimg = new SunImageWrapper (img, null, w, h, this);
|
int h = loader.getHeight ();
|
||||||
|
rimg = new SunImageWrapper (img, null, w, h, this);
|
||||||
|
} finally {
|
||||||
|
loader.done();
|
||||||
|
}
|
||||||
return rimg;
|
return rimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,13 +65,17 @@ public class ImageGenerator {
|
||||||
URL url = new URL (urlstring);
|
URL url = new URL (urlstring);
|
||||||
Image img1 = Toolkit.getDefaultToolkit ().createImage (url);
|
Image img1 = Toolkit.getDefaultToolkit ().createImage (url);
|
||||||
ImageLoader loader = new ImageLoader (img1);
|
ImageLoader loader = new ImageLoader (img1);
|
||||||
loader.load ();
|
try {
|
||||||
int w = loader.getWidth ();
|
loader.getDimensions ();
|
||||||
int h = loader.getHeight ();
|
int w = loader.getWidth ();
|
||||||
Image img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
|
int h = loader.getHeight ();
|
||||||
Graphics g = img.getGraphics ();
|
Image img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
|
||||||
g.drawImage (img1, 0, 0, null);
|
Graphics g = img.getGraphics ();
|
||||||
rimg = new SunImageWrapper (img, g, w, h, this);
|
g.drawImage (img1, 0, 0, null);
|
||||||
|
rimg = new SunImageWrapper (img, g, w, h, this);
|
||||||
|
} finally {
|
||||||
|
loader.done();
|
||||||
|
}
|
||||||
return rimg;
|
return rimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,13 +84,17 @@ public class ImageGenerator {
|
||||||
FilteredImageSource fis = new FilteredImageSource (iw.getSource(), filter);
|
FilteredImageSource fis = new FilteredImageSource (iw.getSource(), filter);
|
||||||
Image img1 = Toolkit.getDefaultToolkit().createImage (fis);
|
Image img1 = Toolkit.getDefaultToolkit().createImage (fis);
|
||||||
ImageLoader loader = new ImageLoader (img1);
|
ImageLoader loader = new ImageLoader (img1);
|
||||||
loader.load ();
|
try {
|
||||||
int w = loader.getWidth ();
|
loader.getDimensions ();
|
||||||
int h = loader.getHeight ();
|
int w = loader.getWidth ();
|
||||||
Image img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
|
int h = loader.getHeight ();
|
||||||
Graphics g = img.getGraphics ();
|
Image img = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);
|
||||||
g.drawImage (img1, 0, 0, null);
|
Graphics g = img.getGraphics ();
|
||||||
rimg = new SunImageWrapper (img, g, w, h, this);
|
g.drawImage (img1, 0, 0, null);
|
||||||
|
rimg = new SunImageWrapper (img, g, w, h, this);
|
||||||
|
} finally {
|
||||||
|
loader.done();
|
||||||
|
}
|
||||||
return rimg;
|
return rimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +103,8 @@ public class ImageGenerator {
|
||||||
Image img = null;
|
Image img = null;
|
||||||
img = Toolkit.getDefaultToolkit ().createImage (filename);
|
img = Toolkit.getDefaultToolkit ().createImage (filename);
|
||||||
ImageLoader loader = new ImageLoader (img);
|
ImageLoader loader = new ImageLoader (img);
|
||||||
loader.load ();
|
loader.getDimensions ();
|
||||||
|
loader.done();
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +112,8 @@ public class ImageGenerator {
|
||||||
Image img = null;
|
Image img = null;
|
||||||
img = Toolkit.getDefaultToolkit ().createImage (producer);
|
img = Toolkit.getDefaultToolkit ().createImage (producer);
|
||||||
ImageLoader loader = new ImageLoader (img);
|
ImageLoader loader = new ImageLoader (img);
|
||||||
loader.load ();
|
loader.getDimensions ();
|
||||||
|
loader.done();
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,26 +121,27 @@ public class ImageGenerator {
|
||||||
|
|
||||||
Image img;
|
Image img;
|
||||||
int w, h;
|
int w, h;
|
||||||
|
boolean waiting;
|
||||||
|
boolean firstFrameLoaded;
|
||||||
|
|
||||||
ImageLoader (Image img) {
|
ImageLoader (Image img) {
|
||||||
this.img = img;
|
this.img = img;
|
||||||
|
waiting = true;
|
||||||
|
firstFrameLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getWidth () {
|
synchronized void getDimensions () {
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getHeight () {
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void load () {
|
|
||||||
w = img.getWidth(this);
|
w = img.getWidth(this);
|
||||||
h = img.getHeight (this);
|
h = img.getHeight (this);
|
||||||
if (w == -1 || h == -1) try {
|
if (w == -1 || h == -1) {
|
||||||
wait (30000);
|
try {
|
||||||
} catch (InterruptedException x) {
|
wait (45000);
|
||||||
return;
|
} catch (InterruptedException x) {
|
||||||
|
waiting = false;
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
waiting = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if width and height haven't been set, throw tantrum
|
// if width and height haven't been set, throw tantrum
|
||||||
if (w == -1 || h == -1) {
|
if (w == -1 || h == -1) {
|
||||||
|
@ -131,6 +149,18 @@ public class ImageGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized void done () {
|
||||||
|
waiting = false;
|
||||||
|
notifyAll ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int getWidth () {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getHeight () {
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized boolean imageUpdate(Image img,
|
public synchronized boolean imageUpdate(Image img,
|
||||||
int infoflags,
|
int infoflags,
|
||||||
|
@ -138,24 +168,24 @@ public class ImageGenerator {
|
||||||
int y,
|
int y,
|
||||||
int width,
|
int width,
|
||||||
int height) {
|
int height) {
|
||||||
if (w == -1 && (infoflags & WIDTH) > 0)
|
|
||||||
w = width;
|
|
||||||
if (h == -1 && (infoflags & HEIGHT) > 0)
|
|
||||||
h = height;
|
|
||||||
if (h > -1 && w > -1 && (infoflags & ALLBITS) > 0) {
|
|
||||||
// we know all we want to know. notify waiting thread that
|
|
||||||
// the image is loaded and ready to be used.
|
|
||||||
notifyAll ();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// check if there was an error
|
// check if there was an error
|
||||||
if ((infoflags & ERROR) > 0) {
|
if (!waiting || (infoflags & ERROR) > 0 || (infoflags & ABORT) > 0) {
|
||||||
|
// we either timed out or there was an error.
|
||||||
notifyAll ();
|
notifyAll ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// TODO: If image production was aborted, but no error was reported,
|
if ((infoflags & WIDTH) > 0 || (infoflags & HEIGHT) > 0) {
|
||||||
// we might want to start production again. For now, we just give up.
|
if ((infoflags & WIDTH) > 0)
|
||||||
if ((infoflags & ABORT) > 0) {
|
w = width;
|
||||||
|
if ((infoflags & HEIGHT) > 0)
|
||||||
|
h = height;
|
||||||
|
if (w > -1 && h > -1 && firstFrameLoaded) {
|
||||||
|
notifyAll ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((infoflags & ALLBITS) > 0 || (infoflags & FRAMEBITS) > 0) {
|
||||||
|
firstFrameLoaded = true;
|
||||||
notifyAll ();
|
notifyAll ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,12 +94,16 @@ public abstract class ImageWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resize (int w, int h) {
|
public void resize (int w, int h) {
|
||||||
// ImageFilter filter = new ReplicateScaleFilter (w, h);
|
|
||||||
// img = Toolkit.getDefaultToolkit ().createImage(new FilteredImageSource(img.getSource(), filter));
|
|
||||||
img = img.getScaledInstance (w, h, Image.SCALE_SMOOTH);
|
img = img.getScaledInstance (w, h, Image.SCALE_SMOOTH);
|
||||||
width = w;
|
width = w;
|
||||||
height = h;
|
height = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void resizeFast (int w, int h) {
|
||||||
|
img = img.getScaledInstance (w, h, Image.SCALE_FAST);
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void reduceColors (int colors);
|
public abstract void reduceColors (int colors);
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import org.apache.xmlrpc.*;
|
||||||
|
|
||||||
public class Server implements IPathElement, Runnable {
|
public class Server implements IPathElement, Runnable {
|
||||||
|
|
||||||
public static final String version = "1.2 RC2 2002/12/05";
|
public static final String version = "1.2.2 (2003/02/04)";
|
||||||
public final long starttime;
|
public final long starttime;
|
||||||
|
|
||||||
// if true we only accept RMI and XML-RPC connections from
|
// if true we only accept RMI and XML-RPC connections from
|
||||||
|
@ -90,6 +90,9 @@ import org.apache.xmlrpc.*;
|
||||||
|
|
||||||
// create new server instance
|
// create new server instance
|
||||||
server = new Server (args);
|
server = new Server (args);
|
||||||
|
|
||||||
|
// start the server main thread
|
||||||
|
server.start ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,8 +140,13 @@ import org.apache.xmlrpc.*;
|
||||||
} catch (Exception portx) {
|
} catch (Exception portx) {
|
||||||
usageError = true;
|
usageError = true;
|
||||||
}
|
}
|
||||||
} else
|
} else if (args[i].equals ("-i") && i+1<args.length) {
|
||||||
|
// eat away the -i parameter which is meant for helma.main.launcher.Main
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
System.err.println ("Unknown command line token: "+args[i]);
|
||||||
usageError = true;
|
usageError = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get main property file from home dir or vice versa, depending on what we have.
|
// get main property file from home dir or vice versa, depending on what we have.
|
||||||
|
@ -291,12 +299,18 @@ import org.apache.xmlrpc.*;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void start () {
|
||||||
// Start running, finishing setup and then entering a loop to check changes
|
// Start running, finishing setup and then entering a loop to check changes
|
||||||
// in the apps.properties file.
|
// in the apps.properties file.
|
||||||
mainThread = new Thread (this);
|
mainThread = new Thread (this);
|
||||||
mainThread.start ();
|
mainThread.start ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void stop () {
|
||||||
|
mainThread = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main method of the Server. Basically, we set up Applications and than
|
* The main method of the Server. Basically, we set up Applications and than
|
||||||
|
|
|
@ -4,6 +4,7 @@ package helma.main.launcher;
|
||||||
|
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.net.URLDecoder;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
@ -16,10 +17,20 @@ import java.security.Policy;
|
||||||
*/
|
*/
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
public static final String[] jars = { "helma.jar", "jetty.jar", "crimson.jar", "xmlrpc.jar",
|
public static final String[] jars = {
|
||||||
"village.jar", "servlet.jar", "regexp.jar", "mail.jar",
|
"helma.jar",
|
||||||
"activation.jar", "netcomponents.jar", "jimi.jar",
|
"jetty.jar",
|
||||||
"apache-dom.jar", "jdom.jar"};
|
"crimson.jar",
|
||||||
|
"xmlrpc.jar",
|
||||||
|
"servlet.jar",
|
||||||
|
"regexp.jar",
|
||||||
|
"mail.jar",
|
||||||
|
"activation.jar",
|
||||||
|
"netcomponents.jar",
|
||||||
|
"jimi.jar",
|
||||||
|
"apache-dom.jar",
|
||||||
|
"jdom.jar"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
public static void main (String[] args) throws Exception {
|
public static void main (String[] args) throws Exception {
|
||||||
|
@ -54,9 +65,13 @@ public class Main {
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
// unable to get Helma installation dir from launcher jar
|
// unable to get Helma installation dir from launcher jar
|
||||||
System.err.println ("Unable to get Helma installation directory: "+x);
|
System.err.println ("Unable to get Helma installation directory: "+x);
|
||||||
|
System.exit (2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decode installDir in case it is URL-encoded
|
||||||
|
installDir = URLDecoder.decode (installDir);
|
||||||
|
|
||||||
// set up the class path
|
// set up the class path
|
||||||
File libdir = new File (installDir, "lib");
|
File libdir = new File (installDir, "lib");
|
||||||
ArrayList jarlist = new ArrayList ();
|
ArrayList jarlist = new ArrayList ();
|
||||||
|
@ -68,17 +83,20 @@ public class Main {
|
||||||
File extdir =new File (libdir, "ext");
|
File extdir =new File (libdir, "ext");
|
||||||
File[] files = extdir.listFiles (new FilenameFilter() {
|
File[] files = extdir.listFiles (new FilenameFilter() {
|
||||||
public boolean accept (File dir, String name) {
|
public boolean accept (File dir, String name) {
|
||||||
return name.toLowerCase().endsWith (".jar");
|
String n = name.toLowerCase();
|
||||||
|
return n.endsWith (".jar") || n.endsWith (".zip");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (files != null)
|
if (files != null)
|
||||||
for (int i=0;i<files.length; i++)
|
for (int i=0;i<files.length; i++) {
|
||||||
// WORKAROUND: add the files in lib/ext before
|
// WORKAROUND: add the files in lib/ext before
|
||||||
// lib/apache-dom.jar, since otherwise putting a full version
|
// lib/apache-dom.jar, since otherwise putting a full version
|
||||||
// of Xerces in lib/ext would cause a version conflict with the
|
// of Xerces in lib/ext would cause a version conflict with the
|
||||||
// xerces classes in lib/apache-dom.jar. Generally, having some pieces
|
// xerces classes in lib/apache-dom.jar. Generally, having some pieces
|
||||||
// of Xerces in lib/apache-dom.jar is kind of problematic.
|
// of Xerces in lib/apache-dom.jar is kind of problematic.
|
||||||
jarlist.add (jars.length-3, new URL ("file:" + files[i].getAbsolutePath()));
|
jarlist.add (jars.length-3, new URL ("file:" + files[i].getAbsolutePath()));
|
||||||
|
System.err.println ("Adding to classpath: "+files[i].getAbsolutePath());
|
||||||
|
}
|
||||||
URL[] urls = new URL[jarlist.size()];
|
URL[] urls = new URL[jarlist.size()];
|
||||||
jarlist.toArray (urls);
|
jarlist.toArray (urls);
|
||||||
FilteredClassLoader loader = new FilteredClassLoader (urls);
|
FilteredClassLoader loader = new FilteredClassLoader (urls);
|
||||||
|
|
|
@ -64,7 +64,7 @@ public final class Property implements IProperty, Serializable {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStringValue (String value) throws ParseException {
|
public void setStringValue (String value) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
this.nvalue = null;
|
this.nvalue = null;
|
||||||
if (type == JAVAOBJECT)
|
if (type == JAVAOBJECT)
|
||||||
|
@ -116,6 +116,7 @@ public final class Property implements IProperty, Serializable {
|
||||||
this.nvalue = value;
|
this.nvalue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setJavaObjectValue (Object value) {
|
public void setJavaObjectValue (Object value) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
this.nvalue = null;
|
this.nvalue = null;
|
||||||
|
@ -124,7 +125,6 @@ public final class Property implements IProperty, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getStringValue () {
|
public String getStringValue () {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case STRING:
|
case STRING:
|
||||||
|
@ -151,32 +151,32 @@ public final class Property implements IProperty, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getIntegerValue () {
|
public long getIntegerValue () {
|
||||||
if (type == INTEGER)
|
if (type == INTEGER)
|
||||||
return lvalue;
|
return lvalue;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getFloatValue () {
|
public double getFloatValue () {
|
||||||
if (type == FLOAT)
|
if (type == FLOAT)
|
||||||
return dvalue;
|
return dvalue;
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Date getDateValue () {
|
public Date getDateValue () {
|
||||||
if (type == DATE)
|
if (type == DATE)
|
||||||
return new Date (lvalue);
|
return new Date (lvalue);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getBooleanValue () {
|
public boolean getBooleanValue () {
|
||||||
if (type == BOOLEAN)
|
if (type == BOOLEAN)
|
||||||
return bvalue;
|
return bvalue;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public INode getNodeValue () {
|
public INode getNodeValue () {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
return nvalue;
|
return nvalue;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -469,12 +469,8 @@ public class TransientNode implements INode, Serializable {
|
||||||
public void setString (String propname, String value) {
|
public void setString (String propname, String value) {
|
||||||
// IServer.getLogger().log ("setting String prop");
|
// IServer.getLogger().log ("setting String prop");
|
||||||
Property prop = initProperty (propname);
|
Property prop = initProperty (propname);
|
||||||
try {
|
prop.setStringValue (value);
|
||||||
prop.setStringValue (value);
|
// Server.throwNodeEvent (new NodeEvent (this, NodeEvent.PROPERTIES_CHANGED));
|
||||||
// Server.throwNodeEvent (new NodeEvent (this, NodeEvent.PROPERTIES_CHANGED));
|
|
||||||
} catch (java.text.ParseException x) {
|
|
||||||
throw new RuntimeException ("Fehler beim Parsen des Datum-Strings");
|
|
||||||
}
|
|
||||||
lastmodified = System.currentTimeMillis ();
|
lastmodified = System.currentTimeMillis ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ public final class DbColumn {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.relation = rel;
|
this.relation = rel;
|
||||||
|
if (relation != null)
|
||||||
|
relation.setColumnType (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,4 +45,4 @@ public final class DbColumn {
|
||||||
return relation;
|
return relation;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import java.util.Enumeration;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import com.workingdogs.village.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A DbMapping describes how a certain type of Nodes is to mapped to a
|
* A DbMapping describes how a certain type of Nodes is to mapped to a
|
||||||
|
@ -58,8 +57,11 @@ public final class DbMapping implements Updatable {
|
||||||
DbColumn[] columns = null;
|
DbColumn[] columns = null;
|
||||||
// Map of db columns by name
|
// Map of db columns by name
|
||||||
HashMap columnMap;
|
HashMap columnMap;
|
||||||
|
|
||||||
// pre-rendered select statement
|
// pre-rendered select statement
|
||||||
String select = null;
|
String selectString = null;
|
||||||
|
String insertString = null;
|
||||||
|
String updateString = null;
|
||||||
|
|
||||||
// db field used as primary key
|
// db field used as primary key
|
||||||
private String idField;
|
private String idField;
|
||||||
|
@ -81,13 +83,10 @@ public final class DbMapping implements Updatable {
|
||||||
// remember last key generated for this table
|
// remember last key generated for this table
|
||||||
long lastID;
|
long lastID;
|
||||||
|
|
||||||
// the (village) schema of the database table
|
|
||||||
Schema schema = null;
|
|
||||||
// the (village) keydef of the db table
|
|
||||||
KeyDef keydef = null;
|
|
||||||
|
|
||||||
// timestamp of last modification of the mapping (type.properties)
|
// timestamp of last modification of the mapping (type.properties)
|
||||||
long lastTypeChange;
|
// init value is -1 so we know we have to run update once even if
|
||||||
|
// the underlying properties file is non-existent
|
||||||
|
long lastTypeChange = -1;
|
||||||
// timestamp of last modification of an object of this type
|
// timestamp of last modification of an object of this type
|
||||||
long lastDataChange;
|
long lastDataChange;
|
||||||
|
|
||||||
|
@ -188,13 +187,10 @@ public final class DbMapping implements Updatable {
|
||||||
}
|
}
|
||||||
|
|
||||||
lastTypeChange = props.lastModified ();
|
lastTypeChange = props.lastModified ();
|
||||||
// null the cached schema & keydef so it's rebuilt the next time around
|
// null the cached columns and select string
|
||||||
schema = null;
|
|
||||||
keydef = null;
|
|
||||||
// same with columns and select string
|
|
||||||
columns = null;
|
columns = null;
|
||||||
columnMap.clear();
|
columnMap.clear();
|
||||||
select = null;
|
selectString = insertString = updateString = null;
|
||||||
|
|
||||||
|
|
||||||
if (extendsProto != null) {
|
if (extendsProto != null) {
|
||||||
|
@ -390,7 +386,9 @@ public final class DbMapping implements Updatable {
|
||||||
return null;
|
return null;
|
||||||
if (table == null && parentMapping != null)
|
if (table == null && parentMapping != null)
|
||||||
return parentMapping.propertyToColumnName (propName);
|
return parentMapping.propertyToColumnName (propName);
|
||||||
Relation rel = (Relation) prop2db.get (propName);
|
// FIXME: prop2db stores keys in lower case, because it gets them
|
||||||
|
// from a SystemProperties object which converts keys to lower case.
|
||||||
|
Relation rel = (Relation) prop2db.get (propName.toLowerCase());
|
||||||
if (rel != null && (rel.reftype == Relation.PRIMITIVE || rel.reftype == Relation.REFERENCE))
|
if (rel != null && (rel.reftype == Relation.PRIMITIVE || rel.reftype == Relation.REFERENCE))
|
||||||
return rel.columnName;
|
return rel.columnName;
|
||||||
return null;
|
return null;
|
||||||
|
@ -415,7 +413,9 @@ public final class DbMapping implements Updatable {
|
||||||
return null;
|
return null;
|
||||||
if (table == null && parentMapping != null)
|
if (table == null && parentMapping != null)
|
||||||
return parentMapping.propertyToRelation (propName);
|
return parentMapping.propertyToRelation (propName);
|
||||||
return (Relation) prop2db.get (propName);
|
// FIXME: prop2db stores keys in lower case, because it gets them
|
||||||
|
// from a SystemProperties object which converts keys to lower case.
|
||||||
|
return (Relation) prop2db.get (propName.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -558,22 +558,6 @@ public final class DbMapping implements Updatable {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Village Schema object for this DbMapping.
|
|
||||||
*/
|
|
||||||
public synchronized Schema getSchema () throws ClassNotFoundException, SQLException, DataSetException {
|
|
||||||
if (!isRelational ())
|
|
||||||
throw new SQLException ("Can't get Schema for non-relational data mapping");
|
|
||||||
if (source == null && parentMapping != null)
|
|
||||||
return parentMapping.getSchema ();
|
|
||||||
// Use local variable s to avoid synchronization (schema may be nulled elsewhere)
|
|
||||||
Schema s = schema;
|
|
||||||
if (s != null)
|
|
||||||
return s;
|
|
||||||
schema = new Schema ().schema (getConnection (), table, "*");
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of DbColumns for the relational table mapped by this DbMapping.
|
* Return an array of DbColumns for the relational table mapped by this DbMapping.
|
||||||
|
@ -630,14 +614,40 @@ public final class DbMapping implements Updatable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringBuffer getSelect () throws SQLException, ClassNotFoundException {
|
public StringBuffer getSelect () throws SQLException, ClassNotFoundException {
|
||||||
String sel = select;
|
String sel = selectString;
|
||||||
if (sel != null)
|
if (sel != null)
|
||||||
return new StringBuffer (sel);
|
return new StringBuffer (sel);
|
||||||
StringBuffer s = new StringBuffer ("SELECT * FROM ");
|
StringBuffer s = new StringBuffer ("SELECT * FROM ");
|
||||||
s.append (getTableName ());
|
s.append (getTableName ());
|
||||||
s.append (" ");
|
s.append (" ");
|
||||||
// cache rendered string for later calls.
|
// cache rendered string for later calls.
|
||||||
select = s.toString();
|
selectString = s.toString();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public StringBuffer getInsert () {
|
||||||
|
String ins = insertString;
|
||||||
|
if (ins != null)
|
||||||
|
return new StringBuffer (ins);
|
||||||
|
StringBuffer s = new StringBuffer ("INSERT INTO ");
|
||||||
|
s.append (getTableName ());
|
||||||
|
s.append (" ( ");
|
||||||
|
s.append (getIDField());
|
||||||
|
// cache rendered string for later calls.
|
||||||
|
insertString = s.toString();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuffer getUpdate () {
|
||||||
|
String upd = updateString;
|
||||||
|
if (upd != null)
|
||||||
|
return new StringBuffer (upd);
|
||||||
|
StringBuffer s = new StringBuffer ("UPDATE ");
|
||||||
|
s.append (getTableName ());
|
||||||
|
s.append (" SET ");
|
||||||
|
// cache rendered string for later calls.
|
||||||
|
updateString = s.toString();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,21 +679,6 @@ public final class DbMapping implements Updatable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Village Schema object for this DbMapping.
|
|
||||||
*/
|
|
||||||
public synchronized KeyDef getKeyDef () {
|
|
||||||
if (!isRelational ())
|
|
||||||
throw new RuntimeException ("Can't get KeyDef for non-relational data mapping");
|
|
||||||
if (source == null && parentMapping != null)
|
|
||||||
return parentMapping.getKeyDef ();
|
|
||||||
// Use local variable s to avoid synchronization (keydef may be nulled elsewhere)
|
|
||||||
KeyDef k = keydef;
|
|
||||||
if (k != null)
|
|
||||||
return k;
|
|
||||||
keydef = new KeyDef ().addAttrib (getIDField ());
|
|
||||||
return keydef;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
if (typename == null)
|
if (typename == null)
|
||||||
|
|
|
@ -179,7 +179,7 @@ public final class Node implements INode, Serializable {
|
||||||
*/
|
*/
|
||||||
public Node (String name, String id, String prototype, WrappedNodeManager nmgr) {
|
public Node (String name, String id, String prototype, WrappedNodeManager nmgr) {
|
||||||
this.nmgr = nmgr;
|
this.nmgr = nmgr;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name == null || "".equals (name) ? id : name;
|
this.name = name == null || "".equals (name) ? id : name;
|
||||||
if (prototype != null)
|
if (prototype != null)
|
||||||
setPrototype (prototype);
|
setPrototype (prototype);
|
||||||
|
@ -235,7 +235,7 @@ public final class Node implements INode, Serializable {
|
||||||
* Constructor used for nodes being stored in a relational database table.
|
* Constructor used for nodes being stored in a relational database table.
|
||||||
*/
|
*/
|
||||||
public Node (DbMapping dbm, ResultSet rs, DbColumn[] columns, WrappedNodeManager nmgr)
|
public Node (DbMapping dbm, ResultSet rs, DbColumn[] columns, WrappedNodeManager nmgr)
|
||||||
throws SQLException {
|
throws SQLException, IOException {
|
||||||
|
|
||||||
this.nmgr = nmgr;
|
this.nmgr = nmgr;
|
||||||
// see what prototype/DbMapping this object should use
|
// see what prototype/DbMapping this object should use
|
||||||
|
@ -302,13 +302,32 @@ public final class Node implements INode, Serializable {
|
||||||
newprop.setIntegerValue (num.longValue ());
|
newprop.setIntegerValue (num.longValue ());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Types.LONGVARBINARY:
|
|
||||||
case Types.VARBINARY:
|
case Types.VARBINARY:
|
||||||
case Types.BINARY:
|
case Types.BINARY:
|
||||||
newprop.setStringValue (rs.getString(columns[i].getName()));
|
newprop.setStringValue (rs.getString(columns[i].getName()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Types.LONGVARBINARY:
|
||||||
case Types.LONGVARCHAR:
|
case Types.LONGVARCHAR:
|
||||||
|
try {
|
||||||
|
newprop.setStringValue (rs.getString(columns[i].getName()));
|
||||||
|
} catch (SQLException x) {
|
||||||
|
Reader in = rs.getCharacterStream(columns[i].getName());
|
||||||
|
char[] buffer = new char[2048];
|
||||||
|
int read = 0, r = 0;
|
||||||
|
while ((r = in.read (buffer, read, buffer.length-read)) > -1) {
|
||||||
|
read += r;
|
||||||
|
if (read == buffer.length) {
|
||||||
|
// grow input buffer
|
||||||
|
char[] newBuffer = new char[buffer.length*2];
|
||||||
|
System.arraycopy (buffer, 0, newBuffer, 0, buffer.length);
|
||||||
|
buffer = newBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newprop.setStringValue (new String(buffer, 0, read));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case Types.CHAR:
|
case Types.CHAR:
|
||||||
case Types.VARCHAR:
|
case Types.VARCHAR:
|
||||||
case Types.OTHER:
|
case Types.OTHER:
|
||||||
|
@ -435,9 +454,9 @@ public final class Node implements INode, Serializable {
|
||||||
Relation rel = getDbMapping ().getSubnodeRelation ();
|
Relation rel = getDbMapping ().getSubnodeRelation ();
|
||||||
if (rel != null) {
|
if (rel != null) {
|
||||||
if (rel.usesPrimaryKey()) {
|
if (rel.usesPrimaryKey()) {
|
||||||
nmgr.evictKey (new DbKey (getDbMapping().getSubnodeMapping(), key));
|
nmgr.evictNodeByKey (new DbKey (getDbMapping().getSubnodeMapping(), key));
|
||||||
} else {
|
} else {
|
||||||
nmgr.evictKey (new SyntheticKey (getKey(), key));
|
nmgr.evictNodeByKey (new SyntheticKey (getKey(), key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -493,7 +512,7 @@ public final class Node implements INode, Serializable {
|
||||||
} else {
|
} else {
|
||||||
anonymous = true;
|
anonymous = true;
|
||||||
}
|
}
|
||||||
} else if (p.contains (this) > -1) {
|
} else if (!anonymous && p.contains (this) > -1) {
|
||||||
anonymous = true;
|
anonymous = true;
|
||||||
}
|
}
|
||||||
} catch (Exception ignore) {
|
} catch (Exception ignore) {
|
||||||
|
@ -873,13 +892,13 @@ public final class Node implements INode, Serializable {
|
||||||
|
|
||||||
public INode createNode (String nm, int where) {
|
public INode createNode (String nm, int where) {
|
||||||
checkWriteLock ();
|
checkWriteLock ();
|
||||||
boolean anon = false;
|
boolean anon = false;
|
||||||
if (nm == null || "".equals (nm.trim ()))
|
if (nm == null || "".equals (nm.trim ()))
|
||||||
anon = true;
|
anon = true;
|
||||||
Node n = new Node (nm, null, nmgr);
|
Node n = new Node (nm, null, nmgr);
|
||||||
if (anon)
|
if (anon)
|
||||||
addNode (n, where);
|
addNode (n, where);
|
||||||
else
|
else
|
||||||
setNode (nm, n);
|
setNode (nm, n);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
@ -917,7 +936,7 @@ public final class Node implements INode, Serializable {
|
||||||
if (rel.otherType != null && rel.otherType.isRelational ())
|
if (rel.otherType != null && rel.otherType.isRelational ())
|
||||||
return (IPathElement) nmgr.getNode (this, name, rel);
|
return (IPathElement) nmgr.getNode (this, name, rel);
|
||||||
else
|
else
|
||||||
return (IPathElement) getNode (name);
|
return (IPathElement) getNode (name);
|
||||||
}
|
}
|
||||||
return (IPathElement) getSubnode (name);
|
return (IPathElement) getSubnode (name);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1748,11 +1767,20 @@ public final class Node implements INode, Serializable {
|
||||||
if (propMap == null)
|
if (propMap == null)
|
||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
Property p = (Property) propMap.remove (propname.toLowerCase ());
|
// if node is relational, leave a null property so that it is
|
||||||
|
// updated in the DB. Otherwise, remove the property.
|
||||||
|
Property p;
|
||||||
|
boolean relational = dbmap != null && dbmap.isRelational();
|
||||||
|
if (relational)
|
||||||
|
p = (Property) propMap.get (propname.toLowerCase ());
|
||||||
|
else
|
||||||
|
p = (Property) propMap.remove (propname.toLowerCase ());
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
checkWriteLock ();
|
checkWriteLock ();
|
||||||
if (p.getType() == Property.NODE)
|
if (p.getType() == Property.NODE)
|
||||||
p.unregisterNode ();
|
p.unregisterNode ();
|
||||||
|
if (relational)
|
||||||
|
p.setStringValue (null);
|
||||||
// Server.throwNodeEvent (new NodeEvent (this, NodeEvent.PROPERTIES_CHANGED));
|
// Server.throwNodeEvent (new NodeEvent (this, NodeEvent.PROPERTIES_CHANGED));
|
||||||
lastmodified = System.currentTimeMillis ();
|
lastmodified = System.currentTimeMillis ();
|
||||||
if (state == CLEAN)
|
if (state == CLEAN)
|
||||||
|
|
|
@ -9,7 +9,6 @@ import helma.framework.core.Application;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import com.workingdogs.village.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The NodeManager is responsible for fetching Nodes from the internal or
|
* The NodeManager is responsible for fetching Nodes from the internal or
|
||||||
|
@ -360,8 +359,8 @@ public final class NodeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a node from the node cache. If at a later time it is accessed again, it will be
|
* Remove a node from the node cache. If at a later time it is accessed again,
|
||||||
* refetched from the database.
|
* it will be refetched from the database.
|
||||||
*/
|
*/
|
||||||
public void evictNode (Node node) {
|
public void evictNode (Node node) {
|
||||||
node.setState (INode.INVALID);
|
node.setState (INode.INVALID);
|
||||||
|
@ -369,7 +368,21 @@ public final class NodeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used when a key stops being valid for a node.
|
* Remove a node from the node cache. If at a later time it is accessed again,
|
||||||
|
* it will be refetched from the database.
|
||||||
|
*/
|
||||||
|
public void evictNodeByKey (Key key) {
|
||||||
|
Node n = (Node) cache.remove (key);
|
||||||
|
if (n != null) {
|
||||||
|
n.setState (INode.INVALID);
|
||||||
|
if (!(key instanceof DbKey))
|
||||||
|
cache.remove (n.getKey ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used when a key stops being valid for a node. The cached node itself
|
||||||
|
* remains valid, if it is present in the cache by other keys.
|
||||||
*/
|
*/
|
||||||
public void evictKey (Key key) {
|
public void evictKey (Key key) {
|
||||||
cache.remove (key);
|
cache.remove (key);
|
||||||
|
@ -396,62 +409,129 @@ public final class NodeManager {
|
||||||
db.saveNode (txn, node.getID (), node);
|
db.saveNode (txn, node.getID (), node);
|
||||||
} else {
|
} else {
|
||||||
// app.logEvent ("inserting relational node: "+node.getID ());
|
// app.logEvent ("inserting relational node: "+node.getID ());
|
||||||
TableDataSet tds = null;
|
|
||||||
|
DbColumn[] columns = dbm.getColumns ();
|
||||||
|
|
||||||
|
StringBuffer b1 = dbm.getInsert ();
|
||||||
|
StringBuffer b2 = new StringBuffer (" ) VALUES ( ?");
|
||||||
|
|
||||||
|
String nameField = dbm.getNameField ();
|
||||||
|
String prototypeField = dbm.getPrototypeField ();
|
||||||
|
|
||||||
|
for (int i=0; i<columns.length; i++) {
|
||||||
|
Relation rel = columns[i].getRelation();
|
||||||
|
String name = columns[i].getName();
|
||||||
|
if ((rel != null && (rel.isPrimitive() || rel.isReference())) ||
|
||||||
|
name.equals (nameField) || name.equals (prototypeField))
|
||||||
|
{
|
||||||
|
b1.append (", "+columns[i].getName());
|
||||||
|
b2.append (", ?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b1.append (b2.toString());
|
||||||
|
b1.append (" )");
|
||||||
|
|
||||||
|
Connection con = dbm.getConnection ();
|
||||||
|
PreparedStatement stmt = con.prepareStatement (b1.toString ());
|
||||||
|
|
||||||
|
if (logSql)
|
||||||
|
app.logEvent ("### insertNode: "+b1.toString ());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tds = new TableDataSet (dbm.getConnection (), dbm.getSchema (), dbm.getKeyDef ());
|
|
||||||
Record rec = tds.addRecord ();
|
|
||||||
rec.setValue (dbm.getIDField (), node.getID ());
|
|
||||||
|
|
||||||
String nameField = dbm.getNameField ();
|
int stmtNumber = 1;
|
||||||
if (nameField != null)
|
stmt.setString (stmtNumber, node.getID());
|
||||||
rec.setValue (nameField, node.getName ());
|
|
||||||
|
|
||||||
for (Iterator i=dbm.getProp2DB().entrySet().iterator(); i.hasNext(); ) {
|
Hashtable propMap = node.getPropMap ();
|
||||||
Map.Entry e = (Map.Entry) i.next ();
|
for (int i=0; i<columns.length; i++) {
|
||||||
String propname = (String) e.getKey ();
|
Relation rel = columns[i].getRelation();
|
||||||
Relation rel = (Relation) e.getValue ();
|
Property p = null;
|
||||||
Property p = node.getProperty (propname);
|
if (rel != null && (rel.isPrimitive() || rel.isReference()))
|
||||||
|
p = (Property) propMap.get (rel.getPropName ());
|
||||||
|
String name = columns[i].getName ();
|
||||||
|
if (!(rel != null && (rel.isPrimitive() || rel.isReference())) && !name.equals (nameField) && !name.equals (prototypeField))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (p != null && rel != null) {
|
stmtNumber++;
|
||||||
switch (p.getType ()) {
|
if (p != null) {
|
||||||
case IProperty.STRING:
|
if (p.getValue() == null) {
|
||||||
rec.setValue (rel.getDbField(), p.getStringValue ());
|
stmt.setNull (stmtNumber, columns[i].getType ());
|
||||||
break;
|
} else {
|
||||||
case IProperty.BOOLEAN:
|
switch (columns[i].getType ()) {
|
||||||
rec.setValue (rel.getDbField(), p.getBooleanValue ());
|
|
||||||
break;
|
case Types.BIT:
|
||||||
case IProperty.DATE:
|
case Types.TINYINT:
|
||||||
Timestamp t = new Timestamp (p.getDateValue ().getTime ());
|
case Types.BIGINT:
|
||||||
rec.setValue (rel.getDbField(), t);
|
case Types.SMALLINT:
|
||||||
break;
|
case Types.INTEGER:
|
||||||
case IProperty.INTEGER:
|
stmt.setLong (stmtNumber, p.getIntegerValue());
|
||||||
rec.setValue (rel.getDbField(), p.getIntegerValue ());
|
break;
|
||||||
break;
|
|
||||||
case IProperty.FLOAT:
|
case Types.REAL:
|
||||||
rec.setValue (rel.getDbField(), p.getFloatValue ());
|
case Types.FLOAT:
|
||||||
break;
|
case Types.DOUBLE:
|
||||||
case IProperty.NODE:
|
case Types.NUMERIC:
|
||||||
if (rel.reftype == Relation.REFERENCE) {
|
case Types.DECIMAL:
|
||||||
// INode n = p.getNodeValue ();
|
stmt.setDouble (stmtNumber, p.getFloatValue());
|
||||||
// String foreignID = n == null ? null : n.getID ();
|
break;
|
||||||
rec.setValue (rel.getDbField(), p.getStringValue ());
|
|
||||||
}
|
case Types.VARBINARY:
|
||||||
break;
|
case Types.BINARY:
|
||||||
|
case Types.BLOB:
|
||||||
|
stmt.setString (stmtNumber, p.getStringValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Types.LONGVARBINARY:
|
||||||
|
case Types.LONGVARCHAR:
|
||||||
|
try {
|
||||||
|
stmt.setString (stmtNumber, p.getStringValue());
|
||||||
|
} catch (SQLException x) {
|
||||||
|
String str = p.getStringValue();
|
||||||
|
Reader r = new StringReader (str);
|
||||||
|
stmt.setCharacterStream (stmtNumber, r, str.length());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Types.CHAR:
|
||||||
|
case Types.VARCHAR:
|
||||||
|
case Types.OTHER:
|
||||||
|
stmt.setString (stmtNumber, p.getStringValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Types.DATE:
|
||||||
|
case Types.TIME:
|
||||||
|
case Types.TIMESTAMP:
|
||||||
|
stmt.setTimestamp (stmtNumber, p.getTimestampValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Types.NULL:
|
||||||
|
stmt.setNull (stmtNumber, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
stmt.setString (stmtNumber, p.getStringValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.dirty = false;
|
} else {
|
||||||
} else if (rel != null && rel.getDbField() != null) {
|
if (name.equals (nameField))
|
||||||
rec.setValueNull (rel.getDbField());
|
stmt.setString (stmtNumber, node.getName());
|
||||||
|
else if (name.equals (prototypeField))
|
||||||
|
stmt.setString (stmtNumber, node.getPrototype ());
|
||||||
|
else
|
||||||
|
stmt.setNull (stmtNumber, columns[i].getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stmt.executeUpdate ();
|
||||||
if (dbm.getPrototypeField () != null) {
|
|
||||||
rec.setValue (dbm.getPrototypeField (), node.getPrototype ());
|
|
||||||
}
|
} catch (Exception x) {
|
||||||
rec.markForInsert ();
|
x.printStackTrace ();
|
||||||
tds.save ();
|
throw x;
|
||||||
} finally {
|
} finally {
|
||||||
if (tds != null) try {
|
if (stmt != null) try {
|
||||||
tds.close ();
|
stmt.close ();
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
dbm.notifyDataChange ();
|
dbm.notifyDataChange ();
|
||||||
|
@ -475,82 +555,146 @@ public final class NodeManager {
|
||||||
db.saveNode (txn, node.getID (), node);
|
db.saveNode (txn, node.getID (), node);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
TableDataSet tds = null;
|
Hashtable propMap = node.getPropMap ();
|
||||||
|
Property[] props = new Property[propMap.size()];
|
||||||
|
propMap.values().toArray (props);
|
||||||
|
|
||||||
|
// make sure table meta info is loaded by dbmapping
|
||||||
|
dbm.getColumns ();
|
||||||
|
|
||||||
|
StringBuffer b = dbm.getUpdate ();
|
||||||
|
|
||||||
|
boolean comma = false;
|
||||||
|
for (int i=0; i<props.length; i++) {
|
||||||
|
// skip clean properties
|
||||||
|
if (props[i] == null || !props[i].dirty) {
|
||||||
|
// null out clean property so we don't consider it later
|
||||||
|
props[i] = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Relation rel = dbm.propertyToRelation (props[i].getName());
|
||||||
|
// skip readonly, virtual and collection relations
|
||||||
|
if (rel == null || rel.readonly || rel.virtual ||
|
||||||
|
(rel.reftype != Relation.REFERENCE && rel.reftype != Relation.PRIMITIVE))
|
||||||
|
{
|
||||||
|
// null out property so we don't consider it later
|
||||||
|
props[i] = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (comma)
|
||||||
|
b.append (", ");
|
||||||
|
else
|
||||||
|
comma = true;
|
||||||
|
b.append (rel.getDbField());
|
||||||
|
b.append (" = ?");
|
||||||
|
|
||||||
|
}
|
||||||
|
// if no columns were updated, return
|
||||||
|
if (!comma)
|
||||||
|
return;
|
||||||
|
|
||||||
|
b.append (" WHERE ");
|
||||||
|
b.append (dbm.getIDField ());
|
||||||
|
b.append (" = ");
|
||||||
|
if (dbm.needsQuotes (dbm.getIDField ())) {
|
||||||
|
b.append ("'");
|
||||||
|
b.append (escape(node.getID()));
|
||||||
|
b.append ("'");
|
||||||
|
} else {
|
||||||
|
b.append (node.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection con = dbm.getConnection ();
|
||||||
|
PreparedStatement stmt = con.prepareStatement (b.toString ());
|
||||||
|
|
||||||
|
if (logSql)
|
||||||
|
app.logEvent ("### updateNode: "+b.toString ());
|
||||||
|
|
||||||
|
int stmtNumber = 0;
|
||||||
try {
|
try {
|
||||||
tds = new TableDataSet (dbm.getConnection (), dbm.getSchema (), dbm.getKeyDef ());
|
for (int i=0; i<props.length; i++) {
|
||||||
Record rec = tds.addRecord ();
|
Property p = props[i];
|
||||||
rec.setValue (dbm.getIDField (), node.getID ());
|
if (p == null)
|
||||||
|
|
||||||
int updated = 0;
|
|
||||||
|
|
||||||
for (Iterator i=dbm.getProp2DB().entrySet().iterator(); i.hasNext(); ) {
|
|
||||||
Map.Entry e = (Map.Entry) i.next ();
|
|
||||||
String propname = (String) e.getKey ();
|
|
||||||
Relation rel = (Relation) e.getValue ();
|
|
||||||
|
|
||||||
// skip properties that don't need to be updated before fetching them
|
|
||||||
if (rel != null && (rel.readonly || rel.virtual ||
|
|
||||||
(rel.reftype != Relation.REFERENCE && rel.reftype != Relation.PRIMITIVE)))
|
|
||||||
continue;
|
continue;
|
||||||
|
Relation rel = dbm.propertyToRelation (p.getName());
|
||||||
|
|
||||||
Property p = node.getProperty (propname);
|
stmtNumber++;
|
||||||
|
|
||||||
if (p != null && rel != null) {
|
if (p.getValue() == null) {
|
||||||
|
stmt.setNull (stmtNumber, rel.getColumnType ());
|
||||||
|
} else {
|
||||||
|
switch (rel.getColumnType ()) {
|
||||||
|
case Types.BIT:
|
||||||
|
case Types.TINYINT:
|
||||||
|
case Types.BIGINT:
|
||||||
|
case Types.SMALLINT:
|
||||||
|
case Types.INTEGER:
|
||||||
|
stmt.setLong (stmtNumber, p.getIntegerValue());
|
||||||
|
break;
|
||||||
|
|
||||||
if (p.dirty) {
|
case Types.REAL:
|
||||||
switch (p.getType ()) {
|
case Types.FLOAT:
|
||||||
case IProperty.STRING:
|
case Types.DOUBLE:
|
||||||
updated++;
|
case Types.NUMERIC:
|
||||||
rec.setValue (rel.getDbField(), p.getStringValue ());
|
case Types.DECIMAL:
|
||||||
break;
|
stmt.setDouble (stmtNumber, p.getFloatValue());
|
||||||
case IProperty.BOOLEAN:
|
break;
|
||||||
updated++;
|
|
||||||
rec.setValue (rel.getDbField(), p.getBooleanValue ());
|
case Types.VARBINARY:
|
||||||
break;
|
case Types.BINARY:
|
||||||
case IProperty.DATE:
|
case Types.BLOB:
|
||||||
updated++;
|
stmt.setString (stmtNumber, p.getStringValue());
|
||||||
Timestamp t = new Timestamp (p.getDateValue ().getTime ());
|
break;
|
||||||
rec.setValue (rel.getDbField(), t);
|
|
||||||
break;
|
case Types.LONGVARBINARY:
|
||||||
case IProperty.INTEGER:
|
case Types.LONGVARCHAR:
|
||||||
updated++;
|
try {
|
||||||
rec.setValue (rel.getDbField(), p.getIntegerValue ());
|
stmt.setString (stmtNumber, p.getStringValue());
|
||||||
break;
|
} catch (SQLException x) {
|
||||||
case IProperty.FLOAT:
|
String str = p.getStringValue();
|
||||||
updated++;
|
Reader r = new StringReader (str);
|
||||||
rec.setValue (rel.getDbField(), p.getFloatValue ());
|
stmt.setCharacterStream (stmtNumber, r, str.length());
|
||||||
break;
|
|
||||||
case IProperty.NODE:
|
|
||||||
if (!rel.virtual && rel.reftype == Relation.REFERENCE) {
|
|
||||||
// INode n = p.getNodeValue ();
|
|
||||||
// String foreignID = n == null ? null : n.getID ();
|
|
||||||
updated++;
|
|
||||||
rec.setValue (rel.getDbField(), p.getStringValue ());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
p.dirty = false;
|
case Types.CHAR:
|
||||||
if (!rel.isPrivate())
|
case Types.VARCHAR:
|
||||||
markMappingAsUpdated = true;
|
case Types.OTHER:
|
||||||
|
stmt.setString (stmtNumber, p.getStringValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Types.DATE:
|
||||||
|
case Types.TIME:
|
||||||
|
case Types.TIMESTAMP:
|
||||||
|
stmt.setTimestamp (stmtNumber, p.getTimestampValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Types.NULL:
|
||||||
|
stmt.setNull (stmtNumber, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
stmt.setString (stmtNumber, p.getStringValue());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (rel != null && rel.getDbField() != null) {
|
|
||||||
|
|
||||||
updated++;
|
|
||||||
rec.setValueNull (rel.getDbField());
|
|
||||||
}
|
}
|
||||||
|
p.dirty = false;
|
||||||
|
if (!rel.isPrivate())
|
||||||
|
markMappingAsUpdated = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (updated > 0) {
|
|
||||||
// mark the key value as clean so no try is made to update it
|
stmt.executeUpdate ();
|
||||||
rec.markValueClean (dbm.getIDField ());
|
|
||||||
rec.markForUpdate ();
|
} catch (Exception x) {
|
||||||
tds.save ();
|
x.printStackTrace ();
|
||||||
}
|
throw x;
|
||||||
} finally {
|
} finally {
|
||||||
if (tds != null) try {
|
if (stmt != null) try {
|
||||||
tds.close ();
|
stmt.close ();
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (markMappingAsUpdated)
|
if (markMappingAsUpdated)
|
||||||
dbm.notifyDataChange ();
|
dbm.notifyDataChange ();
|
||||||
}
|
}
|
||||||
|
@ -579,14 +723,17 @@ public final class NodeManager {
|
||||||
Statement st = null;
|
Statement st = null;
|
||||||
try {
|
try {
|
||||||
Connection con = dbm.getConnection ();
|
Connection con = dbm.getConnection ();
|
||||||
st = con.createStatement ();
|
String str = new StringBuffer ("DELETE FROM ")
|
||||||
st.executeUpdate (new StringBuffer ("DELETE FROM ")
|
|
||||||
.append(dbm.getTableName ())
|
.append(dbm.getTableName ())
|
||||||
.append(" WHERE ")
|
.append(" WHERE ")
|
||||||
.append(dbm.getIDField())
|
.append(dbm.getIDField())
|
||||||
.append(" = ")
|
.append(" = ")
|
||||||
.append(node.getID())
|
.append(node.getID())
|
||||||
.toString());
|
.toString();
|
||||||
|
st = con.createStatement ();
|
||||||
|
st.executeUpdate (str);
|
||||||
|
if (logSql)
|
||||||
|
app.logEvent ("### deleteNode: "+str);
|
||||||
} finally {
|
} finally {
|
||||||
if (st != null) try {
|
if (st != null) try {
|
||||||
st.close ();
|
st.close ();
|
||||||
|
@ -1084,7 +1231,13 @@ public final class NodeManager {
|
||||||
q.append ("WHERE ");
|
q.append ("WHERE ");
|
||||||
q.append (idfield);
|
q.append (idfield);
|
||||||
q.append (" = ");
|
q.append (" = ");
|
||||||
q.append (kstr);
|
if (dbm.needsQuotes (idfield)) {
|
||||||
|
q.append ("'");
|
||||||
|
q.append (escape(kstr));
|
||||||
|
q.append ("'");
|
||||||
|
} else {
|
||||||
|
q.append (kstr);
|
||||||
|
}
|
||||||
|
|
||||||
if (logSql)
|
if (logSql)
|
||||||
app.logEvent ("### getNodeByKey: "+q.toString());
|
app.logEvent ("### getNodeByKey: "+q.toString());
|
||||||
|
|
|
@ -8,6 +8,7 @@ import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.text.*;
|
import java.text.*;
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A property implementation for Nodes stored inside a database. Basically
|
* A property implementation for Nodes stored inside a database. Basically
|
||||||
|
@ -19,13 +20,7 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
private String propname;
|
private String propname;
|
||||||
private Node node;
|
private Node node;
|
||||||
|
|
||||||
private String svalue;
|
private Object value;
|
||||||
private boolean bvalue;
|
|
||||||
private long lvalue;
|
|
||||||
private double dvalue;
|
|
||||||
// protected String nvalueID;
|
|
||||||
private NodeHandle nhandle;
|
|
||||||
private Object jvalue;
|
|
||||||
|
|
||||||
private int type;
|
private int type;
|
||||||
|
|
||||||
|
@ -42,29 +37,31 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
case STRING:
|
case STRING:
|
||||||
// try to convert from old format
|
// try to convert from old format
|
||||||
if (node.version < 7)
|
if (node.version < 7)
|
||||||
svalue = in.readUTF ();
|
value = in.readUTF ();
|
||||||
else
|
else
|
||||||
svalue = (String) in.readObject ();
|
value = in.readObject ();
|
||||||
break;
|
break;
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
bvalue = in.readBoolean ();
|
value = in.readBoolean () ? Boolean.TRUE : Boolean.FALSE;
|
||||||
break;
|
break;
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
|
value = new Long (in.readLong ());
|
||||||
|
break;
|
||||||
case DATE:
|
case DATE:
|
||||||
lvalue = in.readLong ();
|
value = new Date (in.readLong ());
|
||||||
break;
|
break;
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
dvalue = in.readDouble ();
|
value = new Double (in.readDouble ());
|
||||||
break;
|
break;
|
||||||
case NODE:
|
case NODE:
|
||||||
// try to convert from old format
|
// try to convert from old format
|
||||||
if (node.version > 4)
|
if (node.version > 4)
|
||||||
nhandle = (NodeHandle) in.readObject ();
|
value = (NodeHandle) in.readObject ();
|
||||||
else
|
else
|
||||||
nhandle = new NodeHandle (new DbKey (null, in.readUTF ()));
|
value = new NodeHandle (new DbKey (null, in.readUTF ()));
|
||||||
break;
|
break;
|
||||||
case JAVAOBJECT:
|
case JAVAOBJECT:
|
||||||
jvalue = in.readObject ();
|
value = in.readObject ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (ClassNotFoundException x) {
|
} catch (ClassNotFoundException x) {
|
||||||
|
@ -78,26 +75,28 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
out.writeInt (type);
|
out.writeInt (type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case STRING:
|
case STRING:
|
||||||
out.writeObject (svalue);
|
out.writeObject (value);
|
||||||
break;
|
break;
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
out.writeBoolean (bvalue);
|
out.writeBoolean (((Boolean) value).booleanValue());
|
||||||
break;
|
break;
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
|
out.writeLong (((Long) value).longValue());
|
||||||
|
break;
|
||||||
case DATE:
|
case DATE:
|
||||||
out.writeLong (lvalue);
|
out.writeLong (((Date) value).getTime());
|
||||||
break;
|
break;
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
out.writeDouble (dvalue);
|
out.writeDouble (((Double) value).doubleValue());
|
||||||
break;
|
break;
|
||||||
case NODE:
|
case NODE:
|
||||||
out.writeObject (nhandle);
|
out.writeObject (value);
|
||||||
break;
|
break;
|
||||||
case JAVAOBJECT:
|
case JAVAOBJECT:
|
||||||
if (jvalue != null && !(jvalue instanceof Serializable))
|
if (value != null && !(value instanceof Serializable))
|
||||||
out.writeObject (null);
|
out.writeObject (null);
|
||||||
else
|
else
|
||||||
out.writeObject (jvalue);
|
out.writeObject (value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,10 +113,10 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Property (String propname, Node node, Node value) {
|
public Property (String propname, Node node, Node valueNode) {
|
||||||
this (propname, node);
|
this (propname, node);
|
||||||
type = NODE;
|
type = NODE;
|
||||||
nhandle = value == null ? null : value.getHandle ();
|
value = valueNode == null ? null : valueNode.getHandle ();
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,141 +125,115 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getValue () {
|
public Object getValue () {
|
||||||
switch (type) {
|
return value;
|
||||||
case STRING:
|
|
||||||
return svalue;
|
|
||||||
case BOOLEAN:
|
|
||||||
return new Boolean (bvalue);
|
|
||||||
case INTEGER:
|
|
||||||
return new Long (lvalue);
|
|
||||||
case FLOAT:
|
|
||||||
return new Double (dvalue);
|
|
||||||
case DATE:
|
|
||||||
return new Date (lvalue);
|
|
||||||
case NODE:
|
|
||||||
return null;
|
|
||||||
case JAVAOBJECT:
|
|
||||||
return jvalue;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStringValue (String value) {
|
public int getType () {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStringValue (String str) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
unregisterNode ();
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
|
||||||
this.jvalue = null;
|
|
||||||
type = STRING;
|
type = STRING;
|
||||||
this.svalue = value;
|
value = str;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setIntegerValue (long value) {
|
public void setIntegerValue (long l) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
unregisterNode ();
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
|
||||||
this.jvalue = null;
|
|
||||||
type = INTEGER;
|
type = INTEGER;
|
||||||
this.lvalue = value;
|
value = new Long(l);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFloatValue (double value) {
|
public void setFloatValue (double d) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
unregisterNode ();
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
|
||||||
this.jvalue = null;
|
|
||||||
type = FLOAT;
|
type = FLOAT;
|
||||||
this.dvalue = value;
|
value = new Double(d);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDateValue (Date value) {
|
public void setDateValue (Date date) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
unregisterNode ();
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
|
||||||
this.jvalue = null;
|
|
||||||
type = DATE;
|
type = DATE;
|
||||||
this.lvalue = value == null ? 0 : value.getTime();
|
value = date;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBooleanValue (boolean value) {
|
public void setBooleanValue (boolean bool) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
unregisterNode ();
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
|
||||||
this.jvalue = null;
|
|
||||||
type = BOOLEAN;
|
type = BOOLEAN;
|
||||||
this.bvalue = value;
|
value = bool ? Boolean.TRUE : Boolean.FALSE;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeValue (Node value) {
|
public void setNodeValue (Node node) {
|
||||||
// value.checkWriteLock ();
|
// value.checkWriteLock ();
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
unregisterNode ();
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
|
||||||
this.jvalue = null;
|
|
||||||
|
|
||||||
// registerNode (value);
|
// registerNode (value);
|
||||||
type = NODE;
|
type = NODE;
|
||||||
|
|
||||||
nhandle = value.getHandle ();
|
value = node == null ? null : node.getHandle ();
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeHandle (NodeHandle value) {
|
public void setNodeHandle (NodeHandle handle) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
unregisterNode ();
|
unregisterNode ();
|
||||||
if (type == JAVAOBJECT)
|
|
||||||
this.jvalue = null;
|
|
||||||
// registerNode (value);
|
// registerNode (value);
|
||||||
type = NODE;
|
type = NODE;
|
||||||
nhandle = value;
|
value = handle;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeHandle getNodeHandle () {
|
public NodeHandle getNodeHandle () {
|
||||||
return nhandle;
|
if (type == NODE)
|
||||||
|
return (NodeHandle) value;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void convertToNodeReference (DbMapping dbm) {
|
public void convertToNodeReference (DbMapping dbm) {
|
||||||
String id = getStringValue ();
|
if (value != null && !(value instanceof NodeHandle))
|
||||||
if (id == null)
|
value = new NodeHandle (new DbKey (dbm, value.toString ()));
|
||||||
nhandle = null;
|
|
||||||
else
|
|
||||||
nhandle = new NodeHandle (new DbKey (dbm, id));
|
|
||||||
type = NODE;
|
type = NODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setJavaObjectValue (Object value) {
|
public void setJavaObjectValue (Object obj) {
|
||||||
if (type == NODE)
|
if (type == NODE)
|
||||||
unregisterNode ();
|
unregisterNode ();
|
||||||
type = JAVAOBJECT;
|
type = JAVAOBJECT;
|
||||||
this.jvalue = value;
|
value = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tell a the value node that it is no longer used as a property.
|
* tell a the value node that it is no longer used as a property.
|
||||||
* If this was the "main" property for the node, also remove all other references.
|
* If this was the "main" property for the node, also remove all other references.
|
||||||
*/
|
*/
|
||||||
protected void unregisterNode () {
|
protected void unregisterNode () {
|
||||||
Node nvalue = null;
|
if (value == null || !(value instanceof NodeHandle))
|
||||||
if (nhandle != null)
|
return;
|
||||||
nvalue = nhandle.getNode (node.nmgr);
|
NodeHandle nhandle = (NodeHandle) value;
|
||||||
|
Node nvalue = nhandle.getNode (node.nmgr);
|
||||||
|
|
||||||
DbMapping nvmap = null;
|
DbMapping nvmap = null;
|
||||||
Relation nvrel = null;
|
Relation nvrel = null;
|
||||||
if (node.dbmap != null) {
|
if (node.dbmap != null) {
|
||||||
nvmap = node.dbmap.getPropertyMapping (propname);
|
nvmap = node.dbmap.getPropertyMapping (propname);
|
||||||
nvrel = node.dbmap.getPropertyRelation (propname);
|
nvrel = node.dbmap.getPropertyRelation (propname);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nvalue == null)
|
if (nvalue == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nvalue.checkWriteLock ();
|
nvalue.checkWriteLock ();
|
||||||
// check if the property node is also a subnode
|
// check if the property node is also a subnode
|
||||||
// BUG: this doesn't work because properties for subnode/properties are never stored and therefore
|
// BUG: this doesn't work because properties for subnode/properties are never stored and therefore
|
||||||
|
@ -281,22 +254,20 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
|
|
||||||
|
|
||||||
public String getStringValue () {
|
public String getStringValue () {
|
||||||
|
if (value == null)
|
||||||
|
return null;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case STRING:
|
case STRING:
|
||||||
return svalue;
|
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
return bvalue ? "true" : "false";
|
|
||||||
case DATE:
|
|
||||||
SimpleDateFormat format = new SimpleDateFormat ("dd.MM.yy HH:mm");
|
|
||||||
return format.format (new Date (lvalue));
|
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
return Long.toString (lvalue);
|
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
return Double.toString (dvalue);
|
|
||||||
case NODE:
|
|
||||||
return nhandle == null ? null : nhandle.getID ();
|
|
||||||
case JAVAOBJECT:
|
case JAVAOBJECT:
|
||||||
return jvalue == null ? null : jvalue.toString ();
|
return value.toString ();
|
||||||
|
case DATE:
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat ("dd.MM.yy hh:mm:ss");
|
||||||
|
return format.format ((Date) value);
|
||||||
|
case NODE:
|
||||||
|
return ((NodeHandle) value).getID ();
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -306,51 +277,66 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getIntegerValue () {
|
public long getIntegerValue () {
|
||||||
if (type == INTEGER)
|
if (type == INTEGER)
|
||||||
return lvalue;
|
return ((Long) value).longValue ();
|
||||||
return 0;
|
if (type == FLOAT)
|
||||||
|
return ((Double) value).longValue ();
|
||||||
|
if (type == BOOLEAN)
|
||||||
|
return ((Boolean) value).booleanValue() ? 1 : 0;
|
||||||
|
try {
|
||||||
|
return Long.parseLong (getStringValue());
|
||||||
|
} catch (Exception x) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getFloatValue () {
|
public double getFloatValue () {
|
||||||
if (type == FLOAT)
|
if (type == FLOAT)
|
||||||
return dvalue;
|
return ((Double) value).doubleValue();
|
||||||
return 0.0;
|
if (type == INTEGER)
|
||||||
|
return ((Long) value).doubleValue ();
|
||||||
|
try {
|
||||||
|
return Double.parseDouble (getStringValue());
|
||||||
|
} catch (Exception x) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Date getDateValue () {
|
public Date getDateValue () {
|
||||||
if (type == DATE)
|
if (type == DATE)
|
||||||
return new Date (lvalue);
|
return (Date) value;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Timestamp getTimestampValue () {
|
||||||
|
if (type == DATE && value != null)
|
||||||
|
return new Timestamp (((Date) value).getTime());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getBooleanValue () {
|
public boolean getBooleanValue () {
|
||||||
if (type == BOOLEAN)
|
if (type == BOOLEAN)
|
||||||
return bvalue;
|
return ((Boolean) value).booleanValue();
|
||||||
|
if (type == INTEGER)
|
||||||
|
return !(0 == getIntegerValue());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public INode getNodeValue () {
|
public INode getNodeValue () {
|
||||||
|
if (type == NODE && value != null) {
|
||||||
if (nhandle != null) {
|
NodeHandle nhandle = (NodeHandle) value;
|
||||||
Node n = nhandle.getNode (node.nmgr);
|
return nhandle.getNode (node.nmgr);
|
||||||
if (n != null) return n;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getJavaObjectValue () {
|
public Object getJavaObjectValue () {
|
||||||
if (type == JAVAOBJECT)
|
if (type == JAVAOBJECT)
|
||||||
return jvalue;
|
return value;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getType () {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,10 @@ import java.util.Vector;
|
||||||
nmgr.evictNode (node);
|
nmgr.evictNode (node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void evictNodeByKey (Key key) {
|
||||||
|
nmgr.evictNodeByKey (key);
|
||||||
|
}
|
||||||
|
|
||||||
public void evictKey (Key key) {
|
public void evictKey (Key key) {
|
||||||
nmgr.evictKey (key);
|
nmgr.evictKey (key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import java.util.*;
|
||||||
|
|
||||||
import javax.xml.parsers.*;
|
import javax.xml.parsers.*;
|
||||||
import org.w3c.dom.*;
|
import org.w3c.dom.*;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.util.SystemProperties;
|
import helma.util.SystemProperties;
|
||||||
|
@ -75,6 +76,15 @@ public class XmlConverter implements XmlConstants {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public INode convertFromString( String xml, INode helmaNode ) throws RuntimeException {
|
||||||
|
Document document = XmlUtil.parse (new InputSource (new StringReader (xml)));
|
||||||
|
if ( document!=null && document.getDocumentElement()!=null ) {
|
||||||
|
return convert( document.getDocumentElement(), helmaNode, new HashMap() );
|
||||||
|
} else {
|
||||||
|
return helmaNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public INode convert( Element element, INode helmaNode, Map nodeCache ) {
|
public INode convert( Element element, INode helmaNode, Map nodeCache ) {
|
||||||
offset++;
|
offset++;
|
||||||
// previousNode is used to cache previous nodes with the same prototype
|
// previousNode is used to cache previous nodes with the same prototype
|
||||||
|
@ -82,17 +92,16 @@ public class XmlConverter implements XmlConstants {
|
||||||
Object previousNode = null;
|
Object previousNode = null;
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
debug("reading " + element.getNodeName() );
|
debug("reading " + element.getNodeName() );
|
||||||
helmaNode.setName( element.getNodeName() );
|
|
||||||
String prototype = props.getProperty(element.getNodeName()+"._prototype");
|
String prototype = props.getProperty(element.getNodeName()+"._prototype");
|
||||||
if ( prototype == null && !sparse )
|
if ( prototype == null && !sparse )
|
||||||
prototype = "HopObject";
|
prototype = "HopObject";
|
||||||
// if we have a prototype (either explicit or implicit "hopobject"),
|
// if we have a prototype (either explicit or implicit "hopobject"),
|
||||||
// set it on the Helma node and store it in the node cache.
|
// set it on the Helma node and store it in the node cache.
|
||||||
if ( prototype != null ) {
|
if ( prototype != null ) {
|
||||||
|
helmaNode.setName( element.getNodeName() );
|
||||||
helmaNode.setPrototype( prototype );
|
helmaNode.setPrototype( prototype );
|
||||||
previousNode = nodeCache.put (prototype, helmaNode);
|
previousNode = nodeCache.put (prototype, helmaNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check attributes of the current element
|
// check attributes of the current element
|
||||||
attributes(element, helmaNode, nodeCache);
|
attributes(element, helmaNode, nodeCache);
|
||||||
// check child nodes of the current element
|
// check child nodes of the current element
|
||||||
|
@ -113,7 +122,7 @@ public class XmlConverter implements XmlConstants {
|
||||||
private INode children( Element element, helma.objectmodel.INode helmaNode, Map nodeCache ) {
|
private INode children( Element element, helma.objectmodel.INode helmaNode, Map nodeCache ) {
|
||||||
NodeList list = element.getChildNodes();
|
NodeList list = element.getChildNodes();
|
||||||
int len = list.getLength();
|
int len = list.getLength();
|
||||||
boolean nodeHasPrototype = helmaNode.getPrototype() != null;
|
boolean nodeIsInitialized = !nodeCache.isEmpty();
|
||||||
StringBuffer textcontent = new StringBuffer();
|
StringBuffer textcontent = new StringBuffer();
|
||||||
String domKey, helmaKey;
|
String domKey, helmaKey;
|
||||||
for ( int i=0; i<len; i++ ) {
|
for ( int i=0; i<len; i++ ) {
|
||||||
|
@ -121,9 +130,9 @@ public class XmlConverter implements XmlConstants {
|
||||||
// loop through the list of children
|
// loop through the list of children
|
||||||
org.w3c.dom.Node childNode = list.item(i);
|
org.w3c.dom.Node childNode = list.item(i);
|
||||||
|
|
||||||
// if the current node hasn't been initialized yet, try if it can
|
// if the current node hasn't been initialized yet, try if it can
|
||||||
// be initialized and converted from one of the child elements.
|
// be initialized and converted from one of the child elements.
|
||||||
if (!nodeHasPrototype) {
|
if (!nodeIsInitialized) {
|
||||||
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
|
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
convert ((Element) childNode, helmaNode, nodeCache);
|
convert ((Element) childNode, helmaNode, nodeCache);
|
||||||
if (helmaNode.getPrototype() != null)
|
if (helmaNode.getPrototype() != null)
|
||||||
|
@ -162,8 +171,9 @@ public class XmlConverter implements XmlConstants {
|
||||||
String prototype = helmaKey.substring (0, dot);
|
String prototype = helmaKey.substring (0, dot);
|
||||||
INode node = (INode) nodeCache.get (prototype);
|
INode node = (INode) nodeCache.get (prototype);
|
||||||
helmaKey = helmaKey.substring (dot+1);
|
helmaKey = helmaKey.substring (dot+1);
|
||||||
if (node != null && node.getString(helmaKey)==null)
|
if (node != null && node.getString(helmaKey)==null) {
|
||||||
node.setString (helmaKey, XmlUtil.getTextContent (childNode));
|
node.setString (helmaKey, XmlUtil.getTextContent (childNode));
|
||||||
|
}
|
||||||
} else if ( helmaNode.getString(helmaKey)==null ) {
|
} else if ( helmaNode.getString(helmaKey)==null ) {
|
||||||
helmaNode.setString( helmaKey, XmlUtil.getTextContent(childNode) );
|
helmaNode.setString( helmaKey, XmlUtil.getTextContent(childNode) );
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
|
@ -220,7 +230,8 @@ public class XmlConverter implements XmlConstants {
|
||||||
if (helmaKey == null) {
|
if (helmaKey == null) {
|
||||||
// we don't map this child element itself since we do
|
// we don't map this child element itself since we do
|
||||||
// sparse parsing, but there may be something of interest
|
// sparse parsing, but there may be something of interest
|
||||||
// in the child's child elements.
|
// in the child's attributes and child elements.
|
||||||
|
attributes (childElement, helmaNode, nodeCache);
|
||||||
children (childElement, helmaNode, nodeCache);
|
children (childElement, helmaNode, nodeCache);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -295,8 +306,9 @@ public class XmlConverter implements XmlConstants {
|
||||||
if (dot > -1) {
|
if (dot > -1) {
|
||||||
String prototype = helmaKey.substring (0, dot);
|
String prototype = helmaKey.substring (0, dot);
|
||||||
INode node = (INode) nodeCache.get (prototype);
|
INode node = (INode) nodeCache.get (prototype);
|
||||||
if (node != null)
|
if (node != null) {
|
||||||
node.setString (helmaKey.substring(dot+1), attr.getNodeValue());
|
node.setString (helmaKey.substring(dot+1), attr.getNodeValue());
|
||||||
|
}
|
||||||
} else if (helmaNode.getPrototype() != null) {
|
} else if (helmaNode.getPrototype() != null) {
|
||||||
helmaNode.setString( helmaKey, attr.getNodeValue() );
|
helmaNode.setString( helmaKey, attr.getNodeValue() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,8 @@ public class XmlUtil {
|
||||||
int ct = childlist.getLength();
|
int ct = childlist.getLength();
|
||||||
for ( int j=0; j<ct; j++ ) {
|
for ( int j=0; j<ct; j++ ) {
|
||||||
org.w3c.dom.Node childNode = childlist.item(j);
|
org.w3c.dom.Node childNode = childlist.item(j);
|
||||||
if ( childNode.getNodeType()==org.w3c.dom.Node.TEXT_NODE ) {
|
if ( childNode.getNodeType() == Node.TEXT_NODE ||
|
||||||
|
childNode.getNodeType() == Node.CDATA_SECTION_NODE) {
|
||||||
childtext.append(childNode.getNodeValue().trim() );
|
childtext.append(childNode.getNodeValue().trim() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,8 @@ public class FesiEngine implements ScriptingEngine {
|
||||||
* necessary to bootstrap the rest is parsed.
|
* necessary to bootstrap the rest is parsed.
|
||||||
*/
|
*/
|
||||||
private void initialize () {
|
private void initialize () {
|
||||||
|
// set the thread filed in the FESI evaluator
|
||||||
|
evaluator.thread = Thread.currentThread ();
|
||||||
Collection protos = app.getPrototypes();
|
Collection protos = app.getPrototypes();
|
||||||
for (Iterator i=protos.iterator(); i.hasNext(); ) {
|
for (Iterator i=protos.iterator(); i.hasNext(); ) {
|
||||||
Prototype proto = (Prototype) i.next ();
|
Prototype proto = (Prototype) i.next ();
|
||||||
|
@ -132,13 +134,14 @@ public class FesiEngine implements ScriptingEngine {
|
||||||
// we always need it and there's no chance to trigger
|
// we always need it and there's no chance to trigger
|
||||||
// creation on demand.
|
// creation on demand.
|
||||||
getPrototype ("global");
|
getPrototype ("global");
|
||||||
|
evaluator.thread = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a prototype without fully parsing its script files.
|
* Initialize a prototype without fully parsing its script files.
|
||||||
*/
|
*/
|
||||||
void initPrototype (Prototype prototype) {
|
void initPrototype (Prototype prototype) {
|
||||||
// System.err.println ("FESI INIT PROTO "+prototype);
|
// System.err.println ("FESI INIT PROTO "+prototype);
|
||||||
ObjectPrototype op = null;
|
ObjectPrototype op = null;
|
||||||
|
|
||||||
// get the prototype's prototype if possible and necessary
|
// get the prototype's prototype if possible and necessary
|
||||||
|
@ -193,7 +196,7 @@ public class FesiEngine implements ScriptingEngine {
|
||||||
* Set up a prototype, parsing and compiling all its script files.
|
* Set up a prototype, parsing and compiling all its script files.
|
||||||
*/
|
*/
|
||||||
void evaluatePrototype (Prototype prototype) {
|
void evaluatePrototype (Prototype prototype) {
|
||||||
// System.err.println ("FESI EVALUATE PROTO "+prototype+" FOR "+this);
|
// System.err.println ("FESI EVALUATE PROTO "+prototype+" FOR "+this);
|
||||||
ObjectPrototype op = null;
|
ObjectPrototype op = null;
|
||||||
|
|
||||||
// get the prototype's prototype if possible and necessary
|
// get the prototype's prototype if possible and necessary
|
||||||
|
@ -230,8 +233,8 @@ public class FesiEngine implements ScriptingEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register a constructor for all types except global.
|
// Register a constructor for all types except global.
|
||||||
// This will first create a new prototyped hopobject and then calls
|
// This will first create a new prototyped hopobject and then calls
|
||||||
// the actual (scripted) constructor on it.
|
// the actual (scripted) constructor on it.
|
||||||
if (!"global".equalsIgnoreCase (name) && !"root".equalsIgnoreCase (name)) {
|
if (!"global".equalsIgnoreCase (name) && !"root".equalsIgnoreCase (name)) {
|
||||||
try {
|
try {
|
||||||
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
||||||
|
@ -263,11 +266,13 @@ public class FesiEngine implements ScriptingEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called before an execution context is entered to let the
|
* This method is called before an execution context is entered to let the
|
||||||
* engine know it should update its prototype information.
|
* engine know it should update its prototype information.
|
||||||
*/
|
*/
|
||||||
public void updatePrototypes () {
|
public void updatePrototypes () {
|
||||||
|
// set the thread filed in the FESI evaluator
|
||||||
|
evaluator.thread = Thread.currentThread ();
|
||||||
Collection protos = app.getPrototypes();
|
Collection protos = app.getPrototypes();
|
||||||
for (Iterator i=protos.iterator(); i.hasNext(); ) {
|
for (Iterator i=protos.iterator(); i.hasNext(); ) {
|
||||||
Prototype proto = (Prototype) i.next ();
|
Prototype proto = (Prototype) i.next ();
|
||||||
|
|
|
@ -54,11 +54,17 @@ public class NodeConstructor extends BuiltinFunctionObject {
|
||||||
// with the name of the type.
|
// with the name of the type.
|
||||||
// HACK: There is an incompatibility problem here, because the property
|
// HACK: There is an incompatibility problem here, because the property
|
||||||
// constructor is defined as the constructor of the object by EcmaScript.
|
// constructor is defined as the constructor of the object by EcmaScript.
|
||||||
if (op.getProperty ("constructor", "constructor".hashCode()) instanceof ConstructedFunctionObject)
|
if (op.getProperty ("constructor",
|
||||||
|
"constructor".hashCode())
|
||||||
|
instanceof ConstructedFunctionObject)
|
||||||
node.doIndirectCall (engine.getEvaluator(), node, "constructor", arguments);
|
node.doIndirectCall (engine.getEvaluator(), node, "constructor", arguments);
|
||||||
else
|
else if (op.getProperty (typename,
|
||||||
|
typename.hashCode())
|
||||||
|
instanceof ConstructedFunctionObject)
|
||||||
node.doIndirectCall (engine.getEvaluator(), node, typename, arguments);
|
node.doIndirectCall (engine.getEvaluator(), node, typename, arguments);
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception x) {
|
||||||
|
throw new EcmaScriptException (x.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ public class DomExtension extends Extension {
|
||||||
globalXml.putHiddenProperty ("write", new XmlWrite ("write", evaluator, fp));
|
globalXml.putHiddenProperty ("write", new XmlWrite ("write", evaluator, fp));
|
||||||
globalXml.putHiddenProperty ("writeToString", new XmlWriteToString ("writeToString", evaluator, fp));
|
globalXml.putHiddenProperty ("writeToString", new XmlWriteToString ("writeToString", evaluator, fp));
|
||||||
globalXml.putHiddenProperty ("get", new XmlGet ("get", evaluator, fp));
|
globalXml.putHiddenProperty ("get", new XmlGet ("get", evaluator, fp));
|
||||||
|
globalXml.putHiddenProperty ("getFromString", new XmlGetFromString ("getFromString", evaluator, fp));
|
||||||
go.putHiddenProperty ("Xml", globalXml);
|
go.putHiddenProperty ("Xml", globalXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +176,31 @@ public class DomExtension extends Extension {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class XmlGetFromString extends BuiltinFunctionObject {
|
||||||
|
XmlGetFromString(String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
|
super(fp, evaluator, name, 1);
|
||||||
|
}
|
||||||
|
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
|
if ( arguments==null || arguments.length==0 )
|
||||||
|
throw new EcmaScriptException("Xml.getFromString() needs an XML string as parameter");
|
||||||
|
try {
|
||||||
|
XmlConverter converter;
|
||||||
|
if ( arguments.length>1 ) {
|
||||||
|
converter = new XmlConverter (arguments[1].toString());
|
||||||
|
} else {
|
||||||
|
converter = new XmlConverter ();
|
||||||
|
}
|
||||||
|
INode node = new helma.objectmodel.db.Node ( (String)null, (String)null, this.evaluator.engine.getApplication().getWrappedNodeManager() );
|
||||||
|
INode result = converter.convertFromString (arguments[0].toString(),node);
|
||||||
|
return this.evaluator.engine.getNodeWrapper(result);
|
||||||
|
} catch ( NoClassDefFoundError e ) {
|
||||||
|
throw new EcmaScriptException("Can't load dom-capable xml parser.");
|
||||||
|
} catch ( RuntimeException f ) {
|
||||||
|
throw new EcmaScriptException(f.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ public abstract class AbstractServletClient extends HttpServlet {
|
||||||
uploadLimit = upstr == null ? 1024 : Integer.parseInt (upstr);
|
uploadLimit = upstr == null ? 1024 : Integer.parseInt (upstr);
|
||||||
// get cookie domain
|
// get cookie domain
|
||||||
cookieDomain = init.getInitParameter ("cookieDomain");
|
cookieDomain = init.getInitParameter ("cookieDomain");
|
||||||
|
if (cookieDomain != null)
|
||||||
|
cookieDomain = cookieDomain.toLowerCase();
|
||||||
// get default encoding
|
// get default encoding
|
||||||
defaultEncoding = init.getInitParameter ("charset");
|
defaultEncoding = init.getInitParameter ("charset");
|
||||||
debug = ("true".equalsIgnoreCase (init.getInitParameter ("debug")));
|
debug = ("true".equalsIgnoreCase (init.getInitParameter ("debug")));
|
||||||
|
@ -73,7 +75,6 @@ public abstract class AbstractServletClient extends HttpServlet {
|
||||||
protected void execute (HttpServletRequest request,
|
protected void execute (HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
byte method) {
|
byte method) {
|
||||||
Cookie[] cookies = request.getCookies();
|
|
||||||
|
|
||||||
RequestTrans reqtrans = new RequestTrans (method);
|
RequestTrans reqtrans = new RequestTrans (method);
|
||||||
// get app and path from original request path
|
// get app and path from original request path
|
||||||
|
@ -120,11 +121,12 @@ public abstract class AbstractServletClient extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read cookies
|
// read cookies
|
||||||
if (cookies != null) {
|
Cookie[] reqCookies = request.getCookies();
|
||||||
for (int i=0; i < cookies.length;i++) try {
|
if (reqCookies != null) {
|
||||||
|
for (int i=0; i < reqCookies.length;i++) try {
|
||||||
// get Cookies
|
// get Cookies
|
||||||
String nextKey = cookies[i].getName ();
|
String nextKey = reqCookies[i].getName ();
|
||||||
String nextPart = cookies[i].getValue ();
|
String nextPart = reqCookies[i].getValue ();
|
||||||
if ("HopSession".equals (nextKey))
|
if ("HopSession".equals (nextKey))
|
||||||
reqtrans.session = nextPart;
|
reqtrans.session = nextPart;
|
||||||
else
|
else
|
||||||
|
@ -157,6 +159,14 @@ public abstract class AbstractServletClient extends HttpServlet {
|
||||||
if (remotehost != null)
|
if (remotehost != null)
|
||||||
reqtrans.set ("http_remotehost", remotehost);
|
reqtrans.set ("http_remotehost", remotehost);
|
||||||
|
|
||||||
|
// get the cookie domain to use for this response, if any.
|
||||||
|
String resCookieDomain = cookieDomain;
|
||||||
|
if (resCookieDomain != null) {
|
||||||
|
// check if cookieDomain is valid for this response.
|
||||||
|
// (note: cookieDomain is guaranteed to be lower case)
|
||||||
|
if (host != null && host.toLowerCase().indexOf (cookieDomain) == -1)
|
||||||
|
resCookieDomain = null;
|
||||||
|
}
|
||||||
// check if we need to create a session id. also handle the
|
// check if we need to create a session id. also handle the
|
||||||
// case that the session id doesn't match the remote host address
|
// case that the session id doesn't match the remote host address
|
||||||
if (reqtrans.session == null || !reqtrans.session.startsWith (remotehost)) {
|
if (reqtrans.session == null || !reqtrans.session.startsWith (remotehost)) {
|
||||||
|
@ -165,8 +175,8 @@ public abstract class AbstractServletClient extends HttpServlet {
|
||||||
System.currentTimeMillis (), 36);
|
System.currentTimeMillis (), 36);
|
||||||
Cookie c = new Cookie("HopSession", reqtrans.session);
|
Cookie c = new Cookie("HopSession", reqtrans.session);
|
||||||
c.setPath ("/");
|
c.setPath ("/");
|
||||||
if (cookieDomain != null)
|
if (resCookieDomain != null)
|
||||||
c.setDomain (cookieDomain);
|
c.setDomain (resCookieDomain);
|
||||||
response.addCookie(c);
|
response.addCookie(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +193,16 @@ public abstract class AbstractServletClient extends HttpServlet {
|
||||||
reqtrans.path = getPathInfo (request);
|
reqtrans.path = getPathInfo (request);
|
||||||
ResponseTrans restrans = execute (reqtrans);
|
ResponseTrans restrans = execute (reqtrans);
|
||||||
|
|
||||||
|
// set cookies
|
||||||
|
int ncookies = restrans.countCookies();
|
||||||
|
if (restrans.countCookies() > 0) {
|
||||||
|
CookieTrans[] resCookies = restrans.getCookies ();
|
||||||
|
for (int i = 0; i < resCookies.length; i++) try {
|
||||||
|
Cookie c = resCookies[i].getCookie ("/", resCookieDomain);
|
||||||
|
response.addCookie(c);
|
||||||
|
} catch (Exception ignore) {}
|
||||||
|
}
|
||||||
|
// write response
|
||||||
writeResponse (request, response, restrans);
|
writeResponse (request, response, restrans);
|
||||||
|
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
|
@ -210,15 +230,6 @@ public abstract class AbstractServletClient extends HttpServlet {
|
||||||
HttpServletResponse res,
|
HttpServletResponse res,
|
||||||
ResponseTrans hopres) {
|
ResponseTrans hopres) {
|
||||||
|
|
||||||
int ncookies = hopres.countCookies();
|
|
||||||
if (hopres.countCookies() > 0) {
|
|
||||||
CookieTrans[] cookies = hopres.getCookies ();
|
|
||||||
for (int i = 0; i < cookies.length; i++) try {
|
|
||||||
Cookie c = cookies[i].getCookie ("/", cookieDomain);
|
|
||||||
res.addCookie(c);
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hopres.getETag() != null) {
|
if (hopres.getETag() != null) {
|
||||||
res.setHeader ("ETag", hopres.getETag());
|
res.setHeader ("ETag", hopres.getETag());
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,11 +363,14 @@ public final class HtmlEncoder {
|
||||||
if (i < l-2) {
|
if (i < l-2) {
|
||||||
if (!insideMacroTag && '%' == str.charAt(i+1)) {
|
if (!insideMacroTag && '%' == str.charAt(i+1)) {
|
||||||
// this is the beginning of a Helma macro tag
|
// this is the beginning of a Helma macro tag
|
||||||
insideMacroTag = insideTag = true;
|
if (!insideCodeTag) {
|
||||||
macroQuoteChar = '\u0000';
|
insideMacroTag = insideTag = true;
|
||||||
|
macroQuoteChar = '\u0000';
|
||||||
|
}
|
||||||
} else if ('!' == str.charAt(i+1) && '-' == str.charAt(i+2)) {
|
} else if ('!' == str.charAt(i+1) && '-' == str.charAt(i+2)) {
|
||||||
// the beginning of an HTML comment?
|
// the beginning of an HTML comment?
|
||||||
insideComment = insideTag = (i<l-3 && '-' == str.charAt(i+3));
|
if (!insideCodeTag)
|
||||||
|
insideComment = insideTag = (i<l-3 && '-' == str.charAt(i+3));
|
||||||
} else if (!insideTag) {
|
} else if (!insideTag) {
|
||||||
// check if this is a HTML tag.
|
// check if this is a HTML tag.
|
||||||
boolean insideCloseTag = ('/' == str.charAt(i+1));
|
boolean insideCloseTag = ('/' == str.charAt(i+1));
|
||||||
|
@ -480,6 +483,7 @@ public final class HtmlEncoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -494,6 +498,13 @@ public final class HtmlEncoder {
|
||||||
return ret.toString();
|
return ret.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final static void encodeFormValue (String str, StringBuffer ret) {
|
||||||
|
encodeAll (str, ret, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -512,9 +523,8 @@ public final class HtmlEncoder {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final static String encodeAll (String str, StringBuffer ret) {
|
public final static void encodeAll (String str, StringBuffer ret) {
|
||||||
encodeAll (str, ret, true);
|
encodeAll (str, ret, true);
|
||||||
return ret.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue