Schlankes Backend ohne JSF-Code

This commit is contained in:
Peter Hormanns 2010-10-01 19:52:51 +00:00
parent 19ea388bf1
commit 4dd9894b86
69 changed files with 7534 additions and 0 deletions

View File

@ -0,0 +1,357 @@
package de.hsadmin.cliClientConnector;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import de.hsadmin.cliClientConnector.CLIClientConnectorServlet.FunctionNotKnownException;
import de.hsadmin.cliClientConnector.CLIClientConnectorServlet.UnknownModuleException;
import de.hsadmin.core.model.Entity;
import de.hsadmin.core.model.ModuleInterface;
/**
* Parses Arguments for the CLI Client Connector Servlet
*
* @author Christof Donat
*
*/
public class ArgumentParser {
/// I am working for this Servlet instance
private CLIClientConnectorServlet master;
private DateFormat df = new SimpleDateFormat( "yyyy-MM-dd");
public ArgumentParser(CLIClientConnectorServlet master) {
this.master = master;
}
private String getUsageString() {
return " [ (-W name=value|--globalWhere:name=value) ...]\n"+
" [ (-S name=value|--globalSet:name=value) ...]\n"+
" [ (-D displayspec|--globalDisplay=displayspec) ...]\n"+
" [ (-c module.function|--call=module.function)\n" +
" [ (-w name=value|--where:name=value) ...]\n"+
" [ (-s name=value|--set:name=value) ...]\n"+
" [ (-d displayspec|--display:displayspec) ...]\n"+
" [ oids ...] ] ]\n"+
"\n"+
"(" + CLIClientConnectorServlet.version + ")\n";
}
private ArrayList<Method> getMethodList(Object o) {
Method[] meths = o.getClass().getMethods();
ArrayList<Method> methodlist = new ArrayList<Method>();
for( int i = 0; i < meths.length; i++ ) {
Method m = meths[i];
String n = m.getName();
if( n.startsWith("get") && !n.equals("getNew") ) {
String fn = m.getName().substring(3).toLowerCase();
if( fn.equals("class") ) continue;
if (m.getParameterTypes().length == 0) {
methodlist.add(m);
}
}
}
return methodlist;
}
private Hashtable<String,String> getValues(Object o, ArrayList<Method> methodlist, ArrayList<String>fieldNames, boolean deep, ArrayList<Object> foundObjects) {
Hashtable<String,String> row = new Hashtable<String,String>();
int i, j;
if( foundObjects == null ) foundObjects = new ArrayList<Object>();
for( i = 0; i < methodlist.size(); i++ ) {
Method m = methodlist.get(i);
try {
String name = fieldNames.get(i);
String type = m.getReturnType().getCanonicalName();
String val = "";
Object value = null;
try {
value = m.invoke(o);
} catch( Exception e ) {
e.printStackTrace();
}
if( value == null )
val = "";
else if( type.equals("java.lang.String") )
val = (String)value;
else if( type.equals("java.lang.Integer") )
val = String.valueOf((Integer)value);
else if( type.equals("java.lang.Long") )
val = String.valueOf((Long)value);
else if( type.equals("java.lang.Boolean") )
val = String.valueOf((Boolean)value);
else if( type.equals("java.util.Date") ) {
val = df.format((Date)value);
} else if( type.equals("java.util.Set") ) {
val = "<Set>";
} else try {
Entity v = (Entity)value;
val = v.createStringKey();
if( deep && !foundObjects.contains(v) ) {
foundObjects.add(v);
ArrayList<String> fieldNamesDeep = new ArrayList<String>();
ArrayList<Method> methodlistDeep = getMethodList(v);
for( j = 0; j < methodlistDeep.size(); j++ ) {
fieldNamesDeep.add(methodlistDeep.get(j).getName().substring(3).toLowerCase());
}
Hashtable<String,String> tmp = getValues(v,methodlistDeep,fieldNamesDeep,deep,foundObjects);
Enumeration<String> keys = tmp.keys();
while(keys.hasMoreElements()) {
try {
String k = (String)keys.nextElement();
row.put(name+"."+k, tmp.get(k));
} catch( Exception e ) {
e.printStackTrace();
}
}
}
} catch(ClassCastException e) {
val = value.toString();
}
if (val != null) row.put(name, val);
} catch (Exception e) {
e.printStackTrace();
}
}
return row;
}
private String formatObjectsWithoutDisplay(int j, ArrayList<String> fieldNames, ArrayList<Integer>columnWidths, ArrayList<Hashtable<String,String> > rows) {
int i;
StringBuffer rval = new StringBuffer();
for( i = 0; i < fieldNames.size(); i++ ) {
StringBuffer name = new StringBuffer(fieldNames.get(i));
int fieldwidth = columnWidths.get(i);
while( name.length() < fieldwidth )
name.append(" ");
rval.append(name.toString()+((i < fieldNames.size()-1)?" | ":""));
}
rval.append("\n");
for( i = 0; i < j; i++ )
rval.append("-");
rval.append("\n");
for( j = 0; j < rows.size(); j++ ) {
for( i = 0; i < fieldNames.size(); i++ ) {
StringBuffer value = new StringBuffer(rows.get(j).get(fieldNames.get(i)));
int fieldwidth = columnWidths.get(i);
while( value.length() < fieldwidth )
value.append(" ");
rval.append(value.toString()+((i < fieldNames.size()-1)?" | ":""));
}
rval.append("\n");
}
return rval.toString();
}
private String formatObjectsWithDisplay(ArrayList<Hashtable<String,String> > rows, String displayDef) {
StringBuffer rval = new StringBuffer();
for( int j = 0; j < rows.size(); j++) {
String rv = displayDef;
Enumeration<String> fNames = rows.get(j).keys();
while( fNames.hasMoreElements() ) {
String f = (String)fNames.nextElement();
rv = rv.replaceAll("\\$\\{"+f+"\\}", rows.get(j).get(f));
}
rv = rv.replaceAll("\\\\n", "\n");
rv = rv.replaceAll("\\\\t", "\t");
rv = rv.replaceAll("\\\\(.)?", "$1");
rval.append(rv);
}
return rval.toString();
}
/**
* format Objects for the output as a Human readable table
*
* @param objects
* format these objects
*
* @return humanReadableString
* a string with the human readable representation of the objects
*/
public String formatObjects(List<?> objects, String displayDef) {
if( objects.size() == 0 ) return "";
if( objects.get(0) == null ) return "";
ArrayList<Method> methodlist = getMethodList(objects.get(0));
ArrayList<Integer>columnWidths = new ArrayList<Integer>();
ArrayList<String>fieldNames = new ArrayList<String>();
ArrayList<Hashtable<String,String> > rows =
new ArrayList<Hashtable<String,String> >();
int i, j;
for( i = 0; i < methodlist.size(); i++ ) {
Method m = methodlist.get(i);
String n = m.getName();
String fn = n.substring(3).toLowerCase();
fieldNames.add(fn);
columnWidths.add(n.length()+3);
}
for( j = 0; j < objects.size(); j++ ) {
Object o = objects.get(j);
Hashtable<String,String> row = getValues(o,methodlist,fieldNames,(displayDef != null), null);
for( i = 0; i < fieldNames.size(); i++ ) {
String val = row.get(fieldNames.get(i));
if( val != null && i < columnWidths.size() && val.length()+3 > columnWidths.get(i) )
columnWidths.set(i, val.length()+3);
}
rows.add(row);
}
if( displayDef == null ) {
j = 0;
for( i = 0; i < columnWidths.size(); i++ ) {
j += columnWidths.get(i)+2;
}
j -= 2;
return formatObjectsWithoutDisplay(j, fieldNames, columnWidths, rows);
} else
return formatObjectsWithDisplay(rows, displayDef);
}
/**
* The main parser function. Parses the Parameters, uses the master to call
* the functions and returns a formatet output.
*
* @param arguments
* @return humanReadableObjectsString
*/
public String parse(List<String> arguments, ModuleInterface module) {
String rval = "";
String currentModule = null;
String currentFunction = null;
Map<String,String> currentWhere = new Hashtable<String,String>();
Map<String,String> currentSet = new Hashtable<String,String>();
ArrayList<String> currentOIDs = new ArrayList<String>();
Map<String,String> globalWhere = new Hashtable<String,String>();
Map<String,String> globalSet = new Hashtable<String,String>();
String display = null;
String globalDisplay = null;
for( int i = 0; i < arguments.size(); i++ ) {
String arg = arguments.get(i);
if( arg.equals("-c") || arg.startsWith("--call:") ) {
// call
if( currentModule != null ) {
try {
// execute the last call now
rval += formatObjects(master.callModule(
currentModule,
currentFunction,
currentWhere,
currentSet,
currentOIDs,
module),(display==null)?globalDisplay:display);
} catch (FunctionNotKnownException e) {
rval += "Function unknown: "+currentModule+'.'+currentFunction+"\n";
} catch (UnknownModuleException e) {
rval += "Module unknown: "+currentModule+"\n";
}
}
// reset parameters for next call
currentWhere = new HashMap<String, String>();
currentWhere.putAll(globalWhere);
currentSet = new HashMap<String, String>();
currentSet.putAll(globalSet);
currentOIDs = new ArrayList<String>();
display = null;
// set the new call
boolean isShortParam = arg.equals("-c");
String calldef = isShortParam?arguments.get(i+1):arg.substring(7);
if( calldef != null ) {
String[] split = calldef.split("[.]", 2);
currentModule = split[0];
currentFunction = split[1];
}
if( isShortParam ) i++;
} else if( arg.equals("-w") || arg.startsWith("--where:") ) {
// where
boolean isShortParam = arg.equals("-w");
String wheredef = isShortParam?arguments.get(i+1):arg.substring(8);
if( wheredef != null ) {
String[] split = wheredef.split("[=]", 2);
currentWhere.put(split[0],split[1]);
}
if( isShortParam ) i++;
} else if( arg.equals("-W") || arg.startsWith("--globalWhere:") ) {
// global where
boolean isShortParam = arg.equals("-W");
String gwheredef = isShortParam?arguments.get(i+1):arg.substring(14);
if( gwheredef != null ) {
String[] split = gwheredef.split("[=]", 2);
globalWhere.put(split[0],split[1]);
}
if( isShortParam ) i++;
} else if( arg.equals("-s") || arg.startsWith("--set:") ) {
// set
boolean isShortParam = arg.equals("-s");
String setdef = isShortParam?arguments.get(i+1):arg.substring(6);
if( setdef != null ) {
String[] split = setdef.split("[=]", 2);
currentSet.put(split[0],split[1]);
}
if( isShortParam ) i++;
} else if( arg.equals("-S") || arg.startsWith("--globalSet:") ) {
// global set
boolean isShortParam = arg.equals("-S");
String gsetdef = isShortParam?arguments.get(i+1):arg.substring(12);
if( gsetdef != null ) {
String[] split = gsetdef.split("[=]", 2);
globalSet.put(split[0],split[1]);
}
if( isShortParam ) i++;
} else if( arg.equals("-d") || arg.startsWith("--display:") ) {
// display
boolean isShortParam = arg.equals("-d");
display = isShortParam?arguments.get(i+1):arg.substring(10);
if( isShortParam ) i++;
} else if( arg.equals("-D") || arg.startsWith("--globalDisplay:") ) {
// global display
boolean isShortParam = arg.equals("-D");
globalDisplay = isShortParam?arguments.get(i+1):arg.substring(16);
if( isShortParam ) i++;
} else if( arg.equals("-h") || arg.equals("--help") ) {
return getUsageString();
} else if( arg.startsWith("-") ) {
return "unknown option '"+arg+"'\n"+getUsageString();
} else currentOIDs.add(arg);
}
if( currentModule != null ) {
try {
rval += formatObjects(master.callModule(
currentModule,
currentFunction,
currentWhere,
currentSet,
currentOIDs,
module),(display==null)?globalDisplay:display);
} catch (FunctionNotKnownException e) {
rval += "Function unknown: "+currentModule+'.'+currentFunction+"\n";
} catch (UnknownModuleException e) {
rval += "Module unknown: "+currentModule+"\n";
}
}
return rval;
}
}

View File

@ -0,0 +1,244 @@
/*
* @(#)Base64.java 1.5 03/12/19
*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package de.hsadmin.cliClientConnector;
/**
* Static methods for translating Base64 encoded strings to byte arrays
* and vice-versa.
*
* @author Josh Bloch
* @version 1.5, 12/19/03
* @see Preferences
* @since 1.4
*/
class Base64 {
/**
* Translates the specified byte array into a Base64 string as per
* Preferences.put(byte[]).
*/
static String byteArrayToBase64(byte[] a) {
return byteArrayToBase64(a, false);
}
/**
* Translates the specified byte array into an "aternate representation"
* Base64 string. This non-standard variant uses an alphabet that does
* not contain the uppercase alphabetic characters, which makes it
* suitable for use in situations where case-folding occurs.
*/
static String byteArrayToAltBase64(byte[] a) {
return byteArrayToBase64(a, true);
}
private static String byteArrayToBase64(byte[] a, boolean alternate) {
int aLen = a.length;
int numFullGroups = aLen/3;
int numBytesInPartialGroup = aLen - 3*numFullGroups;
int resultLen = 4*((aLen + 2)/3);
StringBuffer result = new StringBuffer(resultLen);
char[] intToAlpha = (alternate ? intToAltBase64 : intToBase64);
// Translate all full groups from byte array elements to Base64
int inCursor = 0;
for (int i=0; i<numFullGroups; i++) {
int byte0 = a[inCursor++] & 0xff;
int byte1 = a[inCursor++] & 0xff;
int byte2 = a[inCursor++] & 0xff;
result.append(intToAlpha[byte0 >> 2]);
result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
result.append(intToAlpha[byte2 & 0x3f]);
}
// Translate partial group if present
if (numBytesInPartialGroup != 0) {
int byte0 = a[inCursor++] & 0xff;
result.append(intToAlpha[byte0 >> 2]);
if (numBytesInPartialGroup == 1) {
result.append(intToAlpha[(byte0 << 4) & 0x3f]);
result.append("==");
} else {
// assert numBytesInPartialGroup == 2;
int byte1 = a[inCursor++] & 0xff;
result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
result.append(intToAlpha[(byte1 << 2)&0x3f]);
result.append('=');
}
}
// assert inCursor == a.length;
// assert result.length() == resultLen;
return result.toString();
}
/**
* This array is a lookup table that translates 6-bit positive integer
* index values into their "Base64 Alphabet" equivalents as specified
* in Table 1 of RFC 2045.
*/
private static final char intToBase64[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
/**
* This array is a lookup table that translates 6-bit positive integer
* index values into their "Alternate Base64 Alphabet" equivalents.
* This is NOT the real Base64 Alphabet as per in Table 1 of RFC 2045.
* This alternate alphabet does not use the capital letters. It is
* designed for use in environments where "case folding" occurs.
*/
private static final char intToAltBase64[] = {
'!', '"', '#', '$', '%', '&', '\'', '(', ')', ',', '-', '.', ':',
';', '<', '>', '@', '[', ']', '^', '`', '_', '{', '|', '}', '~',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '?'
};
/**
* Translates the specified Base64 string (as per Preferences.get(byte[]))
* into a byte array.
*
* @throw IllegalArgumentException if <tt>s</tt> is not a valid Base64
* string.
*/
static byte[] base64ToByteArray(String s) {
return base64ToByteArray(s, false);
}
/**
* Translates the specified "aternate representation" Base64 string
* into a byte array.
*
* @throw IllegalArgumentException or ArrayOutOfBoundsException
* if <tt>s</tt> is not a valid alternate representation
* Base64 string.
*/
static byte[] altBase64ToByteArray(String s) {
return base64ToByteArray(s, true);
}
private static byte[] base64ToByteArray(String s, boolean alternate) {
byte[] alphaToInt = (alternate ? altBase64ToInt : base64ToInt);
int sLen = s.length();
int numGroups = sLen/4;
if (4*numGroups != sLen)
throw new IllegalArgumentException(
"String length must be a multiple of four.");
int missingBytesInLastGroup = 0;
int numFullGroups = numGroups;
if (sLen != 0) {
if (s.charAt(sLen-1) == '=') {
missingBytesInLastGroup++;
numFullGroups--;
}
if (s.charAt(sLen-2) == '=')
missingBytesInLastGroup++;
}
byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
// Translate all full groups from base64 to byte array elements
int inCursor = 0, outCursor = 0;
for (int i=0; i<numFullGroups; i++) {
int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch3 = base64toInt(s.charAt(inCursor++), alphaToInt);
result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
result[outCursor++] = (byte) ((ch2 << 6) | ch3);
}
// Translate partial group, if present
if (missingBytesInLastGroup != 0) {
int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
if (missingBytesInLastGroup == 1) {
int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
}
}
// assert inCursor == s.length()-missingBytesInLastGroup;
// assert outCursor == result.length;
return result;
}
/**
* Translates the specified character, which is assumed to be in the
* "Base 64 Alphabet" into its equivalent 6-bit positive integer.
*
* @throw IllegalArgumentException or ArrayOutOfBoundsException if
* c is not in the Base64 Alphabet.
*/
private static int base64toInt(char c, byte[] alphaToInt) {
int result = alphaToInt[c];
if (result < 0)
throw new IllegalArgumentException("Illegal character " + c);
return result;
}
/**
* This array is a lookup table that translates unicode characters
* drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
* into their 6-bit positive integer equivalents. Characters that
* are not in the Base64 alphabet but fall within the bounds of the
* array are translated to -1.
*/
private static final byte base64ToInt[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
};
/**
* This array is the analogue of base64ToInt, but for the nonstandard
* variant that avoids the use of uppercase alphabetic characters.
*/
private static final byte altBase64ToInt[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
2, 3, 4, 5, 6, 7, 8, -1, 62, 9, 10, 11, -1 , 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 12, 13, 14, -1, 15, 63, 16, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 17, -1, 18, 19, 21, 20, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 22, 23, 24, 25
};
public static void main(String args[]) {
int numRuns = Integer.parseInt(args[0]);
int numBytes = Integer.parseInt(args[1]);
java.util.Random rnd = new java.util.Random();
for (int i=0; i<numRuns; i++) {
for (int j=0; j<numBytes; j++) {
byte[] arr = new byte[j];
for (int k=0; k<j; k++)
arr[k] = (byte)rnd.nextInt();
String s = byteArrayToBase64(arr);
byte [] b = base64ToByteArray(s);
if (!java.util.Arrays.equals(arr, b))
System.out.println("Dismal failure!");
s = byteArrayToAltBase64(arr);
b = altBase64ToByteArray(s);
if (!java.util.Arrays.equals(arr, b))
System.out.println("Alternate dismal failure!");
}
}
}
}

View File

@ -0,0 +1,18 @@
package de.hsadmin.cliClientConnector;
@SuppressWarnings("serial")
public class BusinessException
extends RuntimeException
{
public BusinessException(String msg)
{
super(msg);
}
public BusinessException(Exception exc)
{
super(exc.getMessage());
}
}

View File

@ -0,0 +1,490 @@
package de.hsadmin.cliClientConnector;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import de.hsadmin.core.model.Entity;
import de.hsadmin.core.model.GenericModuleImpl;
import de.hsadmin.core.model.ModuleInterface;
import de.hsadmin.core.model.TicketAuthentication;
import de.hsadmin.core.model.Transaction;
import de.hsadmin.core.model.onetier.TicketValidator;
/**
* actually this is the core of the CLI-Client. The other CLI-Client is just a
* rather simple HTTP Client that calls this Servlet.
*
* @author Christof Donat
*
*/
public class CLIClientConnectorServlet extends HttpServlet {
private static final long serialVersionUID = 7150004719303750077L;
public static final String version = "1.0.8 (2009/May/27 18:22)";
private Map<String, Class<?>> componentmap;
private Map<String, String> componentDescriptions;
private ArgumentParser parser;
/**
* Servlet initialization
*/
public void init(ServletConfig cfg) {
// init ticket validator
String validateURL = cfg.getInitParameter("proxyValidateUrl");
String serviceURL = cfg.getInitParameter("proxyServiceUrl");
TicketValidator.getInstance().initialize(validateURL, serviceURL);
// find components
String cstring = cfg.getInitParameter("Components");
String[] components = cstring.split(",");
componentmap = new HashMap<String, Class<?>>();
componentDescriptions = new HashMap<String, String>();
for (int i = 0; i < components.length; i++) {
// get everything for this component and create an entry.
try {
// component class
String classname = cfg.getInitParameter("ComponentClass_"
+ components[i]);
if (classname == null)
throw new NullPointerException(
"no class name found for Component "
+ components[i]);
Class<?> cls = Class.forName(classname);
componentmap.put(components[i], cls);
// description
String descr = cfg.getInitParameter("ComponentDescription_"
+ components[i]);
if (descr != null)
componentDescriptions.put(components[i], descr);
else
componentDescriptions.put(components[i], "");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// TODO: get username, password from http session
parser = new ArgumentParser(this);
}
/**
* set values to a given entity Object
*
* @param o
* the entity Object
* @param set
* Hashtable with names and values that sould be changed in o
*/
private void setValues(Object o, Map<String, String> set, ModuleInterface module) {
Iterator<String> keys = set.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
String[] ns = key.split("[.]", 2);
Object realO = o;
for (int i = 0; i < ns.length - 1; i++) {
Method[] m = realO.getClass().getMethods();
boolean oFound = false;
for (int j = 0; j < m.length; j++) {
if (m[j].getName().toLowerCase().equals(
"get" + ns[i].toLowerCase())) {
try {
realO = m[j].invoke(realO, (Object[]) null);
oFound = (realO != null);
break;
} catch (Exception e) {
new TechnicalException(e);
}
}
}
if (!oFound)
break;
}
Method[] m = realO.getClass().getMethods();
String value = set.get(key);
for (int j = 0; j < m.length; j++) {
if (!m[j].getName().toLowerCase().equals(
"set" + ns[ns.length - 1].toLowerCase()))
continue;
String type = m[j].getParameterTypes()[0].getCanonicalName();
try {
if (type.equals("java.lang.String"))
m[j].invoke(o, value);
else if (type.equals("java.lang.Integer"))
m[j].invoke(o, Integer.parseInt(value));
else if (type.equals("java.lang.Long"))
m[j].invoke(o, Long.parseLong(value));
else if (type.equals("java.lang.Boolean"))
m[j].invoke(o, Boolean.valueOf(value));
else if (type.equals("java.util.Date")) {
DateFormat df = DateFormat.getInstance();
m[j].invoke(o, df.parse(value));
} else {
Method m2 = module.getClass().getMethod(
"findByString", Class.class, String.class);
Object entity =
m2.invoke(module, m[j].getParameterTypes()[0], value);
if (entity != null)
m[j].invoke(o, entity);
else
throw new BusinessException(
"not object found for '" + value + "'");
}
} catch (Exception e) {
throw new TechnicalException(e); // TODO: this needs to be
// more specific for
// some cases
}
}
}
}
private String hasGetter(Class<?> eType, String name) {
String rval = null;
String[] ns = name.split("[.]", 2);
String n1 = ns[0];
Method meth = null;
for (Method m : eType.getMethods()) {
String n = m.getName();
if (n.startsWith("get")) {
String fn = m.getName().substring(3).toLowerCase();
if (fn != "class" && fn.equals(n1)) {
meth = m;
rval = fn;
break;
}
}
}
if (meth != null) {
Class<?> returnType = meth.getReturnType();
if (rval != null && ns.length > 1 && meth != null)
return hasGetter(returnType, ns[1]);
if (returnType.getCanonicalName().startsWith("de.hsadmin.mods")) {
try {
if (returnType.getMethod("getName") != null) {
return rval + ".name";
}
} catch (Exception e) {
// no method found
}
}
}
return rval;
}
/**
* builds a query from a where clause and some objectIDs.
*
* @param eType
* The class of the Entity Object for which the string should be
* built. We need this to call the static method
* "createQueryFromStringKey"
* @param where
* Hashtable with where parameters. Only objects which match all
* where parameters are found
* @param oids
* Only objects with one of these object IDs are found
*
* @return queryString a query string that can be used to select the
* required Objects
*/
private String buildQuery(Class<?> eType, Map<String, String> where,
ArrayList<String> oids) {
String rval = "";
boolean first = true;
Iterator<String> wkeys = where.keySet().iterator();
while (wkeys.hasNext()) {
String k = (String) wkeys.next();
String kname = hasGetter(eType, k);
if (kname != null) {
rval += (first ? "" : " and ")
+ "(obj." + Entity.escapeString(kname) + " = '" + Entity.escapeString(where.get(k)) + "')";
first = false;
}
}
String rv = "";
if (oids != null)
try {
Method m;
m = eType.getMethod("createQueryFromStringKey", String.class);
first = true;
for (String s : oids) {
rv += (first ? "" : " or ") + "("
+ (String) m.invoke(eType, s) + ")";
first = false;
}
if (rv != "" && rval != "")
rval = rval + " and (" + rv + ")";
else if (rv != "")
rval = rv;
} catch (Exception e) {
throw new TechnicalException(e);
}
return (rval == "") ? null : rval;
}
public class FunctionNotKnownException extends Exception {
private static final long serialVersionUID = -6330015688609717838L;
}
public class UnknownModuleException extends Exception {
private static final long serialVersionUID = 696641072107896601L;
}
private Object callAdd(Class<?> cls, Map<String, String> set, ModuleInterface module) {
Transaction transaction = module.getTransaction();
transaction.beginTransaction();
try {
Method m = module.getClass().getMethod("add", Entity.class);
Object o = cls.newInstance();
setValues(o, set, module);
m.invoke(module, o);
transaction.commitTransaction();
return null;
} catch (Exception e) {
transaction.rollbackTransaction();
// TODO: this needs to be more specific, but how?
throw new TechnicalException(e);
}
}
@SuppressWarnings("unchecked")
private List<Object> callSearch(Class<?> cls, Map<String, String> where,
ArrayList<String> oids, ModuleInterface module) {
try {
Method m = module.getClass().getMethod("search", Class.class,
String.class, String.class);
return (List<Object>) m.invoke(module, cls,
buildQuery(cls, where, oids), null);
} catch (Exception e) {
throw new TechnicalException(e); // TODO: this needs to be more
// specific, but how?
}
}
// / checks wheather all 'oids' are in 'list'
private void checkOids(List<Entity> list, List<String> oids) {
List<String> oidsNotFound = new ArrayList<String>();
for (String id : oids) {
boolean found = false;
for (Entity e : list) {
String foundKey = e.createStringKey();
if (foundKey.equals(id)) {
found = true;
break;
}
}
if (!found)
oidsNotFound.add(id);
}
if (oidsNotFound.size() > 0) {
throw new OidsNotFoundException(oids);
}
}
@SuppressWarnings("unchecked")
private List<Object> callUpdate(Class<?> cls, Map<String, String> where,
ArrayList<String> oids, Map<String, String> set,
ModuleInterface module) {
// better safe than sorry - alsd hso same behavior as UNIX rm
if (where.size() == 0 && oids.size() == 0)
throw new BusinessException(
"better safe than sorry - 'update' needs a -w/--where-query or object id");
Transaction tx = module.getTransaction();
tx.beginTransaction();
try {
Method m = module.getClass().getMethod("search", Class.class,
String.class, String.class);
List<Entity> list = (List<Entity>) m.invoke(module, cls,
buildQuery(cls, where, oids), null);
checkOids(list, oids);
Method m2 = module.getClass().getMethod("update", Entity.class);
for (int i = 0; i < list.size(); i++) {
Entity entity = list.get(i);
tx.detach(entity);
setValues(entity, set, module);
m2.invoke(module, entity);
}
tx.commitTransaction();
} catch (Exception e) {
tx.rollbackTransaction();
// TODO: this needs to be more specific, but how?
throw new TechnicalException(e);
}
return null;
}
@SuppressWarnings("unchecked")
private void callDelete(Class<?> cls, Map<String, String> where,
ArrayList<String> oids, ModuleInterface module) {
// better safe than sorry - also same behavior as UNIX rm
if (where.size() == 0 && oids.size() == 0)
throw new BusinessException(
"better safe than sorry - 'update' needs a -w/--where-query or object id");
Transaction tx = module.getTransaction();
tx.beginTransaction();
try {
Method m =
module.getClass().getMethod("search", Class.class, String.class, String.class);
List<Entity> list =
(List<Entity>) m.invoke(module, cls, buildQuery(cls, where, oids), null);
checkOids(list, oids);
Method m2 = module.getClass().getMethod("delete", Entity.class);
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
m2.invoke(module, o);
}
tx.commitTransaction();
} catch (Exception e) {
tx.rollbackTransaction();
// TODO: this needs to be more specific, but how?
throw new TechnicalException(e);
}
}
/**
* Call one of the EntitySessions methods
*
* @param moduleName
* Defines the Entity class that will be given to the
* EntitySession
* @param function
* Defines the method that will be called. The function can be
* "add", "search", "update" and "delete".
* @param where
* Reduces the set of Entity objects which the function operates
* on to those matched by the where parameters. Only for
* "search", "update" and "delete". Will be ignored otherwise.
* @param set
* Set these values on all Objects - only for "add" and "update".
* Will be ignored otherwise.
* @param oids
* Works on Objects with these IDs. Only for "search", "update"
* and "delete". Will be ignored for "add".
* @return foundObjects
* @throws FunctionNotKnownException
*/
public List<Object> callModule(String moduleName, String function,
Map<String, String> where, Map<String, String> set,
ArrayList<String> oids, ModuleInterface module)
throws FunctionNotKnownException, UnknownModuleException {
List<Object> rval = new ArrayList<Object>();
// handle calls to the virtual module "modules"
if (moduleName.equals("modules")) {
// only search, no manipulation is possible
if (function.equals("search")) {
Iterator<?> m = componentDescriptions.keySet().iterator();
while (m.hasNext()) {
String mn = (String) m.next();
rval.add(new ModuleModel(mn, componentDescriptions.get(mn)));
}
} else if (function.equals("version")) {
rval.add(new VersionModel(version));
} else {
throw new FunctionNotKnownException();
}
return rval;
}
// find the component for the named module
Class<?> cls = componentmap.get(moduleName);
if (cls == null)
throw (new UnknownModuleException());
// call the appropriate methods
if (function.equals("add"))
rval.add(callAdd(cls, set, module));
else if (function.equals("search")) {
List<Object> r = callSearch(cls, where, oids, module);
if (r != null)
return r;
} else if (function.equals("update")) {
List<Object> r = callUpdate(cls, where, oids, set, module);
if (r != null)
return callUpdate(cls, where, oids, set, module);
} else if (function.equals("delete")) {
callDelete(cls, where, oids, module);
} else
throw (new FunctionNotKnownException());
return rval;
}
/**
* handle put method
*/
public void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
try {
ModuleInterface module;
// check login
String auth = req.getHeader("authorization");
if (auth == null) {
// no login information at all - get it
resp.setHeader("WWW-Authenticate",
"Basic realm=\"CLIClientConnector\"");
resp.getOutputStream().println("login Failed.");
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
} else {
// parse login information
String[] a = auth.split(" ", 2);
String ticket = a[1];
byte[] decoded = Base64.base64ToByteArray(ticket.trim());
StringBuffer s = new StringBuffer();
for (int i = 0; i < decoded.length; i++)
s.append((char) decoded[i]);
a = s.toString().split(":", 2);
// try to log in
String login = a[0];
ticket = a[1];
module = null;
try {
if (TicketAuthentication.getInstance().login(login, ticket)) {
// login successful
module = new GenericModuleImpl(new Transaction(login));
// read arguments
BufferedReader read = req.getReader();
String tmpbuf;
ArrayList<String> arguments = new ArrayList<String>();
while ((tmpbuf = read.readLine()) != null) {
arguments.add(tmpbuf);
}
// actually handle the request and write result to output
String output = parser.parse(arguments, module);
resp.getWriter().write(output);
} else {
resp.addHeader("X-hsadmin-error", "authentication failed");
}
} catch (Exception e) {
resp.addHeader("X-hsadmin-error", "exception: " + e.getMessage());
} finally {
if (module != null && module.getTransaction() != null) {
module.getTransaction().close();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,19 @@
package de.hsadmin.cliClientConnector;
public class ModuleModel {
private String name;
private String description;
public ModuleModel(String name, String description) {
this.name = name;
this.description = description;
}
public String getName() {
return this.name;
}
public String getDescription() {
return this.description;
}
}

View File

@ -0,0 +1,25 @@
package de.hsadmin.cliClientConnector;
import java.util.List;
@SuppressWarnings("serial")
public class OidsNotFoundException
extends RuntimeException
{
static private String oidsAsString(List<String> oids)
{
StringBuilder oidsBuilder = new StringBuilder();
for ( String id: oids )
oidsBuilder.append(", " + id);
if ( oidsBuilder.length() > 0 )
return oidsBuilder.substring(2);
throw new RuntimeException( "an empty list of missing OIDS does not make sense" );
}
public OidsNotFoundException(List<String> oids)
{
super("OIDS not found: " + oidsAsString(oids));
}
}

View File

@ -0,0 +1,50 @@
package de.hsadmin.cliClientConnector;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import javax.persistence.RollbackException;
public class TechnicalException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TechnicalException(Throwable e) {
super(extractCauseMessage(e));
}
private static String extractCauseMessage(Throwable e) {
if (e.getMessage() != null && !(e instanceof RollbackException)) {
return e.getMessage();
}
else if (e instanceof InvocationTargetException || e instanceof RollbackException) {
String sqlState = null;
Throwable cause = e.getCause();
Throwable prev = null;
while (cause != null && cause != prev) {
prev = cause;
cause = prev.getCause();
if ((cause == null || cause == prev)
&& prev instanceof SQLException) {
SQLException sqlExc = (SQLException) prev;
sqlState = sqlExc.getSQLState();
cause = sqlExc.getNextException();
}
}
if (cause == null)
cause = prev;
if (cause != null)
return composeMessage(sqlState, cause.getMessage());
if (e instanceof InvocationTargetException) {
return composeMessage(sqlState, ((InvocationTargetException) e).getTargetException().getMessage());
}
}
return e.getClass() + " without detail message";
}
private static String composeMessage(String sqlState, String message) {
if (sqlState != null) return "SQLSTATE[" + sqlState + "] " + message;
return message;
}
}

View File

@ -0,0 +1,14 @@
package de.hsadmin.cliClientConnector;
public class VersionModel
{
private String version;
public VersionModel( String version) {
this.version = version;
}
public String getVersion() {
return this.version;
}
}

View File

@ -0,0 +1,361 @@
package de.hsadmin.core.model;
import java.util.LinkedList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import de.hsadmin.core.qserv.EntityProcessorFactory;
import de.hsadmin.core.qserv.Processor;
import de.hsadmin.core.qserv.QueueTask;
import de.hsadmin.mods.user.UnixUser;
/**
* Generic implementation of EntitySession interface.
*
* @author peter
*/
public abstract class AbstractModuleImpl implements ModuleInterface {
private static final long serialVersionUID = 2693948730004920437L;
private static Log log = LogFactory.getLog(AbstractModuleImpl.class);
private UnixUser loginUser;
private Transaction transaction;
public void construct(Transaction tx) {
transaction = tx;
}
/**
* apply access restriction to JPA-QL condition.
* @param entityClass
* @param loginUser
* @param condition
* @return
*/
private String restrict(Class<?> entityClass, UnixUser loginUser, String condition) {
String restriction = Entity.restriction(entityClass, loginUser);
if (restriction == null)
return condition;
if (condition != null && condition.length() > 0)
condition = "(" + condition + ") AND (" + restriction + ")";
else
condition = restriction;
return condition;
}
public Transaction getTransaction() {
return transaction;
}
public Entity initialize(Entity newEntity)
throws AuthorisationException {
newEntity.initialize(transaction.getEntityManager(), getLoginUser());
return newEntity;
}
public Entity add(Entity newEntity) throws HSAdminException {
// get the user who is logged in
UnixUser loginUser = getLoginUser();
// create record in database
log.debug("merging?");
newEntity.complete(transaction.getEntityManager(), loginUser);
try {
transaction.getEntityManager().persist(newEntity);
} catch (Throwable exc) {
log.error("exception: " + exc);
} finally {
log.debug("finally");
}
log.debug("merged");
// check rights
if (!newEntity.isWriteAllowedFor(loginUser))
throw new AuthorisationException(loginUser, "add", newEntity);
// generically create the processor
EntityProcessorFactory procFact = createProcessorFactory(newEntity.getClass());
if (procFact == null) {
log.debug("no procFact found :-(");
return newEntity;
}
log.debug("procFact found :-)");
Processor proc = procFact.createCreateProcessor(transaction.getEntityManager(), newEntity);
// queue the processor
queueProcessor(proc, loginUser, newEntity, "hinzugefuegt");
// return the added entity
return newEntity;
}
public Entity find(Class<? extends Entity> entityClass, Object key) throws HSAdminException {
Entity entity = transaction.getEntityManager().find(entityClass, key);
// check rights
UnixUser loginUser = getLoginUser();
if (!entity.isReadAllowedFor(loginUser))
throw new AuthorisationException(loginUser, "add", entity);
return entity;
}
public Entity findByString(Class<? extends Entity> entityClass, String key) throws HSAdminException {
// find a static method which creates the query
java.lang.reflect.Method method = null;
try {
method = entityClass.getDeclaredMethod("createQueryFromStringKey", String.class);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
method = null;
}
Entity entity;
if (method == null)
entity = transaction.getEntityManager().find(entityClass, key);
else {
// get the query expression from the static method (query part after
// WHERE)
String query;
try {
query = (String) method.invoke(null, key);
} catch (Exception e) {
throw new RuntimeException(e);
}
// perform the query
List<Entity> result = search(entityClass, query, null);
if (result.size() > 1)
throw new javax.persistence.NonUniqueResultException();
if (result.size() == 0)
return null;
entity = result.get(0);
// this was maybe thought as a fallback
// but is wrong when the above result is empty due to accessibility
// entity = em.find(entityClass, key);
}
// return (checking rights already done in search)
return entity;
}
public List<Entity> search(Class<? extends Entity> entityClass, String condition, String orderBy) throws HSAdminException {
// restrict query
UnixUser loginUser = getLoginUser();
condition = restrict(entityClass, loginUser, condition);
// get the entities name (query part from FROM to WHERE)
// TODO: beware SQL injections!!!
javax.persistence.Entity entityAnnot = entityClass.getAnnotation(javax.persistence.Entity.class);
String queryString = "SELECT obj FROM " + entityAnnot.name() + " obj";
if (condition != null && condition.length() > 0)
queryString += " WHERE " + condition;
// Fix problem with queries WHERE .. AND (FALSE) -- pe
if (condition != null && condition.contains("AND (FALSE)")) {
return new LinkedList<Entity>();
}
if (orderBy != null) {
queryString += " ";
queryString += orderBy;
}
// set parameters
EntityManager entityManager = transaction.getEntityManager();
entityManager.clear();
Query query = entityManager.createQuery(queryString);
setQueryParameter(query, queryString, "loginUser", loginUser);
setQueryParameter(query, queryString, "loginUserName", loginUser.getName());
setQueryParameter(query, queryString, "loginUserPac", loginUser.getPac());
// do query
try {
List<?> res = query.getResultList();
List<Entity> ret = new LinkedList<Entity>();
// remove entities where login user has no access rights
for (Object entity : res) {
if (entity instanceof Entity) {
Entity returnedEntity = (Entity) entity;
if (returnedEntity.isReadAllowedFor(getLoginUser())) {
ret.add(returnedEntity);
}
}
}
// return clean result
return ret;
} catch (Exception ex) {
return null;
}
}
public Entity update(Entity existingEntity) throws HSAdminException {
// get the user who is logged in
UnixUser loginUser = getLoginUser();
// update record in database
log.debug("merging:");
try {
existingEntity = existingEntity.merge(transaction.getEntityManager(), loginUser);
} catch (Throwable exc) {
log.error("exception: " + exc);
throw new RuntimeException(exc);
} finally {
log.debug("finally");
}
log.debug("merged!");
// check rights
if (!existingEntity.isWriteAllowedFor(loginUser))
throw new AuthorisationException(loginUser, "update",
existingEntity);
// generically create the processor
EntityProcessorFactory procFact =
createProcessorFactory(existingEntity.getClass());
if (procFact != null) {
log.debug("creating processor");
Processor proc = procFact.createUpdateProcessor(transaction.getEntityManager(), existingEntity);
// queue the processor
queueProcessor(proc, loginUser, existingEntity, "aktualisiert");
}
// return the merged entity
return existingEntity;
}
public void delete(Entity existingEntity) throws HSAdminException {
// get the user who is logged in
UnixUser user = getLoginUser();
// re-attach the entity
log.debug("merging:");
try {
existingEntity = transaction.getEntityManager().find(existingEntity.getClass(), existingEntity.id());
} catch (Throwable exc) {
log.error("exception: " + exc);
throw new RuntimeException(exc);
} finally {
log.debug("finally");
}
log.debug("merged!");
// check rights
if (!existingEntity.isWriteAllowedFor(loginUser))
throw new AuthorisationException(loginUser, "add", existingEntity);
// delete record in database
log.debug("deleting:");
try {
transaction.getEntityManager().remove(existingEntity);
} catch (Throwable exc) {
log.error("exception: " + exc);
} finally {
log.debug("finally");
}
log.debug("deleted!");
// generically create the processor
EntityProcessorFactory procFact = createProcessorFactory(existingEntity.getClass());
if (procFact == null) {
log.debug("no procFact found :-(");
return;
}
log.debug("procFact found :-)");
Processor proc = procFact.createDeleteProcessor(transaction.getEntityManager(), existingEntity);
// queue the processor
queueProcessor(proc, user, existingEntity, "geloescht");
}
public EntityProcessorFactory createProcessorFactory(Class<? extends Entity> entityClass) {
try {
String procFactName = entityClass.getCanonicalName()
+ "ProcessorFactory";
Class<?> procFactClass = Class.forName(procFactName);
if (procFactClass == null)
return null;
Object procFact = procFactClass.newInstance();
return (EntityProcessorFactory) procFact;
} catch (Exception exc) {
log.error("exception creating instance: " + exc);
return null;
}
}
/**
* get current login user from session context.
* @return
*/
public UnixUser getLoginUser() {
if (loginUser == null) {
log.debug("getting login user");
Query userQuery = transaction.getEntityManager().createQuery("SELECT u FROM UnixUsers u WHERE u.name=:name");
userQuery.setParameter("name", transaction.getLoginName());
loginUser = (UnixUser) userQuery.getSingleResult();
log.debug("found login user: " + loginUser.getName());
}
return loginUser;
}
public void queueProcessor(Processor proc, UnixUser user, Entity entity, String action) {
log.debug("queueing processor for user " + user.getId() + "/"
+ user.getUserId() + "/" + user.getName());
EntityInfo entityInfo =
entity.getClass().getAnnotation(EntityInfo.class);
String entityTypeName =
entityInfo != null ? entityInfo.name() : entity.getClass().getSimpleName();
StringBuilder details = new StringBuilder();
// TODO: add properties of entity to details
String title =
entityTypeName + " (" + entity.createStringKey() + ") " + action;
QueueTask task = new QueueTask(user, title, details.toString(), proc);
transaction.getEntityManager().persist(task);
transaction.enqueue(entity.getHiveName(), task);
log.debug("processor queued");
}
public String toString(StackTraceElement[] stackTrace) {
StringBuilder stack = new StringBuilder();
for (StackTraceElement e : stackTrace)
stack.append(e.getFileName() + ":" + e.getLineNumber() + "\n");
return stack.toString();
}
/**
* determines if the login user is a hostmaster.
* @return
*/
public boolean isHostmaster() {
// TODO: dummy
return false;
}
public static void setQueryParameter(Query query, String queryString,
String argName, Object argValue) {
int argLen = argName.length();
int iMax = queryString.length();
int i = 0;
while ((i = queryString.indexOf(argName, i)) >= 0) {
if ((i + argLen) >= iMax || queryString.charAt(i + argLen) < 'A') {
query.setParameter(argName, argValue);
break;
}
++i;
}
}
}

View File

@ -0,0 +1,15 @@
package de.hsadmin.core.model;
public class AuthenticationException extends HSAdminException {
private static final long serialVersionUID = 6242824365822822456L;
public AuthenticationException(Exception e) {
super(e);
}
public AuthenticationException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,56 @@
package de.hsadmin.core.model;
import de.hsadmin.mods.user.UnixUser;
public class AuthorisationException extends HSAdminException {
private static final long serialVersionUID = -8125905071037488732L;
private UnixUser user;
private String method;
private Entity entity;
private String field;
public UnixUser getUser() {
return user;
}
public String getMethod() {
return method;
}
public Entity getEntity() {
return entity;
}
public String getField() {
return field;
}
public AuthorisationException(UnixUser user, String method) {
super("nicht authorisiert fuer " + method + "()");
this.user = user;
this.method = method;
}
public AuthorisationException(UnixUser user, String method, Entity entity) {
super("nicht authorisiert fuer " + method + "("
+ entity.createStringKey() + ")");
this.user = user;
this.method = method;
this.entity = entity;
}
public AuthorisationException(UnixUser user, String method, Entity entity,
String field) {
super("nicht authorisiert fuer " + method + "("
+ entity.createStringKey() + "." + field + ")");
this.user = user;
this.method = method;
this.entity = entity;
this.field = field;
}
}

View File

@ -0,0 +1,249 @@
package de.hsadmin.core.model;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.persistence.EntityManager;
import de.hsadmin.mods.user.UnixUser;
public abstract class Entity {
/**
* trims whitespace from both ends, but a null remains null.
* @param field
* @return
*/
public static String trim(String field) {
if (field == null)
return field;
return field.trim();
}
/**
* trims whitespace from both ends, returns null for a resulting empty
* string or null.
* @param field
* @return
*/
public static String trimToNull(String field) {
if (field == null)
return field;
field = field.trim();
if (field.length() == 0)
return null;
return field;
}
/**
* trims whitespace from both ends, returns an empty string for null
* @param field
* @return
*/
public static String trimToEmpty(String field) {
if (field == null)
return "";
field = field.trim();
return field;
}
/**
* Creates a JPA-QL query string from a human readable string representing a
* key.
*
* Such a static method is to be implemented by every entity class which has
* a human readable key different from "id".
*
* @param humanKey
* A human readable key representing the entity. E.g.
* "info@example.com" for an E-Mail-Address.
*
* @return jpaQLQuery the matching JPA-QL query
*/
public static String createQueryFromStringKey(String humanKey) throws HSAdminException {
return "id=" + humanKey;
}
/**
* escapes a String so that it can be used for SQL statements
* @param str a sting that should be usable as a String in an SQLStatement
* @return the escapedString
*/
public static String escapeString(String str) {
str = str.replaceAll("\"", "\\\"");
str = str.replaceAll("\'", "\\'");
return str;
}
/**
* Calls the static method of the Entity subclass to get a query
* restriction.
*
* @return a restricting JPA-QL expression to limit access to entities
*/
public static String restriction(Class<?> entityClass, UnixUser loginUser) {
// hostmasters don't get any restriction
if (loginUser.hasHostmasterRole())
return null;
// find a static method which creates the query
java.lang.reflect.Method method = null;
try {
method = entityClass.getDeclaredMethod("restriction");
} catch (SecurityException e) {
throw new RuntimeException(
"unexpected SecurityException in restriction()");
} catch (NoSuchMethodException e) {
// don't grant any access
return "FALSE";
}
// get the restriction from a static method of the Entity class
String restriction = "FALSE";
try {
restriction = (String) method.invoke(null);
} catch (Exception e) {
throw new RuntimeException(
"unexpected Exception in Entity-restriction() implementation");
}
return restriction;
}
/**
* Creates a human readable string representing a key to this entity.
*
* @return humanReadableString A human readable string which can be used as
* a key to this entity. This string can also be used with the
* static method createQueryFromStringKey which has to be supported
* by all entity
*/
public abstract String createStringKey();
/**
* returns true if entity is not yet stored to the database, false otherwise.
* @return
*/
public abstract boolean isNew();
/**
* returns the unique database if
*/
public abstract long id();
/**
* returns true if the argument entity has the same database id
* @param entity
* @return
*/
public boolean sameIdAs(Entity entity) {
if (entity == null)
return false;
if (getClass() != entity.getClass())
return false;
return id() == entity.id();
}
/**
* returns true if entity is not yet stored to the database, false otherwise.
* @return
*/
@javax.persistence.Transient
public boolean getNew() {
return isNew();
}
/**
* Initializes a newly created entity.
*
* This method makes it possible to initialize fields of entities using the
* login user and database access.
* @param em
* @param loginUser
*/
public void initialize(EntityManager em, UnixUser loginUser) {
}
/**
* completes the (new) entity before it gets stored to the database
* @param em
* @param loginUser
*/
public void complete(EntityManager em, UnixUser loginUser) {
}
/**
* merges this entity with the database, keeping transient members which are
* otherwise nulled.
*
* Usually subclasses load the attached entity with same id and update all
* fields to which the login user has access, but no other fields. Then the
* attached entity is returned instead of this entity.
* @param em
* @param loginUser
*/
public Entity merge(EntityManager em, UnixUser loginUser) {
return em.merge(this);
}
/**
* determines whether the given user has full read access on all merged
* fields of this entity
* @param loginUser
* @return
*/
public boolean isReadAllowedFor(UnixUser loginUser) {
return loginUser.hasHostmasterRole();
}
/**
* determines whether the given user has full write access on all merged
* fields of this entity
* @param loginUser
* @return
*/
public boolean isWriteAllowedFor(UnixUser loginUser) {
return loginUser.hasHostmasterRole();
}
/**
* returns the hive name in which this entity resists or null if entity
* is new or does not need a hive.
* @return
*/
public String getHiveName() {
return null;
}
/**
* returns the UnixUser who owns this entity (and thus has broad access to it
* @param em
* @return
*/
public abstract UnixUser owningUser(EntityManager em);
/**
* Clonable::clone did result in javasisst errors (duplicate method) since
* JBoss 5.1.
* This is just for testing, it does not use the proper class loader!
*/
public <T extends Entity> T replicate() {
try {
ByteArrayOutputStream baOut = new ByteArrayOutputStream();
ObjectOutputStream oOut = new ObjectOutputStream(baOut);
oOut.writeObject(this);
byte[] buffer = baOut.toByteArray();
ByteArrayInputStream baIn = new ByteArrayInputStream(buffer);
ObjectInputStream oIn = new ObjectInputStream(baIn);
@SuppressWarnings("unchecked")
T clone = (T) oIn.readObject();
return clone;
} catch (Exception exc) {
throw new RuntimeException(exc);
}
}
}

View File

@ -0,0 +1,12 @@
package de.hsadmin.core.model;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(value=RetentionPolicy.RUNTIME)
public @interface EntityInfo
{
/// human readable identifier of the entity
String name();
}

View File

@ -0,0 +1,41 @@
package de.hsadmin.core.model;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class EntitySessionHelper {
private static Log log = LogFactory.getLog(EntitySessionHelper.class);
/**
* helper method to create a wrapper for checking the rights according to
* the entity class.
* @param entityClass
* @return
*/
public static AbstractModuleImpl createEntitySessionWrapper(Class<? extends Entity> entityClass) {
// get in instance
AbstractModuleImpl impl = null;
try {
// determine wrapper class
ModuleImpl wrapperAnnot = entityClass.getAnnotation(ModuleImpl.class);
Class<?> wrapperClass = null;
if (wrapperAnnot != null) {
wrapperClass = wrapperAnnot.value();
} else {
wrapperClass = Class.forName(entityClass.getCanonicalName() + "ModuleImpl");
}
// instantiate wrapper
impl = (AbstractModuleImpl) wrapperClass.newInstance();
} catch (ClassNotFoundException exc) {
log.info("entity class '"
+ entityClass.getCanonicalName()
+ "' has no session wrapper => using restrictive default access rights");
impl = new SecureDefaultModuleImpl();
} catch (Exception exc) {
throw new RuntimeException(exc);
}
return impl;
}
}

View File

@ -0,0 +1,99 @@
package de.hsadmin.core.model;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class GenericModuleImpl implements ModuleInterface {
private static final Log log = LogFactory.getLog(GenericModuleImpl.class);
private Transaction tx;
public GenericModuleImpl(Transaction transaction) {
tx = transaction;
}
public Transaction getTransaction() {
return tx;
}
@Override
public Entity initialize(Entity newEntity) throws HSAdminException {
log.trace("initialize(" + newEntity + ")");
AbstractModuleImpl wrapper =
EntitySessionHelper.createEntitySessionWrapper(newEntity.getClass());
wrapper.construct(tx);
return wrapper.initialize(newEntity);
}
@Override
public Entity add(Entity newEntity) throws HSAdminException {
if (!newEntity.isNew())
throw new HSAdminException("cannot add an already persistent entity");
log.trace("add(" + newEntity + ")");
AbstractModuleImpl wrapper =
EntitySessionHelper.createEntitySessionWrapper(newEntity.getClass());
wrapper.construct(tx);
Entity result = null;
try {
result = wrapper.add(newEntity);
return result;
} catch (Exception e) {
throw new HSAdminException(e);
}
}
@Override
public Entity find(Class<? extends Entity> entityClass, Object key) throws HSAdminException {
log.trace("find(" + entityClass + ", " + key + ")");
AbstractModuleImpl wrapper = EntitySessionHelper.createEntitySessionWrapper(entityClass);
wrapper.construct(tx);
return wrapper.find(entityClass, key);
}
@Override
public Entity findByString(Class<? extends Entity> entityClass, String key) throws HSAdminException {
log.trace("find(" + entityClass + ", " + key + ")");
AbstractModuleImpl wrapper = EntitySessionHelper.createEntitySessionWrapper(entityClass);
wrapper.construct(tx);
return wrapper.findByString(entityClass, key);
}
@Override
public List<Entity> search(Class<? extends Entity> entityClass, String condition, String orderBy) throws HSAdminException {
log.trace("search(" + entityClass + ", " + condition + ")");
AbstractModuleImpl wrapper = EntitySessionHelper.createEntitySessionWrapper(entityClass);
wrapper.construct(tx);
return wrapper.search(entityClass, condition, orderBy);
}
@Override
public Entity update(Entity existingEntity) throws HSAdminException {
if (existingEntity.isNew())
return add(existingEntity);
log.debug("update(" + existingEntity + ")");
AbstractModuleImpl wrapper = EntitySessionHelper.createEntitySessionWrapper(existingEntity.getClass());
wrapper.construct(tx);
try {
return wrapper.update(existingEntity);
} catch (Exception e) {
throw new HSAdminException(e);
}
}
@Override
public void delete(Entity existingEntity) throws HSAdminException {
log.trace("delete(" + existingEntity + ")");
AbstractModuleImpl wrapper =
EntitySessionHelper.createEntitySessionWrapper(existingEntity.getClass());
wrapper.construct(tx);
try {
wrapper.delete(existingEntity);
} catch (Exception e) {
throw new HSAdminException(e);
}
}
}

View File

@ -0,0 +1,19 @@
package de.hsadmin.core.model;
public class HSAdminException extends Exception {
private static final long serialVersionUID = -5082179267383474532L;
public HSAdminException(String message) {
super(message);
}
public HSAdminException(Exception e) {
super(e);
}
public HSAdminException(String message, Exception aExc) {
super(message, aExc);
}
}

View File

@ -0,0 +1,10 @@
package de.hsadmin.core.model;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface ModuleImpl
{
Class<?> value();
}

View File

@ -0,0 +1,50 @@
package de.hsadmin.core.model;
import java.util.List;
/**
* Represents a CRUD (Create, Retrieve, Update, Delete) interface for generic
* entity instances.
* @author peter
*/
public interface ModuleInterface {
public Transaction getTransaction();
/**
* initializes a newly created entity.
*/
public Entity initialize(Entity newEntity) throws HSAdminException;
/**
* Adds a new entity instance to the model.
*/
public Entity add(Entity newEntity) throws HSAdminException;
/**
* Finds an entity instance in the model, using its primary key.
*/
public Entity find(Class<? extends Entity> entityClass, Object key) throws HSAdminException;
/**
* Finds an entity instance in the model, using its primary key in a String
* representation.
*/
public Entity findByString(Class<? extends Entity> entityClass, String key) throws HSAdminException;
/**
* Searches entity instances in the model, using a simplified JPA-QL query.
*/
public List<Entity> search(Class<? extends Entity> entityClass, String query, String orderBy) throws HSAdminException;
/**
* Updates an existing entity in the model.
*/
public Entity update(Entity existingEntity) throws HSAdminException;
/**
* Deletes an existing entity from the model.
*/
public void delete(Entity existingEntity) throws HSAdminException;
}

View File

@ -0,0 +1,12 @@
package de.hsadmin.core.model;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/// specifies pre-filters (JPAQL) for several roles
@Retention(value=RetentionPolicy.RUNTIME)
public @interface SearchFilter
{
/// an additional JPA condition to add to the WHERE clause
String value();
}

View File

@ -0,0 +1,105 @@
package de.hsadmin.core.model;
import java.util.LinkedList;
import java.util.List;
/**
* allows access only for hostmasters, used as fallback wrapper.
*/
public class SecureDefaultModuleImpl extends AbstractModuleImpl {
private static final long serialVersionUID = 4567381515459292565L;
@Override
public Entity initialize(Entity newEntity) throws AuthorisationException {
return super.initialize(newEntity);
}
@Override
public Entity find(Class<? extends Entity> entityClass, Object key) throws HSAdminException {
Entity entity = super.find(entityClass, key);
if (entity != null && !entity.isReadAllowedFor(getLoginUser()))
throw new AuthorisationException(getLoginUser(), "find");
return entity;
}
@Override
public Entity findByString(Class<? extends Entity> entityClass, String key) throws HSAdminException {
Entity entity = super.findByString(entityClass, key);
if (entity != null && !entity.isReadAllowedFor(getLoginUser()))
throw new AuthorisationException(getLoginUser(), "findByString");
return entity;
}
@Override
public List<Entity> search(Class<? extends Entity> entityClass, String condition, String orderBy)
throws HSAdminException {
// restrict query to entities where the loginUser could have rights on
SearchFilter filterAnnot;
if (!getLoginUser().hasHostmasterRole()
&& (filterAnnot = getSecurityFilterAnnotation(entityClass)) != null) {
String securityCondition = filterAnnot.value();
if (condition != null && condition.length() > 0)
condition = "(" + condition + ")" + " AND ( "
+ securityCondition + ")";
else
condition = securityCondition;
}
// do query
List<Entity> res = super.search(entityClass, condition, orderBy);
List<Entity> ret = new LinkedList<Entity>();
// remove entities where login user has no access rights
if (res != null) {
for (Entity entity : res) {
Entity returnedEntity = entity;
if (returnedEntity.isReadAllowedFor(getLoginUser()))
ret.add(returnedEntity);
}
}
// return clean result
return ret;
}
// helper method to get annotation from class or superclass
private SearchFilter getSecurityFilterAnnotation(Class<?> entityClass) {
SearchFilter ret;
while (entityClass != null) {
ret = (SearchFilter) entityClass.getAnnotation(SearchFilter.class);
if (ret != null)
return ret;
entityClass = entityClass.getSuperclass();
}
return null;
}
@Override
public Entity add(Entity newEntity) throws HSAdminException {
// access rights checking is done by base class
return super.add(newEntity);
}
@Override
public Entity update(Entity existingEntity) throws HSAdminException {
// access rights checking is done by base class
return super.update(existingEntity);
}
@Override
public void delete(Entity detachedEntity) throws HSAdminException {
// get the entity from the database
Entity attachedEntity = getTransaction().getEntityManager().find(detachedEntity.getClass(),
detachedEntity.id());
// does the login user have the right to delete?
if (!attachedEntity.isWriteAllowedFor(getLoginUser()))
throw new AuthorisationException(getLoginUser(), "delete",
detachedEntity);
super.delete(attachedEntity);
}
}

View File

@ -0,0 +1,17 @@
package de.hsadmin.core.model;
import de.hsadmin.core.model.onetier.TicketValidator;
public class TicketAuthentication {
private static TicketAuthentication auth = new TicketAuthentication();
public static TicketAuthentication getInstance() {
return auth;
}
public boolean login(String login, String ticket) throws AuthenticationException {
return TicketValidator.getInstance().validateTicket(login, ticket);
}
}

View File

@ -0,0 +1,179 @@
package de.hsadmin.core.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
//import org.hibernate.Session;
import de.hsadmin.cliClientConnector.TechnicalException;
import de.hsadmin.core.model.onetier.PersistenceManager;
import de.hsadmin.core.qserv.QueueClient;
import de.hsadmin.core.qserv.QueueTask;
public class Transaction {
private static final Log log = LogFactory.getLog(Transaction.class);
private EntityManager entityManager;
private QueueConnectionFactory queueConnectionFactory;
private String loginName;
private Map<String, QueueTaskStore> taskStores;
private boolean transactionActive;
private InitialContext ctx;
public Transaction(String loginName) {
transactionActive = false;
this.entityManager = PersistenceManager.getEntityManager("hsadmin");
this.loginName = loginName;
taskStores = new HashMap<String, QueueTaskStore>();
try {
ctx = new InitialContext();
Context env = (Context) ctx.lookup("java:comp/env");
queueConnectionFactory = (QueueConnectionFactory) env.lookup("jms/QueueCF");
} catch (NamingException e) {
log.fatal(e);
e.printStackTrace();
throw new TechnicalException(e);
}
}
public EntityManager getEntityManager() {
return entityManager;
}
public QueueConnectionFactory getQueueConnectionFactory() {
return queueConnectionFactory;
}
public Queue lookupJMSQueue(String queueName) {
if (ctx != null) {
try {
Context env = (Context) ctx.lookup("java:comp/env");
return (Queue) env.lookup("jms/" + queueName);
} catch (NamingException e) {
log.fatal(e);
e.printStackTrace();
return null;
}
}
return null;
}
public String getLoginName() {
if (loginName != null) return loginName;
return null;
}
public void enqueue(String hiveName, QueueTask task) {
QueueTaskStore taskStore = taskStores.get(hiveName);
if (taskStore == null) {
taskStore = new QueueTaskStore();
taskStores.put(hiveName, taskStore);
}
taskStore.add(task);
}
private void sendAll(EntityTransaction transaction) {
boolean firstHive = true;
for (String hive : taskStores.keySet()) {
QueueTaskStore store = taskStores.get(hive);
String queueName = "hsadminSystem-" + hive;
Queue jmsSystemQueue = lookupJMSQueue(queueName);
QueueClient qClient = null;
try {
qClient = new QueueClient(queueConnectionFactory, jmsSystemQueue);
if (firstHive) {
firstHive = false;
transaction.commit();
}
for (QueueTask task : store.getTasks()) {
qClient.send(task);
}
} catch (Exception e) {
throw new TechnicalException(e);
} finally {
store.clear();
if (qClient != null) qClient.close();
}
}
if (firstHive) {
try {
transaction.commit();
} catch (Exception e) {
throw new TechnicalException(e);
}
}
}
public void beginTransaction() {
transactionActive = true;
entityManager.getTransaction().begin();
}
public void commitTransaction() {
sendAll(entityManager.getTransaction());
transactionActive = false;
}
public void rollbackTransaction() {
taskStores.clear();
transactionActive = false;
try {
entityManager.getTransaction().rollback();
} catch (IllegalStateException e) {
log.info(e);
}
}
public void close() {
if (transactionActive) {
rollbackTransaction();
}
entityManager.close();
}
/**
* Detach entities from hibernate session.
* Used to detach entities before update. Makes it possible to compare
* old and new attribute values.
*/
public void detach(Entity entity) {
// TODO: replace hibernate specific implmentation
// org.hibernate.Session hSession = (Session) entityManager.getDelegate();
// hSession.evict(entity);
if (entityManager instanceof OpenJPAEntityManager) {
OpenJPAEntityManager openjpaEM = (OpenJPAEntityManager) entityManager;
openjpaEM.detach(entity);
}
}
class QueueTaskStore {
private List<QueueTask> taskList;
QueueTaskStore() {
taskList = new ArrayList<QueueTask>();
}
public void clear() {
taskList = new ArrayList<QueueTask>();
}
void add(QueueTask t) {
taskList.add(t);
}
Iterable<QueueTask> getTasks() {
return taskList;
}
}
}

View File

@ -0,0 +1,43 @@
package de.hsadmin.core.model.onetier;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class PersistenceManager {
private static PersistenceManager instance;
private Map<String, EntityManagerFactory> persistenceUnits;
private PersistenceManager() {
persistenceUnits = new HashMap<String, EntityManagerFactory>();
}
private EntityManagerFactory getEMF(String persistUnitName) {
EntityManagerFactory emf = persistenceUnits.get(persistUnitName);
if (emf == null) {
emf = Persistence.createEntityManagerFactory(persistUnitName);
persistenceUnits.put(persistUnitName, emf);
}
return emf;
}
public static EntityManager getEntityManager(String persistUnitName) {
PersistenceManager pm = PersistenceManager.getInstance();
EntityManagerFactory emf = pm.getEMF(persistUnitName);
return emf.createEntityManager();
}
private static PersistenceManager getInstance() {
if (instance == null) {
instance = new PersistenceManager();
}
return instance;
}
}

View File

@ -0,0 +1,96 @@
package de.hsadmin.core.model.onetier;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import de.hsadmin.core.model.AuthenticationException;
public class TicketValidator {
private static final Log log = LogFactory.getLog(TicketValidator.class);
private static TicketValidator instance;
private String proxyValidateURL;
private String proxyServiceURL;
private TicketValidator() {
proxyServiceURL = null;
proxyValidateURL = null;
}
public static TicketValidator getInstance() {
if (instance == null) {
instance = new TicketValidator();
}
return instance;
}
public void initialize(String validateURL, String serviceURL) {
proxyServiceURL = serviceURL;
proxyValidateURL = validateURL;
}
public boolean validateTicket(String runAsUser, String ticket) throws AuthenticationException {
String ticketUser = validateTicket(ticket);
if (runAsUser != null &&
(runAsUser.equals(ticketUser) // user himself
|| (ticketUser.length() == 5 && runAsUser.startsWith(ticketUser))
// pac-admin
|| ticketUser.length() == 2) // hostmaster
// TODO: add test for member-account
) {
return true;
} else {
throw new AuthenticationException("User " + ticketUser + " is not allowed to run as " + runAsUser);
}
}
public String validateTicket(String ticket) throws AuthenticationException {
if (proxyServiceURL == null || proxyServiceURL == null) {
log.fatal("TicketValidator is not initialized.");
throw new RuntimeException("TicketValidator is not initialized.");
}
try {
URL url = new URL(proxyValidateURL + "?service=" + proxyServiceURL + "&ticket=" + ticket);
URLConnection httpConnection = url.openConnection();
httpConnection.connect();
InputStream inputStream = httpConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String nextLine = reader.readLine();
while (nextLine != null) {
if (nextLine.contains("<cas:user>")) {
String user = extractUser(nextLine);
inputStream.close();
return user;
}
nextLine = reader.readLine();
}
inputStream.close();
log.debug("Ticket validation failed: " + ticket);
throw new AuthenticationException("Invalid Ticket: " + ticket);
} catch (MalformedURLException e) {
log.fatal(e);
throw new AuthenticationException(e.getMessage());
} catch (IOException e) {
log.fatal(e);
throw new AuthenticationException(e.getMessage());
}
}
private String extractUser(String nextLine) {
int start = nextLine.indexOf("<cas:user>");
int end = nextLine.indexOf("</cas:user>");
String user = nextLine.substring(start + 10, end);
return user;
}
}

View File

@ -0,0 +1,17 @@
package de.hsadmin.core.qserv;
import de.hsadmin.core.model.Transaction;
abstract public class AbstractProcessor implements Processor {
private static final long serialVersionUID = -2401718681212973276L;
@Override
abstract public Object process() throws ProcessorException;
@Override
public void finalize(Transaction transaction, QueueTask task) throws ProcessorException {
task.done();
}
}

View File

@ -0,0 +1,162 @@
package de.hsadmin.core.qserv;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
public class CommandShell
{
private static boolean bExecute = true; // really execute or just store command and stdin?
private static String executedCommands; // stored command and stdin
private static String[] aEnvironment; // stored environment
/** Set mode of real execution or just storing the command and stdin.
*
* @param bExec
* specifies whether shell commands should really be executed (true) or not (false)
*/
public static void setExecute( boolean bExec )
{
bExecute = bExec;
}
/** Returns and clears the last command which should have been executed.
*
* @return
* Last command, plus "<<EOF\n" + stdin + "EOF" if stdin was given.
*/
public static String popLastCommand()
{
String aLastCommand = executedCommands;
executedCommands = null;
return aLastCommand != null ? aLastCommand.trim() : null;
}
/** Returns and clears the environment which ist currently used for commands.
*
* @return
* Most recent command environment.
*/
public static String[] popEnvironment()
{
String[] aLastEnvironment = aEnvironment;
aEnvironment = null;
return aLastEnvironment;
}
public static void setEnvironment( String[] env )
{
aEnvironment = env;
}
/** Execute the given command by a shell.
*
* @throws ShellException
* if an execution error has occured.
*/
public static String execute( String command )
throws ShellException
{
return execute( command, null );
}
/** Execute the given command by a shell including stdin.
*
* @throws ShellException
* if an execution error has occured.
*/
public static String execute( String command, String stdInput )
throws ShellException
{
Process backend = null;
String callOutput = null;
int exitCode = 0;
try
{
String logCommand = command;
if ( stdInput != null ) //&& stdInput.length() > 0 )
logCommand += "<<EOF\n" + stdInput + "EOF";
logCommand += "\n";
// add to command buffer (used in tests)
if ( executedCommands == null )
executedCommands = logCommand;
else
executedCommands += logCommand;
if ( bExecute )
{
// TODO logging
System.out.println("--- shell command: ---" );
System.out.println( logCommand );
String[] cmdArray = { "/bin/bash", "-c", command };
backend = Runtime.getRuntime().exec(cmdArray, aEnvironment);
if ( stdInput != null )
{
OutputStream stdInputStream = backend.getOutputStream();
PrintWriter stdInputWriter = new PrintWriter(stdInputStream);
stdInputWriter.print(stdInput);
stdInputWriter.close();
stdInputStream.close();
}
callOutput = readProcessStream(backend.getInputStream());
exitCode = backend.waitFor();
// TODO logging
System.out.println( "RET: " + exitCode );
if (exitCode != 0)
{
String aErr = readProcessStream(backend.getErrorStream());
// TODO logging
System.out.println( "ERR: " + aErr );
System.out.println("--- done. ---" );
throw new ShellException( exitCode, aErr );
}
// TODO logging
System.out.println("--- done. ---" );
}
}
catch (IOException e)
{
throw new ShellException();
}
catch (InterruptedException e)
{
throw new ShellException();
}
if ( callOutput != null )
{
// int nLen = callOutput.length();
// if ( nLen > 0 && callOutput.charAt(nLen-1) == '\n' )
// callOutput = callOutput.substring(0, nLen-1);
return callOutput.trim();
}
return null;
}
private static String readProcessStream(InputStream stream) throws IOException
{
BufferedReader reader = new BufferedReader(
new InputStreamReader(stream));
StringBuffer textBuff = new StringBuffer();
String textLine = reader.readLine();
while (textLine != null)
{
textBuff.append(textLine);
textBuff.append('\n');
textLine = reader.readLine();
}
reader.close();
return textBuff.toString();
}
}

View File

@ -0,0 +1,30 @@
package de.hsadmin.core.qserv;
import java.util.ArrayList;
import java.util.List;
public class CompoundProcessor extends AbstractProcessor {
private static final long serialVersionUID = 5718623579674305929L;
private List<Processor> aProcessors;
public CompoundProcessor(Processor... aProcessor) {
aProcessors = new ArrayList<Processor>();
for (Processor aP : aProcessor) {
aProcessors.add(aP);
}
}
public Object process() throws ProcessorException {
for (Processor aProcessor : aProcessors) {
aProcessor.process();
}
return null;
}
public void appendProcessor(Processor aProcessor) {
aProcessors.add(aProcessor);
}
}

View File

@ -0,0 +1,22 @@
package de.hsadmin.core.qserv;
public class CopyFileProcessor extends AbstractProcessor {
private static final long serialVersionUID = 1741419610410712714L;
private Processor internal;
public CopyFileProcessor(String source, String target, String owner, String group, String modeMask) {
internal = new ShellProcessor(
"cp " + source + " " + target + " && " +
"chown " + owner + ":" + group + " " + target + " && " +
"chmod " + modeMask + " " + target
);
}
@Override
public Object process() throws ProcessorException {
return internal.process();
}
}

View File

@ -0,0 +1,25 @@
package de.hsadmin.core.qserv;
import java.util.Map;
public class CreateFileProcessor extends AbstractProcessor {
private static final long serialVersionUID = -2947609532975712444L;
private CompoundProcessor compoundProcessor;
public CreateFileProcessor(String templateName, Map<String, String> templateValues, String targetPath, String owner, String group, String modeMask) throws ProcessorException {
TemplateProcessor templateProcessor = new TemplateProcessor(templateName, templateValues, targetPath, false);
ShellProcessor shellProcessor =
new ShellProcessor(
"chown " + owner + ":" + group + " " + targetPath + " && " +
"chmod " + modeMask + " " + targetPath);
compoundProcessor = new CompoundProcessor(templateProcessor, shellProcessor);
}
@Override
public Object process() throws ProcessorException {
return compoundProcessor.process();
}
}

View File

@ -0,0 +1,22 @@
package de.hsadmin.core.qserv;
import javax.persistence.EntityManager;
import de.hsadmin.core.model.Entity;
/**
* Most processor factories need only these methods.
*
* @author peter
*/
public interface EntityProcessorFactory {
public <T extends Entity> Processor createCreateProcessor(EntityManager em,
T entity) throws ProcessorException;
public <T extends Entity> Processor createUpdateProcessor(EntityManager em,
T newEntity) throws ProcessorException;
public <T extends Entity> Processor createDeleteProcessor(EntityManager em,
T entity) throws ProcessorException;
}

View File

@ -0,0 +1,89 @@
package de.hsadmin.core.qserv;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import de.hsadmin.core.qserv.AbstractProcessor;
import de.hsadmin.core.qserv.ProcessorException;
import de.hsadmin.core.util.Config;
public class JDBCProcessor extends AbstractProcessor {
private static final long serialVersionUID = 7702753017749022325L;
private String driver;
private String url;
private String user;
private String password;
private List<String> sql;
public JDBCProcessor(String driver, String url, String user, String password) {
this.driver = driver;
this.url = url;
this.user = user;
this.password = password;
}
public JDBCProcessor(String driver, String url) {
this.driver = driver;
this.url = url;
}
public void addSQL(String sqlStatement) {
if (sql == null)
sql = new ArrayList<String>();
sql.add(sqlStatement);
}
public Object process() throws ProcessorException {
Connection c = null;
Config config = Config.getInstance();
if ("com.mysql.jdbc.Driver".equals(driver)) {
if (user == null)
user = config.getProperty("mysqladmin.user", "root");
if (password == null)
password = config.getProperty("mysqladmin.password");
}
if ("org.postgresql.Driver".equals(driver)) {
if (user == null)
user = config.getProperty("pgsqladmin.user", "postgres");
if (password == null)
password = config.getProperty("pgsqladmin.password");
}
if (user == null || password == null) {
throw new ProcessorException("database admin-user configuration failed");
}
try {
Class.forName(driver);
c = DriverManager.getConnection(url, user, password);
if (c == null)
throw new ProcessorException("cannot connect to '" + url + "'");
Statement s = c.createStatement();
for (String sqlStatement : sql) {
s.addBatch(sqlStatement);
System.out.println("SQL: " + sqlStatement);
}
return s.executeBatch();
} catch (SQLException aSqlExc) {
Exception exc = aSqlExc.getNextException();
if (exc == null)
exc = aSqlExc;
System.out.println("ERR: " + exc.getMessage());
throw new ProcessorException(aSqlExc.getMessage() + ", reason: "
+ exc.getMessage());
} catch (Exception aExc) {
throw new ProcessorException(aExc.getMessage());
} finally {
if (c != null) {
try {
c.close();
} catch (Exception exc) {
}
}
}
}
}

View File

@ -0,0 +1,41 @@
package de.hsadmin.core.qserv;
import java.util.Properties;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class MailerProcessor extends AbstractProcessor {
private static final long serialVersionUID = -8900943664576420041L;
private String aTo;
private String aSubject;
private String aBody;
public MailerProcessor(String aTo, String aSubject, String aBody) {
this.aTo = aTo;
this.aSubject = aSubject;
this.aBody = aBody;
}
public Object process() throws ProcessorException {
Properties aProps = new Properties();
aProps.setProperty("mail.smtp.host", "localhost");
Session aSess = Session.getInstance(aProps);
MimeMessage aMsg = new MimeMessage(aSess);
try {
aMsg.setFrom(new InternetAddress("robot@hostsharing.net"));
aMsg.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(aTo));
aMsg.setSubject(aSubject);
aMsg.setText(aBody);
MailerShell.send(aMsg);
return null;
} catch (MessagingException aExc) {
throw new ProcessorException(aExc);
}
}
}

View File

@ -0,0 +1,41 @@
package de.hsadmin.core.qserv;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
public class MailerShell {
private static boolean bExecute = true; // really execute or just store
// command and stdin?
private static MimeMessage aMessage; // stored message
/**
* Set mode of real mailer or just storing the messages for testing
* purposes.
*
* @param bExec
* specifies whether messages are really send (true) or just
* stored (false)
*/
public static void setExecute(boolean bExec) {
bExecute = bExec;
}
/**
* Returns and clears the last command which should have been executed.
*
* @return Last command, plus "<<EOF\n" + stdin + "EOF" if stdin was given.
*/
public static MimeMessage popLastMessage() {
MimeMessage aLastMessage = aMessage;
aMessage = null;
return aLastMessage;
}
public static void send(MimeMessage aMsg) throws MessagingException {
if (bExecute)
javax.mail.Transport.send(aMsg);
aMessage = aMsg;
}
}

View File

@ -0,0 +1,22 @@
package de.hsadmin.core.qserv;
import java.io.Serializable;
import de.hsadmin.core.model.Transaction;
/**
* A Processor encapsulates some code to be prepared by a client and to be
* executed on a server.
*/
public interface Processor extends Serializable {
/**
* Executes the encapsulated code, optionally returning a result.
* @return
* @throws ProcessorException
*/
public abstract Object process() throws ProcessorException;
public abstract void finalize(Transaction transaction, QueueTask task) throws ProcessorException;
}

View File

@ -0,0 +1,21 @@
package de.hsadmin.core.qserv;
import de.hsadmin.core.model.HSAdminException;
public class ProcessorException extends HSAdminException {
private static final long serialVersionUID = -1893688504714037106L;
public ProcessorException(String message, Exception aExc) {
super(message, aExc);
}
public ProcessorException(Exception aExc) {
super(aExc);
}
public ProcessorException(String message) {
super(message);
}
}

View File

@ -0,0 +1,80 @@
package de.hsadmin.core.qserv;
import javax.jms.JMSException;
import javax.jms.JMSSecurityException;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import de.hsadmin.core.util.Config;
/**
* An instance of this class is used to send Processor instances to the
* QueueServer.
*
* @author mi
*/
public class QueueClient extends QueueCommons {
private QueueConnectionFactory jmsConnectionFactory;
private Queue jmsSystemQueue;
private QueueConnection jmsConnection;
private QueueSession jmsSession;
private QueueSender jmsSender;
public QueueClient(QueueConnectionFactory jmsConFact, Queue jmsSysQueue)
throws JMSException {
this.jmsConnectionFactory = jmsConFact;
this.jmsSystemQueue = jmsSysQueue;
Config config = Config.getInstance();
String jmsUser = config.getProperty("hsadmin.jms.username", "hsadmin");
String jmsPass = config.getProperty("hsadmin.jms.password", "hsadmin-pw");
jmsConnection = jmsConnectionFactory.createQueueConnection(jmsUser, jmsPass);
jmsSession = jmsConnection.createQueueSession(DEFAULT, Session.AUTO_ACKNOWLEDGE);
jmsSender = jmsSession.createSender(jmsSystemQueue);
}
// Query a single value from the QueueServer which will process it as
// root.
public void send(QueueTask task) throws ProcessorException {
try {
ObjectMessage jmsMessage = jmsSession.createObjectMessage(task);
jmsSender.send(jmsMessage);
} catch (JMSSecurityException secExc) {
secExc.printStackTrace();
throw new ProcessorException("Not allowed to send to queue "
+ queueName(jmsSystemQueue) + " failed", secExc);
} catch (Exception exc) {
exc.printStackTrace();
throw new ProcessorException("Error while sending to queue "
+ queueName(jmsSystemQueue) + " failed", exc);
}
}
private String queueName(Queue jmsSystemQueue2) {
try {
return jmsSystemQueue.getQueueName();
} catch (Exception exc) {
return "<unknown>";
}
}
// frees all ressources
public void close() {
try {
if (jmsSender != null) jmsSender.close();
} catch (Exception exc) { }
try {
if (jmsSession != null) jmsSession.close();
} catch (Exception exc) { }
try {
if (jmsConnection != null) jmsConnection.close();
} catch (Exception exc) { }
}
}

View File

@ -0,0 +1,14 @@
package de.hsadmin.core.qserv;
public class QueueCommons
{
protected static final boolean TRANSACTED = true;
protected static final boolean IMMEDIATE = false;
protected static final boolean DEFAULT = IMMEDIATE;
public QueueCommons()
{
super();
}
}

View File

@ -0,0 +1,254 @@
package de.hsadmin.core.qserv;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Properties;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
public class QueueServer extends QueueCommons implements
MessageListener, ExceptionListener {
private static final String VERSION_NO = "1.0";
private int nMessagesProcessed = 0;
private QueueConnection conn;
private QueueSession queueSession;
private String jmsStatusQueue;
private String jmsPassWord;
private String jmsUserName;
private String jmsSystemQueue;
private String jmsFactory;
/** Runs the QueueServer, using the arguments as ConnectionFactory
* and Topic names.
*/
public static void main(String[] args) throws Exception {
File propFile = new File(System.getProperty("user.dir"),
"conf/qserv.properties");
if (args.length == 1)
propFile = new File(args[0]);
else if (args.length != 0) {
throw new Exception(
"Wrong number of arguments.\n"
+ "With no arguments '"
+ propFile
+ "' will be used as config file.\n"
+ "Or give a properties file as single argument.\n\n"
+ "Example config file:\n\n"
+ "hsadmin.jms.factory=QueueCF\n"
+ "hsadmin.jms.system-queue=hive-h01\n"
+ "hsadmin.jms.status-queue=queue/hsadminStatus\n"
+ "hsadmin.jms.username=hive-h01\n"
+ "hsadmin.jms.password=geheimeskennwort\n");
}
FileInputStream propStream = new FileInputStream(propFile);
Properties props = new Properties(System.getProperties());
props.load(propStream);
propStream.close();
String stdout = System.getProperty("hsadmin.stdout");
if (stdout != null && stdout.length() > 0)
System.setOut(new PrintStream(new FileOutputStream(stdout)));
String stderr = System.getProperty("hsadmin.stderr");
if (stderr != null && stderr.length() > 0)
System.setErr(new PrintStream(new FileOutputStream(stderr)));
final QueueServer qServ = new QueueServer();
qServ.setJmsFactory(props.getProperty("hsadmin.jms.factory"));
qServ.setJmsSystemQueue(props.getProperty("hsadmin.jms.system-queue"));
qServ.setJmsStatusQueue(props.getProperty("hsadmin.jms.status-queue"));
qServ.setJmsUserName(props.getProperty("hsadmin.jms.username"));
qServ.setJmsPassWord(props.getProperty("hsadmin.jms.password"));
System.out.println("==================================================");
System.out.println("hsadmin-qserv " + VERSION_NO +
" started using:");
System.out.println("queue server: "
+ props.getProperty("hsadmin.jms.factory"));
System.out.println("system queue: "
+ props.getProperty("hsadmin.jms.system-queue"));
System.out.println("status queue: "
+ props.getProperty("hsadmin.jms.status-queue"));
System.out.println("queue user: "
+ props.getProperty("hsadmin.jms.username"));
System.out.println("==================================================");
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
qServ.close();
}
});
while (!qServ.connect()) {
Thread.sleep(10000);
}
while (true) {
Thread.sleep(10000);
}
}
private boolean connect() {
// create JMS connection and session
try {
Context ctx = new InitialContext();
QueueConnectionFactory connectionFactory =
(QueueConnectionFactory) ctx.lookup(jmsFactory);
conn = connectionFactory.createQueueConnection(jmsUserName, jmsPassWord);
conn.setExceptionListener(this);
queueSession = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = (Queue) ctx.lookup(jmsSystemQueue);
conn.start();
QueueReceiver receiver = queueSession.createReceiver(queue);
receiver.setMessageListener(this);
return true;
} catch (Exception e) {
System.out.println(e.getMessage());
return false;
}
}
// / Is called when a message arrives; processes Processor within message.
public synchronized void onMessage(Message jmsMessage) {
// TODO logging
System.out.println("\nonMessage(" + jmsMessage);
QueueTask task = null;
try {
// expect ObjectMessage
ObjectMessage jmsObjectMessage = (ObjectMessage) jmsMessage;
// get QueueTask
task = (QueueTask) jmsObjectMessage.getObject();
// TODO: logging
System.out.println("processing (" + task.getTitle() + " | started("
+ task.getStarted() + ") |" + task.getDetails() + "|"
+ task.getProcessor() + ")");
System.out.println("with " + task.getProcessor());
// execute processor within the message
task.getProcessor().process();
System.out.println("done");
// mark done
sendStatus(task);
} catch (Exception receiveException) {
System.err.println("exception " + receiveException); // TODO:
// logging
receiveException.printStackTrace(System.err);
if (receiveException.getCause() != null) {
System.err.println("caused by exception "
+ receiveException.getCause()); // TODO: logging
receiveException.getCause().printStackTrace(System.err);
} else
System.err.println("no further cause available");
task.setException(receiveException);
sendStatus(task);
} catch (Throwable t) {
System.err.println("severe exception " + t); // TODO: logging
} finally {
setNMessagesProcessed(getNMessagesProcessed() + 1);
notifyAll();
}
}
@Override
public void onException(JMSException e) {
System.out.println("Exception: " + e.getMessage());
close();
while (!connect()) {
try {
Thread.sleep(10000);
} catch (InterruptedException e1) { }
}
}
public void close() {
if (queueSession != null) {
try {
queueSession.close();
} catch (JMSException e1) { }
}
if (conn != null) {
try {
conn.close();
} catch (JMSException e1) { }
}
}
// / send the status information back to the hsadmin server
protected void sendStatus(QueueTask queueMessage) {
MessageProducer producer = null;
Session statusSession = null;
Connection statusConnection = null;
try {
System.out.println("sendStatus( " + queueMessage + ")");
Context ctx = new InitialContext();
System.out.println("Created InitialContext");
ConnectionFactory connectionFactory = (ConnectionFactory) ctx.lookup(jmsFactory);
System.out.println("connectionFactory= "
+ connectionFactory.toString());
Destination queue = (Destination) ctx.lookup(jmsStatusQueue);
statusConnection = connectionFactory.createConnection(jmsUserName, jmsPassWord);
statusSession = statusConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = statusSession.createProducer(queue);
ObjectMessage statusMessage = statusSession.createObjectMessage(queueMessage);
System.out.println("send( " + statusMessage + ")");
producer.send(statusMessage);
} catch (Exception statusException) {
// TODO: log exception
System.out.println("failed");
statusException.printStackTrace(System.err);
} finally {
// close JMS
try { producer.close(); } catch (Exception exc) { }
try { statusSession.close(); } catch (Exception exc) { }
try { statusConnection.close(); } catch (Exception exc) { }
}
}
public void setNMessagesProcessed(int nMessagesProcessed) {
this.nMessagesProcessed = nMessagesProcessed;
}
public int getNMessagesProcessed() {
return nMessagesProcessed;
}
public void setJmsStatusQueue(String property) {
jmsStatusQueue = property;
}
public void setJmsPassWord(String property) {
jmsPassWord = property;
}
public void setJmsUserName(String property) {
jmsUserName = property;
}
public void setJmsSystemQueue(String property) {
jmsSystemQueue = property;
}
public void setJmsFactory(String property) {
jmsFactory = property;
}
}

View File

@ -0,0 +1,141 @@
package de.hsadmin.core.qserv;
import java.io.IOException;
import java.io.PrintWriter;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import de.hsadmin.cliClientConnector.TechnicalException;
import de.hsadmin.core.model.Transaction;
import de.hsadmin.core.util.Config;
public class QueueStatusReceiverServlet extends HttpServlet
implements MessageListener, ExceptionListener {
private static final long serialVersionUID = -5701350884034782083L;
private String jmsUser;
private String jmsPass;
private QueueConnectionFactory queueConnectionFactory;
private QueueConnection queueConnection;
private QueueSession queueSession;
private boolean isConnected;
private int messageCount;
private int errorCount;
@Override
public void init() throws ServletException {
isConnected = false;
messageCount = 0;
errorCount = 0;
try {
connect();
} catch (NamingException e) {
throw new ServletException(e);
}
}
private void connect() throws NamingException {
Config config = Config.getInstance();
jmsUser = config.getProperty("hsadmin.jms.username", "hsadmin");
jmsPass = config.getProperty("hsadmin.jms.password", "hsadmin-pw");
InitialContext ctx = new InitialContext();
Context env = (Context) ctx.lookup("java:comp/env");
queueConnectionFactory = (QueueConnectionFactory) env.lookup("jms/QueueCF");
while (!isConnected) {
try {
queueConnection = queueConnectionFactory.createQueueConnection(jmsUser, jmsPass);
queueConnection.setExceptionListener(this);
queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = (Queue) env.lookup("jms/hsadminStatus");
queueConnection.start();
QueueReceiver receiver = queueSession.createReceiver(queue);
receiver.setMessageListener(this);
isConnected = true;
} catch (JMSException e) {
close();
try {
Thread.sleep(2000);
} catch (InterruptedException e1) { }
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/plain");
PrintWriter writer = resp.getWriter();
writer.println("Verbindungsstatus: " + (isConnected ? "OK" : "ERROR"));
writer.println("Verarbeitete Nachrichten: " + messageCount);
writer.println("Verarbeitungsfehler: " + errorCount);
writer.close();
}
@Override
public void destroy() {
close();
}
private void close() {
try { if (queueSession != null) queueSession.close(); } catch (JMSException e) { }
try { if (queueConnection != null) queueConnection.close(); } catch (JMSException e) { }
isConnected = false;
}
@Override
public void onMessage(Message jmsMessage) {
Transaction transaction = null;
messageCount++;
try {
ObjectMessage objMessage = (ObjectMessage) jmsMessage;
QueueTask detachedQT = (QueueTask) objMessage.getObject();
transaction = new Transaction("statusreceiver");
transaction.beginTransaction();
EntityManager em = transaction.getEntityManager();
// merging detachedQT directly makes Hibernate run into an endless recursion (stack overflow)
em.clear();
QueueTask persistentQT = em.find(QueueTask.class, detachedQT.getId());
persistentQT.assign(detachedQT);
Processor processor = persistentQT.getProcessor();
if (processor != null) {
processor.finalize(transaction, persistentQT);
}
em.persist(persistentQT);
em.flush();
transaction.commitTransaction();
} catch (Exception e) {
errorCount++;
if (transaction != null) transaction.rollbackTransaction();
throw new TechnicalException(e);
} finally {
if (transaction != null) transaction.close();
}
}
@Override
public void onException(JMSException exception) {
close();
try { Thread.sleep(10000); } catch (InterruptedException e) { }
try { connect(); } catch (NamingException e) { }
}
}

View File

@ -0,0 +1,232 @@
package de.hsadmin.core.qserv;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.EntityManager;
import javax.persistence.FetchType;
import javax.persistence.GenerationType;
import de.hsadmin.core.model.Entity;
import de.hsadmin.core.model.EntityInfo;
import de.hsadmin.core.model.ModuleImpl;
import de.hsadmin.mods.qstat.QTaskModuleImpl;
import de.hsadmin.mods.user.UnixUser;
@javax.persistence.Entity(name = "QueueTasks")
@javax.persistence.Table(name = "queue_task")
@javax.persistence.SequenceGenerator(name = "QueueTaskSeqGen", sequenceName = "queue_task_id_seq")
@EntityInfo(name = "Systemauftrag")
@ModuleImpl(QTaskModuleImpl.class)
public class QueueTask extends Entity implements Serializable {
private static final long serialVersionUID = 2171870783383767875L;
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "QueueTaskSeqGen")
@javax.persistence.Column(name = "task_id", columnDefinition = "integer")
private long id;
@javax.persistence.JoinColumn(name="user_id", columnDefinition="integer", nullable=true)
@javax.persistence.ManyToOne(fetch=FetchType.EAGER)
private UnixUser user;
@javax.persistence.Column(name = "started", columnDefinition = "date")
@javax.persistence.Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date started;
@javax.persistence.Column(name = "finished", columnDefinition = "date", nullable = true)
@javax.persistence.Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date finished;
@javax.persistence.Column(name = "title", columnDefinition = "character varying(192)")
private String title;
@javax.persistence.Column(name = "details", columnDefinition = "text", nullable = true)
private String details;
private Processor proc;
@javax.persistence.Column(name = "exception", columnDefinition = "text", nullable = true)
private String exception;
public QueueTask() {
}
public QueueTask(UnixUser user, String title, String details, Processor proc) {
this.user = user;
this.title = title;
this.details = details;
this.started = new Date();
this.finished = null;
this.proc = proc;
this.exception = null;
}
@Override
public UnixUser owningUser(EntityManager em) {
return user;
}
/**
* determines whether the given user has full read access
* on all merged fields of this entity
*/
@Override
public boolean isReadAllowedFor(UnixUser loginUser) {
return loginUser.hasPacAdminRoleFor(getUser().getPac())
|| loginUser.id() == getUser().id();
}
/**
* JPA-Query restriction for these entities
* @return
*/
public static String restriction() {
return
// customers can see all entries of all users of their pacs
"obj.user.pac.customer.name=:loginUserName OR " +
// packet admins can access all entries of their users
// TODO: Hostsharing convention
"obj.user.pac.name=:loginUserName OR " +
// otherwise only their own tasks
"obj.user=:loginUser";
}
@Override
public String createStringKey() {
return Long.toString(id);
}
@Override
public long id() {
return id;
}
public long getId() {
return id;
}
protected void setId(long id) {
this.id = id;
}
public UnixUser getUser() {
return user;
}
public void setUser(UnixUser user) {
this.user = user;
}
public Date getStarted() {
return started;
}
public void setStarted(Date started) {
this.finished = started;
}
public Date getFinished() {
return finished;
}
/**
* virtual attribute done
* @return
*/
@javax.persistence.Transient
public boolean isDone() {
return finished != null;
}
public void done() {
finished = new java.util.Date();
}
/**
* virtual attribute status
* @return
*/
@javax.persistence.Transient
public QueueTaskStatus getStatus() {
return isDone() ? (exception == null ? QueueTaskStatus.DONE
: QueueTaskStatus.ERROR) : QueueTaskStatus.PENDING;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
public Processor getProcessor() {
return proc;
}
public void setProcessor(Processor proc) {
this.proc = proc;
}
public String getException() {
return exception;
};
public void setException(String exception) {
this.exception = exception;
}
public void setException(Exception exception) {
this.exception = exception.toString();
// TODO: stack+cause
}
@Override
public boolean isNew() {
return id == 0;
}
/**
* assigns all data field of qt to this instance, with
* the exception of the id
*/
public void assign(QueueTask qt) {
this.user = qt.user;
this.title = qt.title;
this.details = qt.details;
this.started = qt.started;
this.finished = qt.finished;
this.proc = qt.proc;
this.exception = qt.exception;
}
@Override
public String getHiveName() {
return null;
}
public enum QueueTaskStatus {
PENDING("pending"), ERROR("error"), DONE("done");
private final String color;
QueueTaskStatus(final String color) {
this.color = color;
}
public String toString() {
return color;
}
}
}

View File

@ -0,0 +1,19 @@
package de.hsadmin.core.qserv;
public class ShellException
extends Exception
{
private static final long serialVersionUID = 8335020360721047849L;
int nExitCode;
public ShellException()
{
}
public ShellException( int exitCode, String message )
{
super( message );
nExitCode = exitCode;
}
}

View File

@ -0,0 +1,76 @@
package de.hsadmin.core.qserv;
/**
* A ShellProcessor encapsulates a shell command as a Processor.
*
* As such, a client can prepare shell commands to be processed on a server.
*
* @author mi
*/
public class ShellProcessor extends AbstractProcessor {
private static final long serialVersionUID = -649045174380048818L;
private String aSystemCall;
private String[] aEnv;
private String aInput;
private String aOutput;
private String aErrors;
/**
* Constructor for a queue entry which executes a system call.
*
* @param aSystemCall
* the system call to be executed
*/
public ShellProcessor(String aSystemCall) {
this(aSystemCall, null, null);
}
/**
* Constructor for a queue entry which executes a system call with stdin
* data.
*
* @param aSystemCall
* the system call to be executed
* @param aInput
* data for stdin of the system call
*/
public ShellProcessor(String aSystemCall, String aInput) {
this.aSystemCall = aSystemCall;
this.aInput = aInput;
}
public ShellProcessor(String aSystemCall, String[] aEnv, String aInput) {
this.aSystemCall = aSystemCall;
this.aEnv = aEnv;
this.aInput = aInput;
}
public Object process() throws ProcessorException {
try {
CommandShell.setEnvironment(aEnv);
aOutput = CommandShell.execute(aSystemCall, aInput);
return aOutput;
} catch (ShellException aExc) {
aExc.printStackTrace(System.err); // Logging
throw new ProcessorException(aExc);
}
}
/**
* @return Returns stderr as a String.
*/
public String getErrors() {
return aErrors;
}
/**
* @return Returns stdout as a String.
*/
public String getOutput() {
return aOutput;
}
}

View File

@ -0,0 +1,57 @@
package de.hsadmin.core.qserv;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import net.sf.jtpl.Template;
public class TemplateProcessor extends AbstractProcessor {
private static final long serialVersionUID = 4520635523274792876L;
private String content = null;
private String targetPath = null;
private boolean overwriteTarget = false;
public TemplateProcessor(String templateName, Map<String, String> templateValues, String targetPath, boolean overwriteTarget) throws ProcessorException {
this.targetPath = targetPath;
this.overwriteTarget = overwriteTarget;
try {
InputStream stream = TemplateProcessor.class.getClassLoader().getResourceAsStream(templateName);
Template template = new Template(new InputStreamReader(stream));
for (String key : templateValues.keySet()) {
template.assign(key, templateValues.get(key));
}
template.parse("main");
content = template.out();
} catch (IOException e) {
throw new ProcessorException(e);
}
}
@Override
public Object process() throws ProcessorException {
try {
File file = new File(targetPath);
if (file.exists() && !overwriteTarget) {
return null;
}
if (!file.exists() || file.canWrite()) {
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
writer.append(content);
writer.close();
} else {
throw new ProcessorException("could not write file " + targetPath);
}
return null;
} catch (IOException e) {
throw new ProcessorException(e);
}
}
}

View File

@ -0,0 +1,64 @@
package de.hsadmin.core.qserv;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import de.hsadmin.core.model.Transaction;
public class WaitingTasksProcessor extends AbstractProcessor {
private static final long serialVersionUID = 1198528557513957546L;
private Processor main;
private List<WaitingProcessor> waitingTasks;
public WaitingTasksProcessor(Processor mainProcessor) {
this.main = mainProcessor;
this.waitingTasks = new ArrayList<WaitingProcessor>();
}
@Override
public Object process() throws ProcessorException {
return main.process();
}
@Override
public void finalize(Transaction transaction, QueueTask task)
throws ProcessorException {
if (task.getException() == null) {
for (WaitingProcessor p : waitingTasks) {
QueueTask wTask =
new QueueTask(task.getUser(), task.getTitle() + " / " + p.getTitle(), task.getTitle() + " / " + p.getTitle(), p.getProc());
transaction.getEntityManager().persist(wTask);
transaction.enqueue(p.getHost(), wTask);
}
}
super.finalize(transaction, task);
}
public void appendProcessor(String hostName, Processor waitingTask, String title) {
waitingTasks.add(new WaitingProcessor(hostName, waitingTask, title));
}
class WaitingProcessor implements Serializable {
private static final long serialVersionUID = -5205925170344385765L;
private String host;
private Processor proc;
private String title;
public WaitingProcessor(String hostName, Processor processor, String procTitle) {
host = hostName;
proc = processor;
title = procTitle;
}
public Processor getProc() {
return proc;
}
public String getHost() {
return host;
}
public String getTitle() {
return title;
}
}
}

View File

@ -0,0 +1,53 @@
package de.hsadmin.core.util;
import java.io.File;
import java.io.FileReader;
import java.util.Properties;
public class Config {
private static Config instance;
private Properties props;
private Config() {
props = new Properties();
File file = new File(System.getProperty("user.dir") + "/hsadmin.properties");
if (!file.canRead()) {
file = new File(System.getProperty("user.dir") + "/conf/hsadmin.properties");
}
if (!file.canRead()) {
file = new File(System.getProperty("user.home") + "/.hsadmin.properties");
}
if (!file.canRead()) {
file = new File("/etc/hsadmin.properties");
}
if (!file.canRead()) {
file = new File("/etc/hsadmin/hsadmin.properties");
}
if (file.canRead()) {
try {
props.load(new FileReader(file));
} catch (Exception e) {
// should not happen
e.printStackTrace();
}
}
}
public static Config getInstance() {
if (instance == null) {
instance = new Config();
}
return instance;
}
public String getProperty(String propertyName) {
return props.getProperty(propertyName).trim();
}
public String getProperty(String propertyName, String defaultValue) {
return props.getProperty(propertyName, defaultValue).trim();
}
}

View File

@ -0,0 +1,164 @@
package de.hsadmin.mods.cust;
import static javax.persistence.FetchType.EAGER;
import javax.persistence.EntityManager;
import de.hsadmin.mods.user.UnixUser;
@javax.persistence.Entity(name = "BankAccounts")
@javax.persistence.Table(name = "bank_account")
public class BankAccount extends de.hsadmin.core.model.Entity implements
java.io.Serializable {
private static final long serialVersionUID = 2965368183976686458L;
public static String createQueryFromStringKey(String humanKey) {
return "customer.name = " + humanKey;
}
@Override
public String createStringKey() {
return getCustomer().getName();
}
@Override
public long id() {
return id;
}
// attribute id
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = javax.persistence.GenerationType.SEQUENCE)
@javax.persistence.SequenceGenerator(name = "bank_account_id_seq_gen", sequenceName = "bank_account_bank_account_i_seq", allocationSize = 20)
@javax.persistence.Column(name = "bank_account_id", columnDefinition = "integer")
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
// attribute customer
@javax.persistence.JoinColumn(name = "bp_id", columnDefinition = "integer")
@javax.persistence.OneToOne(fetch = EAGER)
private Customer customer;
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
// attribute autoDebitGA
@javax.persistence.Column(name = "autodebit_ga", columnDefinition = "boolean", nullable = true)
private Boolean autoDebitGA;
public Boolean isAutoDebitGA() {
return autoDebitGA;
}
public Boolean getAutoDebitGA() {
return autoDebitGA;
}
public void setAutoDebitGA(Boolean autoDebitGA) {
this.autoDebitGA = autoDebitGA;
}
// attribute autoDebitAR
@javax.persistence.Column(name = "autodebit_ar", columnDefinition = "boolean", nullable = true)
private Boolean autoDebitAR;
public Boolean isAutoDebitAR() {
return autoDebitAR;
}
public Boolean getAutoDebitAR() {
return autoDebitAR;
}
public void setAutoDebitAR(Boolean autoDebitAR) {
this.autoDebitAR = autoDebitAR;
}
// attribute autoDebitOP
@javax.persistence.Column(name = "autodebit_op", columnDefinition = "boolean", nullable = true)
private Boolean autoDebitOP;
public Boolean isAutoDebitOP() {
return autoDebitOP;
}
public Boolean getAutoDebitOP() {
return autoDebitOP;
}
public void setAutoDebitOP(Boolean autoDebitOP) {
this.autoDebitOP = autoDebitOP;
}
// attribute bankCustomer
@javax.persistence.Column(name = "bank_customer", columnDefinition = "character varying(50)", nullable = true)
private String bankCustomer;
public String getBankCustomer() {
return bankCustomer;
}
public void setBankCustomer(String bankCustomer) {
this.bankCustomer = bankCustomer;
}
// attribute bankAccount
@javax.persistence.Column(name = "bank_account", columnDefinition = "character varying(10)", nullable = true)
private String bankAccount;
public String getBankAccount() {
return bankAccount;
}
public void setBankAccount(String bankAccount) {
this.bankAccount = bankAccount;
}
// attribute bankCode
@javax.persistence.Column(name = "bank_code", columnDefinition = "character varying(8)", nullable = true)
private String bankCode;
public String getBankCode() {
return bankCode;
}
public void setBankCode(String bankCode) {
this.bankCode = bankCode;
}
// attribute bankName
@javax.persistence.Column(name = "bank_name", columnDefinition = "character varying(50)", nullable = true)
private String bankName;
public String getBankName() {
return bankName;
}
public void setBankName(String bankName) {
this.bankName = bankName;
}
// / {$inheritDoc}
@Override
public boolean isNew() {
return id == 0;
}
// / {@inheritDoc}
@Override
public UnixUser owningUser(EntityManager em) {
return customer.owningUser(em);
}
}

View File

@ -0,0 +1,282 @@
package de.hsadmin.mods.cust;
import static javax.persistence.FetchType.EAGER;
import static javax.persistence.GenerationType.SEQUENCE;
import javax.persistence.EntityManager;
import de.hsadmin.mods.user.UnixUser;
@javax.persistence.Entity(name = "Contacts")
@javax.persistence.Table(name = "contact")
@javax.persistence.SequenceGenerator(name = "ContactsSeqGen", sequenceName = "contact_contact_id_seq")
public class Contact extends de.hsadmin.core.model.Entity implements
java.io.Serializable {
private static final long serialVersionUID = 9119607911598098558L;
// attribute id
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = SEQUENCE, generator = "ContactsSeqGen")
@javax.persistence.Column(name = "contact_id", columnDefinition = "integer")
private long id;
// attribute customer
@javax.persistence.JoinColumn(name = "bp_id", columnDefinition = "integer")
@javax.persistence.ManyToOne(fetch = EAGER)
private Customer customer;
// attribute salut
@javax.persistence.Column(name = "salut", columnDefinition = "character varying(30)")
private String salut;
// attribute firstName
@javax.persistence.Column(name = "first_name", columnDefinition = "character varying(40)")
private String firstName;
// attribute lastName
@javax.persistence.Column(name = "last_name", columnDefinition = "character varying(40)")
private String lastName;
// attribute title
@javax.persistence.Column(name = "title", columnDefinition = "character varying(20)")
private String title;
// attribute firma
@javax.persistence.Column(name = "firma", columnDefinition = "character varying(120)")
private String firma;
// attribute co
@javax.persistence.Column(name = "co", columnDefinition = "character varying(50)")
private String co;
// attribute street
@javax.persistence.Column(name = "street", columnDefinition = "character varying(50)")
private String street;
// attribute zipCode
@javax.persistence.Column(name = "zipcode", columnDefinition = "character varying(10)")
private String zipCode;
// attribute city
@javax.persistence.Column(name = "city", columnDefinition = "character varying(40)")
private String city;
// attribute country
@javax.persistence.Column(name = "country", columnDefinition = "character varying(30)")
private String country;
// attribute phonePrivate
@javax.persistence.Column(name = "phone_private", columnDefinition = "character varying(30)")
private String phonePrivate;
// attribute phoneOffice
@javax.persistence.Column(name = "phone_office", columnDefinition = "character varying(30)")
private String phoneOffice;
// attribute phoneMobile
@javax.persistence.Column(name = "phone_mobile", columnDefinition = "character varying(30)")
private String phoneMobile;
// attribute fax
@javax.persistence.Column(name = "fax", columnDefinition = "character varying(30)")
private String fax;
// attribute email
@javax.persistence.Column(name = "email", columnDefinition = "character varying(50)")
private String email;
public Contact() {
}
public Contact(Customer cust) {
this.customer = cust;
}
public Contact(Customer cust, String salut, String title, String firstName,
String lastName, String firma, String co, String street,
String zipCode, String city, String country, String phonePrivate,
String phoneOffice, String phoneMobile, String fax, String email) {
this.customer = cust;
this.salut = salut;
this.title = title;
this.firstName = firstName;
this.lastName = lastName;
this.firma = firma;
this.co = co;
this.street = street;
this.zipCode = zipCode;
this.city = city;
this.country = country;
this.phonePrivate = phonePrivate;
this.phoneOffice = phoneOffice;
this.phoneMobile = phoneMobile;
this.fax = fax;
this.email = email;
}
// / {@inheritDoc}
public static String createQueryFromStringKey(String humanKey) {
return "name='" + humanKey + "'";
}
// / {@inheritDoc}
@Override
public String createStringKey() {
return getCustomer().getName();
}
// / {@inheritDoc}
@Override
public long id() {
return id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public String getSalut() {
return salut;
}
public void setSalut(String salut) {
this.salut = salut;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getFirma() {
return firma;
}
public void setFirma(String firma) {
this.firma = firma;
}
public String getCo() {
return co;
}
public void setCo(String co) {
this.co = co;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhonePrivate() {
return phonePrivate;
}
public void setPhonePrivate(String phonePrivate) {
this.phonePrivate = phonePrivate;
}
public String getPhoneOffice() {
return phoneOffice;
}
public void setPhoneOffice(String phoneOffice) {
this.phoneOffice = phoneOffice;
}
public String getPhoneMobile() {
return phoneMobile;
}
public void setPhoneMobile(String phoneMobile) {
this.phoneMobile = phoneMobile;
}
public String getFax() {
return fax;
}
public void setFax(String fax) {
this.fax = fax;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
// / {$inheritDoc}
@Override
public boolean isNew() {
return id == 0;
}
// / {@inheritDoc}
@Override
public UnixUser owningUser(EntityManager em) {
return null; // TODO: no access yet
}
}

View File

@ -0,0 +1,267 @@
package de.hsadmin.mods.cust;
import static javax.persistence.CascadeType.ALL;
import static javax.persistence.FetchType.EAGER;
import static javax.persistence.FetchType.LAZY;
import static javax.persistence.GenerationType.SEQUENCE;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.EntityManager;
import de.hsadmin.mods.pac.Pac;
import de.hsadmin.mods.user.UnixUser;
@javax.persistence.Entity(name = "Customers")
@javax.persistence.Table(name = "business_partner")
@javax.persistence.SequenceGenerator(name = "CustomersSeqGen", sequenceName = "business_partner_bp_id_seq")
public class Customer extends de.hsadmin.core.model.Entity implements Serializable {
private static final long serialVersionUID = -7450594652238392616L;
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = SEQUENCE, generator = "CustomersSeqGen")
@javax.persistence.Column(name = "bp_id", columnDefinition = "integer")
private long id;
@javax.persistence.Column(name = "member_id", columnDefinition = "integer")
private int memberNo;
@javax.persistence.Column(name = "member_code", columnDefinition = "character varying(20)")
private String name;
@javax.persistence.Column(name = "member_since", columnDefinition = "date", nullable = true)
private Date memberSince;
@javax.persistence.Column(name = "member_until", columnDefinition = "date", nullable = true)
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date memberUntil;
@javax.persistence.Column(name = "member_role", columnDefinition = "character varying(100)", nullable = true)
private String memberRole;
@javax.persistence.Column(name = "author_contract", columnDefinition = "date", nullable = true)
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date authorContract;
@javax.persistence.Column(name = "nondisc_contract", columnDefinition = "date", nullable = true)
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date nonDiscContract;
@javax.persistence.Column(name = "shares_updated", columnDefinition = "date", nullable = true)
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date sharesUpdated;
@javax.persistence.Column(name = "shares_signed", columnDefinition = "integer")
private int sharesSigned;
@javax.persistence.Column(name = "uid_vat", columnDefinition = "character varying(20)", nullable = true)
private String uidVAT;
@javax.persistence.OneToMany(fetch = EAGER, cascade = ALL, mappedBy = "customer")
private Set<Contact> contacts;
// virtual attribute bankAccount
@javax.persistence.OneToOne(fetch = EAGER, cascade = ALL, mappedBy = "customer")
private BankAccount bankAccount;
// virtual attribute billData
@javax.persistence.OneToOne(fetch = EAGER, cascade = ALL, mappedBy = "customer")
private CustomersTariff billData;
// virtual attribute pacs
@javax.persistence.OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "customer")
@javax.persistence.OrderBy("name")
private Set<Pac> pacs;
public Customer() {
}
public Customer(int memberNo, String memberCode) {
this.memberNo = memberNo;
this.name = memberCode;
}
public static String createQueryFromStringKey(String humanKey) {
return "name='" + humanKey + "'";
}
@Override
public String createStringKey() {
return getName();
}
@Override
public long id() {
return id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getMemberNo() {
return memberNo;
}
public void setMemberNo(int memberNo) {
this.memberNo = memberNo;
}
public String getName() {
return name;
}
public void setName(String memberCode) {
this.name = memberCode;
}
public Date getMemberSince() {
return memberSince;
}
public void setMemberSince(Date memberSince) {
this.memberSince = memberSince;
}
public Date getMemberUntil() {
return memberUntil;
}
public void setMemberUntil(Date memberUntil) {
this.memberUntil = memberUntil;
}
public String getMemberRole() {
return memberRole;
}
public void setMemberRole(String memberRole) {
this.memberRole = memberRole;
}
public Date getAuthorContract() {
return authorContract;
}
public void setAuthorContract(Date authorContract) {
this.authorContract = authorContract;
}
public Date getNonDiscContract() {
return nonDiscContract;
}
public void setNonDiscContract(Date nonDiscContract) {
this.nonDiscContract = nonDiscContract;
}
public Date getSharesUpdated() {
return sharesUpdated;
}
public void setSharesUpdated(Date sharesUpdated) {
this.sharesUpdated = sharesUpdated;
}
public int getSharesSigned() {
return sharesSigned;
}
public void setSharesSigned(int sharesSigned) {
this.sharesSigned = sharesSigned;
}
public String getUidVAT() {
return uidVAT;
}
public void setUidVAT(String uidVAT) {
this.uidVAT = uidVAT;
}
public Set<Contact> getContacts() {
if (contacts == null) {
contacts = new HashSet<Contact>();
contacts.add(new Contact(this));
}
return contacts;
}
public void setContacts(Set<Contact> contacts) {
this.contacts = contacts;
}
// virtual attribute contractualContact
// TODO: currently only a single contact can be managed
@javax.persistence.Transient
public Contact getContractualContact() {
return getContacts().iterator().next();
}
public void setContractualContact(Contact contact) {
contacts = new HashSet<Contact>();
contacts.add(contact);
}
public BankAccount getBankAccount() {
return bankAccount;
}
public void setBankAccount(BankAccount bankAccount) {
this.bankAccount = bankAccount;
}
public CustomersTariff getBillData() {
return billData;
}
public void setBillData(CustomersTariff tariff) {
this.billData = tariff;
}
public Set<Pac> getPacs() {
return pacs;
}
public void setPacs(Set<Pac> pacs) {
this.pacs = pacs;
}
@Override
public boolean isNew() {
return id == 0;
}
@Override
public UnixUser owningUser(EntityManager em) {
return null; // TODO: no access yet
}
/**
* determines whether the given user has full read access on all merged fields of this entity
*/
@Override
public boolean isReadAllowedFor(UnixUser loginUser) {
return loginUser.hasCustomerRoleFor(this);
}
/**
* determines whether the given user has full write access on all merged fields of this entity
*/
@Override
public boolean isWriteAllowedFor(UnixUser loginUser) {
return loginUser.hasCustomerRoleFor(this);
}
public static String restriction() {
return "name=:loginUserName";
}
}

View File

@ -0,0 +1,188 @@
package de.hsadmin.mods.cust;
import static javax.persistence.FetchType.EAGER;
import static javax.persistence.GenerationType.SEQUENCE;
import java.util.Date;
import javax.persistence.EntityManager;
import de.hsadmin.mods.user.UnixUser;
@javax.persistence.Entity(name = "CustomersTariffs")
@javax.persistence.Table(name = "billdata")
@javax.persistence.SequenceGenerator(name = "CustomersTariffsSeqGen", sequenceName = "billdata_billdata_id_seq")
public class CustomersTariff extends de.hsadmin.core.model.Entity implements
java.io.Serializable {
private static final long serialVersionUID = -3628577459027111705L;
// / bean ctor
public CustomersTariff() {
}
public CustomersTariff(Customer cust) {
this.customer = cust;
}
// / {@inheritDoc}
public static String createQueryFromStringKey(String humanKey) {
return "customer.name = '" + humanKey + "'";
}
// / {@inheritDoc}
@Override
public String createStringKey() {
return getCustomer().getName();
}
// / {@inheritDoc}
@Override
public long id() {
return id;
}
// attribute id
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = SEQUENCE, generator = "CustomersTariffsSeqGen")
@javax.persistence.Column(name = "billdata_id", columnDefinition = "integer")
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
// attribute customer
@javax.persistence.JoinColumn(name = "bp_id", columnDefinition = "integer")
@javax.persistence.OneToOne(fetch = EAGER)
// TODO: das will ich gar nicht, geht aber nicht ohne?!?
private Customer customer;
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
// attribute domainDiscountSince
@javax.persistence.Column(name = "tariff_domain_discount_since", columnDefinition = "date")
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date domainDiscountSince;
public Date getDomainDiscountSince() {
return domainDiscountSince;
}
public void setDomainDiscountSince(Date domainDiscountSince) {
this.domainDiscountSince = domainDiscountSince;
}
// attribute domainDiscountUntil
@javax.persistence.Column(name = "tariff_domain_discount_until", columnDefinition = "date")
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date domainDiscountUntil;
public Date getDomainDiscountUntil() {
return domainDiscountUntil;
}
public void setDomainDiscountUntil(Date domainDiscountUntil) {
this.domainDiscountUntil = domainDiscountUntil;
}
// attribute trafficDiscountSince
@javax.persistence.Column(name = "tariff_traffic_discount_since", columnDefinition = "date")
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date trafficDiscountSince;
public Date getTrafficDiscountSince() {
return trafficDiscountSince;
}
public void setTrafficDiscountSince(Date trafficDiscountSince) {
this.trafficDiscountSince = trafficDiscountSince;
}
// attribute trafficDiscountUntil
@javax.persistence.Column(name = "tariff_traffic_discount_until", columnDefinition = "date")
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date trafficDiscountUntil;
public Date getTrafficDiscountUntil() {
return trafficDiscountUntil;
}
public void setTrafficDiscountUntil(Date trafficDiscountUntil) {
this.trafficDiscountUntil = trafficDiscountUntil;
}
// attribute quotaDiscountSince
@javax.persistence.Column(name = "tariff_quota_discount_since", columnDefinition = "date")
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date quotaDiscountSince;
public Date getQuotaDiscountSince() {
return quotaDiscountSince;
}
public void setQuotaDiscountSince(Date quotaDiscountSince) {
this.quotaDiscountSince = quotaDiscountSince;
}
// attribute quotaDiscountUntil
@javax.persistence.Column(name = "tariff_quota_discount_until", columnDefinition = "date")
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date quotaDiscountUntil;
public Date getQuotaDiscountUntil() {
return quotaDiscountUntil;
}
public void setQuotaDiscountUntil(Date quotaDiscountUntil) {
this.quotaDiscountUntil = quotaDiscountUntil;
}
// attribute discountSince
@javax.persistence.Column(name = "tariff_discount_since", columnDefinition = "date")
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date discountSince;
public Date getDiscountSince() {
return discountSince;
}
public void setDiscountSince(Date discountSince) {
this.discountSince = discountSince;
}
// attribute discountUntil
@javax.persistence.Column(name = "tariff_discount_until", columnDefinition = "date")
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date discountUntil;
public Date getDiscountUntil() {
return discountUntil;
}
public void setDiscountUntil(Date discountUntil) {
this.discountUntil = discountUntil;
}
// / {$inheritDoc}
@Override
public boolean isNew() {
return id == 0;
}
// / {@inheritDoc}
@Override
public UnixUser owningUser(EntityManager em) {
return customer.owningUser(em);
}
}

View File

@ -0,0 +1,108 @@
package de.hsadmin.mods.pac;
import static javax.persistence.GenerationType.SEQUENCE;
import java.io.Serializable;
import javax.persistence.EntityManager;
import de.hsadmin.mods.user.UnixUser;
@javax.persistence.Entity(name = "BaseComponents")
@javax.persistence.Table(name = " basecomponent")
@javax.persistence.SequenceGenerator(name = "BaseComponentsSeqGen", sequenceName = "basecomponent_basecomponent_seq")
public class BaseComponent extends de.hsadmin.core.model.Entity implements Serializable {
private static final long serialVersionUID = -8161827018235142603L;
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = SEQUENCE, generator = "BaseComponentsSeqGen")
@javax.persistence.Column(name = "basecomponent_id", columnDefinition = "integer")
private long id;
@javax.persistence.Column(name = "basecomponent_code", columnDefinition = "character varying(10)")
private String feature;
@javax.persistence.Column(name = "description", columnDefinition = "character varying(100)")
private String description;
@javax.persistence.Column(name = "sorting", columnDefinition = "integer")
private int sorting;
@javax.persistence.Column(name = "valid", columnDefinition = "boolean")
private boolean valid;
public BaseComponent() {
}
public BaseComponent(String feature, String desc, int sortPos, boolean valid) {
this.feature = feature;
this.description = desc;
this.sorting = sortPos;
this.valid = valid;
}
public static String createQueryFromStringKey(String humanKey) {
return "feature='" + humanKey + "'";
}
@Override
public String createStringKey() {
return getFeature();
}
@Override
public long id() {
return id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFeature() {
return feature;
}
public void setFeature(String code) {
this.feature = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getSorting() {
return sorting;
}
public void setSorting(int sorting) {
this.sorting = sorting;
}
public boolean getValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
@Override
public boolean isNew() {
return id == 0;
}
@Override
public UnixUser owningUser(EntityManager em) {
return null; // TODO: kinda somebody like root needed
}
}

View File

@ -0,0 +1,141 @@
package de.hsadmin.mods.pac;
import static javax.persistence.CascadeType.ALL;
import static javax.persistence.FetchType.LAZY;
import static javax.persistence.GenerationType.SEQUENCE;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
@javax.persistence.Entity(name = "BasePacs")
@javax.persistence.Table(name = "basepacket")
@javax.persistence.SequenceGenerator(name = "BasePacsSeqGen", sequenceName = "basepacket_basepacket_id_seq")
public class BasePac implements Serializable {
private static final long serialVersionUID = 1491121619195513435L;
public BasePac() {
}
public BasePac(String name, String desc, int sortPos) {
this.name = name;
this.description = desc;
this.sorting = sortPos;
this.valid = true;
}
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = SEQUENCE, generator = "BasePacsSeqGen")
@javax.persistence.Column(name = "basepacket_id", columnDefinition = "integer")
private long id;
@javax.persistence.Column(name = "basepacket_code", columnDefinition = "character varying(10)")
private String name;
@javax.persistence.Column(name = "description", columnDefinition = "character varying(100)")
private String description;
@javax.persistence.Column(name = "sorting", columnDefinition = "integer")
private int sorting;
@javax.persistence.Column(name = "valid", columnDefinition = "boolean")
private boolean valid;
@javax.persistence.OneToMany(fetch = LAZY, cascade = ALL)
private Set<Component> components;
@javax.persistence.OneToMany(fetch = LAZY, cascade = ALL)
@javax.persistence.JoinTable(name = "packet_component", joinColumns = @javax.persistence.JoinColumn(name = "packet_id"), inverseJoinColumns = @javax.persistence.JoinColumn(name = "basepacket_id"))
private Set<Pac> pacs;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getSorting() {
return sorting;
}
public void setSorting(int sorting) {
this.sorting = sorting;
}
public boolean isValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
public Set<Component> getComponents() {
return components != null ? components
: (components = new HashSet<Component>());
}
public void setComponents(Set<Component> components) {
this.components = components;
}
public Component getComponent(String feature) {
for (Component comp : getComponents())
if (feature.equals(comp.getBaseComponent().getFeature()))
return comp;
return null;
}
public void addComponent(Component comp) {
getComponents().add(comp);
}
public void removeComponent(Component comp) {
getComponents().remove(comp);
}
public Set<Pac> getPacs() {
return pacs;
}
public void setPacs(Set<Pac> pacs) {
this.pacs = pacs;
}
// generic
public boolean equals(Object aOther) {
if (aOther == null || aOther.getClass() != getClass())
return false;
BasePac aOtherBP = (BasePac) aOther;
if (id != aOtherBP.id)
return false;
if (name != null && !name.equals(aOtherBP.name))
return false;
if (description != null && description.equals(aOtherBP.description))
return false;
if (sorting != aOtherBP.sorting)
return false;
if (valid != aOtherBP.valid)
return false;
return true;
}
}

View File

@ -0,0 +1,117 @@
package de.hsadmin.mods.pac;
import java.io.Serializable;
import javax.persistence.IdClass;
@javax.persistence.Entity(name = "Components")
@javax.persistence.Table(name = "component")
@IdClass(ComponentId.class)
public class Component implements Serializable {
private static final long serialVersionUID = 970709621200712794L;
@javax.persistence.Id
private BasePac basePac;
@javax.persistence.Id
private BaseComponent baseComponent;
@javax.persistence.Column(name = "min_quantity", columnDefinition = "integer")
private int minimumQuantity;
@javax.persistence.Column(name = "max_quantity", columnDefinition = "integer")
private int maximimumQuantity;
@javax.persistence.Column(name = "default_quantity", columnDefinition = "integer")
private int defaultQuantity;
@javax.persistence.Column(name = "increment_quantity", columnDefinition = "integer")
private int incrementQuantity;
@javax.persistence.Column(name = "include_quantity", columnDefinition = "integer")
private int includedQuantity;
@javax.persistence.Column(name = "admin_only", columnDefinition = "boolean")
private boolean adminOnly;
public Component() {
}
public Component(BasePac basePac, BaseComponent baseComp, int min, int max,
int def, int incr, int incl, boolean adminOnly) {
this.basePac = basePac;
this.baseComponent = baseComp;
this.minimumQuantity = min;
this.maximimumQuantity = max;
this.defaultQuantity = def;
this.incrementQuantity = incr;
this.includedQuantity = incl;
this.adminOnly = adminOnly;
}
public BasePac getBasePac() {
return basePac;
}
public void setBasePac(BasePac basePac) {
this.basePac = basePac;
}
public BaseComponent getBaseComponent() {
return baseComponent;
}
public void setBaseComponent(BaseComponent baseComponent) {
this.baseComponent = baseComponent;
}
public int getMinimumQuantity() {
return minimumQuantity;
}
public void setMinimumQuantity(int minimumQuantity) {
this.minimumQuantity = minimumQuantity;
}
public int getMaximimumQuantity() {
return maximimumQuantity;
}
public void setMaximimumQuantity(int maximimumQuantity) {
this.maximimumQuantity = maximimumQuantity;
}
public int getDefaultQuantity() {
return defaultQuantity;
}
public void setDefaultQuantity(int defiautoQuantity) {
this.defaultQuantity = defiautoQuantity;
}
public int getIncrementQuantity() {
return incrementQuantity;
}
public void setIncrementQuantity(int incrementQuantity) {
this.incrementQuantity = incrementQuantity;
}
public int getIncludedQuantity() {
return includedQuantity;
}
public void setIncludedQuantity(int includedQuantity) {
this.includedQuantity = includedQuantity;
}
public boolean isAdminOnly() {
return adminOnly;
}
public void setAdminOnly(boolean adminOnly) {
this.adminOnly = adminOnly;
}
}

View File

@ -0,0 +1,22 @@
package de.hsadmin.mods.pac;
public class ComponentId {
public long basePac;
public long baseComponent;
@Override
public boolean equals(Object obj) {
if (obj != null && obj instanceof ComponentId) {
ComponentId other = (ComponentId) obj;
return basePac == other.basePac && baseComponent == other.baseComponent;
}
return false;
}
@Override
public int hashCode() {
return (new Long(basePac ^ baseComponent % Integer.MAX_VALUE)).intValue();
}
}

View File

@ -0,0 +1,109 @@
package de.hsadmin.mods.pac;
import static javax.persistence.CascadeType.ALL;
import static javax.persistence.FetchType.EAGER;
import static javax.persistence.FetchType.LAZY;
import static javax.persistence.GenerationType.SEQUENCE;
import java.util.Set;
import javax.persistence.EntityManager;
import de.hsadmin.mods.user.UnixUser;
@javax.persistence.Entity(name="Hives")
@javax.persistence.Table(name="hive")
@javax.persistence.SequenceGenerator(name="HivesSeqGen", sequenceName="hive_hive_id_seq")
public class Hive
extends de.hsadmin.core.model.Entity
implements java.io.Serializable
{
private static final long serialVersionUID = -2270234313165009590L;
/// bean ctor
public Hive()
{
}
public Hive( String name, INetAddress inetAddr )
{
this.name = name;
this.inetAddr = inetAddr;
}
public Hive( String name, INetAddress inetAddr, String desc )
{
this(name, inetAddr);
this.description = desc;
}
/// {@inheritDoc}
public static String createQueryFromStringKey(String humanKey)
{
return "hiveName='" + humanKey + "'";
}
/// {@inheritDoc}
@Override
public String createStringKey()
{
return getHiveName();
}
/// {@inheritDoc}
@Override
public long id()
{
return id;
}
// attribute id
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy=SEQUENCE, generator="HivesSeqGen")
@javax.persistence.Column(name="hive_id")
private long id;
public long getId() { return id; }
public void setId( long id ) { this.id = id; }
// attribute hiveName
@javax.persistence.Column(name="hive_name", columnDefinition="character varying(3)", unique=true)
private String name;
public String getName() { return name; }
@Override
public String getHiveName() { return name; }
public void setName( String hiveName ) { this.name = hiveName; }
// attribute inetAddr
@javax.persistence.JoinColumn(name="inet_addr_id")
@javax.persistence.ManyToOne(fetch=EAGER)
private INetAddress inetAddr;
public INetAddress getInetAddr() { return inetAddr; }
public void setInetAddr( INetAddress inetAddr ) { this.inetAddr = inetAddr; }
// attribute description
@javax.persistence.Column(name="description", columnDefinition="character varying(100)")
private String description;
public String getDescription() { return description; }
public void setDescription( String description ) { this.description = description; }
// virtual attribute pacs
@javax.persistence.OneToMany(fetch=LAZY, cascade=ALL, mappedBy="hive")
@javax.persistence.OrderBy("name")
private Set<Pac> pacs;
public Set<Pac> getPacs() { return pacs; }
public void setPacs( Set<Pac> pacs) { this.pacs = pacs; }
/// {$inheritDoc}
@Override
public boolean isNew()
{
return id == 0;
}
/// {@inheritDoc}
@Override
public UnixUser owningUser( EntityManager em )
{
return null; // TODO: kinda somebody like root needed
}
}

View File

@ -0,0 +1,87 @@
package de.hsadmin.mods.pac;
import static javax.persistence.GenerationType.SEQUENCE;
import javax.persistence.EntityManager;
import de.hsadmin.mods.user.UnixUser;
@javax.persistence.Entity(name="INetAddresses")
@javax.persistence.Table(name="inet_addr")
@javax.persistence.SequenceGenerator(name="INetAddressesSeqGen", sequenceName="inet_addr_inet_addr_id_seq")
public class INetAddress
extends de.hsadmin.core.model.Entity
implements java.io.Serializable
{
private static final long serialVersionUID = -5792279453911426607L;
/// bean ctor
public INetAddress()
{
}
public INetAddress( String inetAddr )
{
this.inetAddr = inetAddr;
}
public INetAddress( String inetAddr, String desc )
{
this(inetAddr);
description = desc;
}
/// {@inheritDoc}
public static String createQueryFromStringKey(String humanKey)
{
return "inetAddr='" + humanKey + "'";
}
/// {@inheritDoc}
@Override
public String createStringKey()
{
return getInetAddr();
}
/// {@inheritDoc}
@Override
public long id()
{
return id;
}
// attribute id
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy=SEQUENCE, generator="INetAddressesSeqGen")
@javax.persistence.Column(name="inet_addr_id")
private long id;
public long getId() { return id; }
public void setId( long id ) { this.id = id; }
// attribute inetAddr
@javax.persistence.Column(name="inet_addr", columnDefinition="inet", unique=true)
private String inetAddr;
public String getInetAddr() { return inetAddr; }
public void setInetAddr( String inetAddr ) { this.inetAddr = inetAddr; }
// attribute description
@javax.persistence.Column(name="description", columnDefinition="character varying(100)")
private String description;
public String getDescription() { return description; }
public void setDescription( String description ) { this.description = description; }
/// {$inheritDoc}
@Override
public boolean isNew()
{
return id == 0;
}
/// {@inheritDoc}
@Override
public UnixUser owningUser( EntityManager em )
{
return null; // TODO: kinda somebody like root needed
}
}

View File

@ -0,0 +1,280 @@
package de.hsadmin.mods.pac;
import static javax.persistence.CascadeType.ALL;
import static javax.persistence.FetchType.EAGER;
import static javax.persistence.FetchType.LAZY;
import static javax.persistence.GenerationType.SEQUENCE;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.EntityManager;
import de.hsadmin.mods.cust.Customer;
import de.hsadmin.mods.user.UnixUser;
@javax.persistence.Entity(name = "Pacs")
@javax.persistence.Table(name = "packet")
@javax.persistence.SequenceGenerator(name = "PacsSeqGen", sequenceName = "packet_packet_id_seq")
@de.hsadmin.core.model.EntityInfo(name = "Paket")
public class Pac extends de.hsadmin.core.model.Entity implements Serializable {
private static final long serialVersionUID = 1201899873300190132L;
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = SEQUENCE, generator = "PacsSeqGen")
@javax.persistence.Column(name = "packet_id")
private long id;
@javax.persistence.Column(name = "packet_name", unique = true)
private String name;
@javax.persistence.JoinColumn(name = "bp_id")
@javax.persistence.ManyToOne(fetch = EAGER)
private Customer customer;
@javax.persistence.JoinColumn(name = "hive_id")
@javax.persistence.ManyToOne(fetch = EAGER)
private Hive hive;
@javax.persistence.Column(name = "created")
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date created;
@javax.persistence.Column(name = "cancelled", nullable = true)
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date cancelled;
@javax.persistence.Column(name = "order_number", nullable = true)
private String orderNo;
@javax.persistence.Column(name = "webserver_group", nullable = true)
private String webserverGroup;
@javax.persistence.JoinColumn(name = "cur_inet_addr_id", nullable = true)
@javax.persistence.ManyToOne(fetch = EAGER)
private INetAddress curINetAddr;
@javax.persistence.JoinColumn(name = "old_inet_addr_id", nullable = true)
@javax.persistence.ManyToOne(fetch = EAGER)
private INetAddress oldINetAddr;
@javax.persistence.OneToMany(fetch = LAZY, cascade = ALL)
private java.util.Set<PacComponent> pacComponents;
@javax.persistence.OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "pac")
private java.util.Set<UnixUser> unixUser;
public Pac() {
}
public Pac(String name, Customer cust, BasePac basePac, Hive hive) {
this.name = name;
this.customer = cust;
this.hive = hive;
this.created = new java.util.Date();
this.webserverGroup = "httpd";
this.curINetAddr = hive.getInetAddr();
pacComponents = new java.util.HashSet<PacComponent>();
java.util.Date today = new java.util.Date();
for (Component comp : basePac.getComponents()) {
PacComponent pacComp = new PacComponent(basePac,
comp.getBaseComponent(), this, comp.getDefaultQuantity(),
today, null);
pacComponents.add(pacComp);
System.err.println("TRACE [Pac]: added pacComp " + pacComp + " to "
+ getName());
}
}
// / {@inheritDoc}
public static String createQueryFromStringKey(String humanKey) {
return "obj.name='" + humanKey + "'";
}
// / {@inheritDoc}
@Override
public String createStringKey() {
return getName();
}
// / {@inheritDoc}
@Override
public long id() {
return id;
}
public long getId() {
return id;
}
protected void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public Hive getHive() {
return hive;
}
public void setHive(Hive hive) {
this.hive = hive;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getCancelled() {
return cancelled;
}
public void setCancelled(Date cancelled) {
this.cancelled = cancelled;
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public String getwebserverGroup() {
return webserverGroup;
}
public void setwebserverGroup(String webserverGroup) {
this.webserverGroup = webserverGroup;
}
public INetAddress getCurINetAddr() {
return curINetAddr;
}
public void setCurINetAddr(INetAddress curINetAddr) {
this.curINetAddr = curINetAddr;
}
public INetAddress getOldINetAddr() {
return oldINetAddr;
}
public void setOldINetAddr(INetAddress oldINetAddr) {
this.oldINetAddr = oldINetAddr;
}
// virtual attribute basePac
/*
* This does not work, JPA/Hibernate always wants to create an invalid row
* in packet_component
*
* @javax.persistence.ManyToOne(fetch=EAGER, optional=true) // optional
* should be default anyway
*
* @javax.persistence.JoinTable( name="packet_component",
* joinColumns=@javax.persistence.JoinColumn(name="packet_id"),
* inverseJoinColumns=@javax.persistence.JoinColumn(name="basepacket_id") )
*/
@javax.persistence.Transient
public BasePac getBasePac() {
return getPacComponents().iterator().next().getBasePac();
}
public void setBasePac(BasePac basePac) {
// TODO: needs code to change basePac in all pacComponents
}
public java.util.Set<PacComponent> getPacComponents() {
return pacComponents;
}
public void setPacComponents(java.util.Set<PacComponent> pacComponents) {
this.pacComponents = pacComponents;
}
public PacComponent getPacComponent(String feature) {
for (PacComponent pc : getPacComponents())
if (feature.equals(pc.getBaseComponent().getFeature()))
return pc;
return null;
}
public java.util.Set<UnixUser> getUnixUser() {
return unixUser;
}
public void setUnixUser(java.util.Set<UnixUser> unixUser) {
this.unixUser = unixUser;
}
// generic
public String toString() {
return super.toString() + "{ name=" + name + " }";
}
// / {$inheritDoc}
@Override
public boolean isNew() {
return id == 0;
}
// / {$inheritDoc}
@Override
public String getHiveName() {
if (isNew())
return null;
else
return getHive().getHiveName();
}
// / {@inheritDoc}
@Override
public UnixUser owningUser(EntityManager em) {
return customer.owningUser(em);
}
public UnixUser getAdminUser(EntityManager em) {
// TODO Auto-generated method stub
return null;
}
// / determines whether the given user has full read access on all merged
// fields of this entity
public boolean isReadAllowedFor(UnixUser loginUser) {
return getName().equals(loginUser.getName())
|| super.isReadAllowedFor(loginUser);
}
// / query restriction for access control
public static String restriction() {
return
// all pacs of customer
"obj.customer.name=:loginUserName OR " +
// pac of packet admin
"obj.name=:loginUserName";
}
}

View File

@ -0,0 +1,99 @@
package de.hsadmin.mods.pac;
import static javax.persistence.FetchType.EAGER;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.IdClass;
@javax.persistence.Entity(name = "PacComponents")
@javax.persistence.Table(name = "packet_component")
@IdClass(PacComponentId.class)
public class PacComponent implements Serializable {
private static final long serialVersionUID = 5359873462163274873L;
@javax.persistence.Id
private Pac pac;
@javax.persistence.Id
private BaseComponent baseComponent;
@javax.persistence.JoinColumn(name = "basepacket_id", columnDefinition = "integer", nullable = false)
@javax.persistence.ManyToOne(fetch = EAGER)
private BasePac basePac;
@javax.persistence.Column(name = "quantity", columnDefinition = "integer")
private int quantity;
@javax.persistence.Column(name = "created", columnDefinition = "date", nullable = true)
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date created;
@javax.persistence.Column(name = "cancelled", columnDefinition = "date", nullable = true)
@javax.persistence.Temporal(javax.persistence.TemporalType.DATE)
private Date cancelled;
public PacComponent() {
}
public PacComponent(BasePac basePac, BaseComponent baseComp, Pac pac,
int quantity, Date created, Date cancelled) {
this.basePac = basePac;
this.pac = pac;
this.baseComponent = baseComp;
this.quantity = quantity;
this.created = created;
this.cancelled = cancelled;
}
public BasePac getBasePac() {
return basePac;
}
public void setbasePac(BasePac basePac) {
this.basePac = basePac;
}
public BaseComponent getBaseComponent() {
return baseComponent;
}
public void setBaseComponent(BaseComponent baseComponent) {
this.baseComponent = baseComponent;
}
public Pac getPac() {
return pac;
}
public void setPac(Pac pac) {
this.pac = pac;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getCancelled() {
return cancelled;
}
public void setCancelled(Date cancelled) {
this.cancelled = cancelled;
}
}

View File

@ -0,0 +1,23 @@
package de.hsadmin.mods.pac;
public class PacComponentId {
public long pac;
public long baseComponent;
@Override
public boolean equals(Object obj) {
if (obj != null && obj instanceof PacComponentId) {
PacComponentId other = (PacComponentId) obj;
return pac == other.pac && baseComponent == other.baseComponent;
}
return false;
}
@Override
public int hashCode() {
return (new Long(pac ^ baseComponent % Integer.MAX_VALUE)).intValue();
}
}

View File

@ -0,0 +1,38 @@
package de.hsadmin.mods.qstat;
import java.util.List;
import de.hsadmin.core.model.AbstractModuleImpl;
import de.hsadmin.core.model.Entity;
import de.hsadmin.core.model.HSAdminException;
import de.hsadmin.mods.user.UnixUser;
public class QTaskModuleImpl extends AbstractModuleImpl {
private static final long serialVersionUID = 3942424688570077274L;
public QTaskModuleImpl() {
}
@Override
public List<Entity> search(Class<? extends Entity> entityClass, String condition, String orderBy) throws HSAdminException {
// do query and return result
if (orderBy == null || orderBy.length() == 0) {
orderBy = "ORDER BY obj.started DESC";
}
return super.search(entityClass, condition, orderBy);
}
// throws an AuthorisationException if the login user has no write acess
// on the pac of the given UnixUser
@SuppressWarnings("unused")
private boolean hasAccessOnPacOf(UnixUser user) {
// only pac admins (same name as pac) and the owner (customer) have
// write access to the pac
boolean isPacAdmin = getLoginUser().getName().equals(
user.getPac().getName());
boolean isCustomer = getLoginUser().getName().equals(
user.getPac().getCustomer().getName());
return isPacAdmin || isCustomer;
}
}

View File

@ -0,0 +1,323 @@
package de.hsadmin.mods.user;
import static javax.persistence.FetchType.EAGER;
import static javax.persistence.GenerationType.SEQUENCE;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import de.hsadmin.core.model.EntityInfo;
import de.hsadmin.mods.pac.Pac;
@Entity(name = "UnixUsers")
@Table(name = "unixuser")
@SequenceGenerator(name = "UnixUsersSeqGen", sequenceName = "unixuser_unixuser_id_seq")
@EntityInfo(name = "UNIX-Zugang/Mailbox")
public class UnixUser extends de.hsadmin.core.model.Entity implements Serializable {
private static final long serialVersionUID = 7823071611805642906L;
@Id
@GeneratedValue(strategy = SEQUENCE, generator = "UnixUsersSeqGen")
@Column(name = "unixuser_id", columnDefinition = "integer", updatable=false, insertable=false)
private long id;
// attribute userid - really NOT unique!
@Column(name = "userid", columnDefinition = "integer", nullable = false, updatable=false)
private long userId;
@Column(name = "name", columnDefinition = "character varying(24)", unique = true, updatable=false)
private String name;
@Transient
private String password;
@JoinColumn(name = "packet_id", columnDefinition = "integer", updatable=false)
@ManyToOne(fetch = EAGER)
private Pac pac;
@Column(name = "comment", columnDefinition = "character varying(128)")
private String comment;
@Column(name = "shell", columnDefinition = "character varying(32)")
private String shell;
@Column(name = "homedir", columnDefinition = "character varying(48)", updatable=false)
private String homedir;
@Column(name = "locked", columnDefinition = "boolean")
private boolean locked;
@Column(name = "quota_softlimit", columnDefinition = "integer")
private Integer quotaSoftlimit;
@Column(name = "quota_hardlimit", columnDefinition = "integer")
private Integer quotaHardlimit;
public UnixUser() {
}
public UnixUser(Pac pac, String name, int userId, String comment,
String homeDir, String shell) {
this.pac = pac;
this.name = name;
this.userId = userId;
this.comment = comment;
this.shell = shell;
init();
}
/**
* fixes some fields if null
*/
public void init() {
if (comment == null) {
comment = name;
}
if (homedir == null) {
this.homedir = getDefaultHomedir();
}
if (shell == null) {
shell = "/bin/false";
}
if (quotaSoftlimit == null) {
quotaSoftlimit = new Integer(0);
}
if (quotaHardlimit == null) {
quotaHardlimit = new Integer(0);
}
}
public static String createQueryFromStringKey(String humanKey) {
return "obj.name='" + humanKey + "'";
}
@Override
public String createStringKey() {
return getName();
}
@Override
public long id() {
return id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
// TODO: should NOT be an external property
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Pac getPac() {
return pac;
}
public void setPac(Pac pac) {
this.pac = pac;
pac.getUnixUser().add(this);
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getShell() {
return shell;
}
public void setShell(String shell) {
this.shell = shell;
}
public String getHomedir() {
return homedir;
}
public void setHomedir(String homedir) {
this.homedir = homedir;
}
/**
* returns true if the user has the default homedir path
*/
public boolean isDefaultHomedir() {
return getHomedir().equals(getDefaultHomedir());
}
/**
* returns the default homedir path
*/
private String getDefaultHomedir() {
String pacName = pac.getName();
if (name.equals(pacName))
return "/home/pacs/" + pacName;
else
return "/home/pacs/" + pacName + "/users/"
+ name.substring(pacName.length() + 1);
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public Integer getQuotaSoftlimit() {
return quotaSoftlimit;
}
public void setQuotaSoftlimit(Integer quota) {
this.quotaSoftlimit = quota;
}
public void setQuotaHardlimit(Integer quotaLimit) {
this.quotaHardlimit = quotaLimit;
}
public Integer getQuotaHardlimit() {
return quotaHardlimit;
}
@Override
public boolean isNew() {
return id == 0;
}
@Override
public void initialize(EntityManager em, UnixUser loginUser) {
pac = loginUser.getPac(); // a default useful for the pac admin
// TODO should not be hardcoded, but how?
homedir = "/home/pacs/" + pac.getName() + "/users/...";
}
@Override
public UnixUser merge(EntityManager em, UnixUser loginUser) {
if (homedir == null)
homedir = "/home/pacs/" + pac.getName() + "/users/"
+ getName().substring(6); // TODO: Hack
UnixUser dbEntity = (UnixUser) super.merge(em, loginUser);
dbEntity.setPassword(this.getPassword()); // because this is not in database
return dbEntity;
}
@Override
public String getHiveName() {
if (isNew())
return null;
else
return getPac().getHiveName();
}
@Override
public UnixUser owningUser(EntityManager em) {
return getPac().getAdminUser(em);
}
/**
* determines whether this user account is a hostmaster account
*/
public boolean hasHostmasterRole() {
// TODO: hardcoded Hostsharing conventions
return getName().length() == 2;
}
/**
* determines whether this user account has rights on the given customer
*/
public boolean hasCustomerRoleFor(de.hsadmin.mods.cust.Customer cust) {
// TODO: hardcoded Hostsharing conventions
return getName().equals(cust.getName()) || hasHostmasterRole();
}
/**
* determines whether this user account has admin rights on the given pac
*/
public boolean hasPacAdminRoleFor(de.hsadmin.mods.pac.Pac pac) {
// TODO: hardcoded Hostsharing conventions
return pac.getName().equals(getName())
|| hasCustomerRoleFor(pac.getCustomer());
}
/**
* determines whether this user account has admin rights on the given dom
*/
// public boolean hasDomAdminRoleFor(de.hsadmin.mods.dom.Domain dom) {
// // TODO: hardcoded Hostsharing conventions
// return this.getId() == dom.getUser().getId()
// || hasPacAdminRoleFor(dom.getUser().getPac());
// }
@Override
public boolean isWriteAllowedFor(UnixUser loginUser) {
String pacName = pac.getName();
if (!name.equals(pacName) && !name.startsWith(pacName + "-"))
return false;
if (super.isWriteAllowedFor(loginUser))
return true;
return this == loginUser || loginUser.hasPacAdminRoleFor(getPac());
}
@Override
public boolean isReadAllowedFor(UnixUser loginUser) {
if (super.isReadAllowedFor(loginUser))
return true;
return this.getId() == loginUser.getId() || loginUser.hasPacAdminRoleFor(getPac());
}
/**
* JPA-Query restriction for these entities
*/
public static String restriction() {
return
// customers can access all users in their pacs
"obj.pac.customer.name = :loginUserName OR "
// packet admins can access all users in their pacs
+ "obj.pac.name = :loginUserName OR "
// all users can access their own account
+ "obj.name = :loginUserName";
}
}

View File

@ -0,0 +1,279 @@
package de.hsadmin.mods.user;
import java.util.LinkedList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import de.hsadmin.core.model.AuthorisationException;
import de.hsadmin.core.model.Entity;
import de.hsadmin.core.model.AbstractModuleImpl;
import de.hsadmin.core.model.HSAdminException;
import de.hsadmin.mods.pac.Pac;
public class UnixUserModuleImpl extends AbstractModuleImpl {
private static final long serialVersionUID = 7480353553685400790L;
public UnixUserModuleImpl() {
}
@Override
public Entity initialize(Entity newEntity) throws AuthorisationException {
UnixUser newUnixUser = (UnixUser) super.initialize(newEntity);
newUnixUser.setName(getLoginUser().getPac().getName() + '-');
return newUnixUser;
}
@Override
public Entity find(Class<? extends Entity> entityClass, Object key) throws HSAdminException {
// do query
UnixUser res = (UnixUser) super.find(entityClass, key);
// check access rights
needsPartialAccessOnPacOf(res, "find");
// return clean result
return res;
}
@Override
public Entity findByString(Class<? extends Entity> entityClass, String key) throws HSAdminException {
// do query
UnixUser res = (UnixUser) super.findByString(entityClass, key);
// return directly (checking rights already done in search within
// findByString)
return res;
}
@Override
public List<Entity> search(Class<? extends Entity> entityClass, String condition, String orderBy) throws HSAdminException {
// do query
if (orderBy == null || orderBy.length() == 0) {
orderBy = "ORDER BY obj.name ASC";
}
List<Entity> res = super.search(entityClass, condition, orderBy);
List<Entity> ret = new LinkedList<Entity>();
// remove entities where login user has no access rights
if (res != null) {
for (Entity entity : res) {
try {
UnixUser returnedUnixUser = (UnixUser) entity;
needsPartialAccessOnPacOf(returnedUnixUser, "search");
ret.add(returnedUnixUser);
} catch (AuthorisationException exc) {
} // ignore
}
}
// return clean result
return ret;
}
@Override
public Entity add(Entity newEntity) throws HSAdminException {
EntityManager em = getEntityManager();
// only allow pac which matches the username (TODO: hard coded
// Hostsharing convention)
UnixUser newUnixUser = (UnixUser) newEntity;
// validation of username and password
String name = newUnixUser.getName();
if (name == null) {
throw new HSAdminException("username is required");
}
String userName = name.toLowerCase().trim();
for (char c : userName.toCharArray()) {
if (!(Character.isLetterOrDigit(c) || c == '.' || c == '-' || c == '_')) {
throw new AuthorisationException(getLoginUser(), "add", newUnixUser, "userId");
}
}
if (userName.length() < 7 || userName.charAt(5) != '-' || userName.lastIndexOf('-') > 5) {
throw new AuthorisationException(getLoginUser(), "add", newUnixUser, "userId");
}
String passWord = newUnixUser.getPassword();
if (passWord == null || passWord.length() == 0) {
throw new HSAdminException("password is required");
}
if (passWord.indexOf(':') >= 0) {
throw new AuthorisationException(getLoginUser(), "add", newUnixUser, "userId");
}
Query qPac = em.createQuery("SELECT obj FROM Pacs obj WHERE obj.name = :pacName");
qPac.setParameter("pacName", userName.substring(0, 5));
Pac pac = (Pac) qPac.getSingleResult();
newUnixUser.setName(userName);
newUnixUser.setHomedir("/home/pacs/" + userName.substring(0, 5) + "/users/" + userName.substring(6));
// no appropriate uid?
if (newUnixUser.getUserId() < 1000) {
// determine next free uid
long nUID = 20000;
Query qUID = em.createQuery("SELECT MAX(u.userId) FROM UnixUsers u");
Long maxUid = (Long) qUID.getSingleResult();
if (maxUid >= nUID)
nUID = maxUid + 1;
newUnixUser.setUserId(nUID);
} else {
// given uid belongs to same pac?
Query q = em.createQuery("SELECT u.userId FROM UnixUsers u WHERE u.userId = :userId AND u.pac = :pac");
q.setParameter("userId", newUnixUser.getUserId());
q.setParameter("pac", pac);
List<?> idOfSamePac = q.getResultList();
if (idOfSamePac.size() == 0) {
throw new AuthorisationException(getLoginUser(), "add", newUnixUser, "userId");
}
}
// don't move this up, it will update the new entity still with wrong
// userid!
newUnixUser.setPac(pac);
newUnixUser.init();
// authorisation check
needsFullAccessOnPacOf(newUnixUser, "add");
// add new entity
return super.add(newEntity);
}
private EntityManager getEntityManager() {
return getTransaction().getEntityManager();
}
@Override
public Entity update(Entity existingEntity) throws HSAdminException {
// get the entity from the database
UnixUser detachedUnixUser = (UnixUser) existingEntity;
UnixUser attachedUnixUser = getEntityManager().find(detachedUnixUser.getClass(),
detachedUnixUser.getId());
// authorisation check
needsFullAccessOnUser(attachedUnixUser, "update");
// update fields where the login user has write access
if (attachedUnixUser.getUserId() != detachedUnixUser.getUserId())
throw new AuthorisationException(getLoginUser(), "update",
detachedUnixUser, "id");
attachedUnixUser.setName(detachedUnixUser.getName());
attachedUnixUser.setPassword(detachedUnixUser.getPassword());
if (hasFullAccessOnPacOf(attachedUnixUser))
attachedUnixUser.setComment(detachedUnixUser.getComment());
else if (!attachedUnixUser.getComment().equals(
detachedUnixUser.getComment()))
throw new AuthorisationException(getLoginUser(), "update",
detachedUnixUser, "comment");
if (hasFullAccessOnPacOf(attachedUnixUser))
attachedUnixUser.setHomedir(detachedUnixUser.getHomedir());
else if (!attachedUnixUser.getHomedir().equals(
detachedUnixUser.getHomedir()))
throw new AuthorisationException(getLoginUser(), "update",
detachedUnixUser, "homedir");
if (!attachedUnixUser.getShell().equals(detachedUnixUser.getShell()))
if (hasFullAccessOnPacOf(attachedUnixUser)
|| isLoginShell(attachedUnixUser.getShell())
|| !isLoginShell(detachedUnixUser.getShell()))
attachedUnixUser.setShell(detachedUnixUser.getShell());
else
throw new AuthorisationException(getLoginUser(), "update",
detachedUnixUser, "shell");
if (attachedUnixUser.isLocked() != detachedUnixUser.isLocked())
throw new AuthorisationException(getLoginUser(), "update",
detachedUnixUser, "locked");
if (detachedUnixUser.getQuotaSoftlimit() != null) {
if (hasFullAccessOnPacOf(attachedUnixUser)) {
attachedUnixUser.setQuotaSoftlimit(detachedUnixUser.getQuotaSoftlimit());
if (detachedUnixUser.getQuotaHardlimit() != null) {
attachedUnixUser.setQuotaHardlimit(detachedUnixUser.getQuotaHardlimit());
}
}
else {
Integer oldQuota = attachedUnixUser.getQuotaSoftlimit();
Integer newQuota = detachedUnixUser.getQuotaSoftlimit();
if (oldQuota != newQuota && !oldQuota.equals(newQuota))
throw new AuthorisationException(getLoginUser(), "update",
detachedUnixUser, "quota");
}
}
// update entity
return super.update(attachedUnixUser);
}
@Override
public void delete(Entity existingEntity) throws HSAdminException {
// get the entity from the database
UnixUser detachedUnixUser = (UnixUser) existingEntity;
UnixUser attachedUnixUser = getEntityManager().find(detachedUnixUser.getClass(),
detachedUnixUser.getId());
// authorisation check
if (attachedUnixUser.getName().length() < 7) {
throw new AuthorisationException(attachedUnixUser, "delete");
}
needsFullAccessOnPacOf(attachedUnixUser, "delete");
// delete entity
super.delete(attachedUnixUser);
}
// throws an AuthorisationException if the login user has no write acess
// on the pac of the given UnixUser
private boolean hasFullAccessOnPacOf(UnixUser user) {
// only pac admins (same name as pac) and the owner (customer) have
// write access to the pac
boolean isPacAdmin = getLoginUser().getName().equals(
user.getPac().getName());
boolean isCustomer = getLoginUser().getName().equals(
user.getPac().getCustomer().getName());
boolean isHostmaster = getLoginUser().hasHostmasterRole();
return isPacAdmin || isCustomer || isHostmaster;
}
// throws an AuthorisationException if the login user has no write acess
// on the pac of the given UnixUser
private void needsFullAccessOnPacOf(UnixUser user, String method)
throws AuthorisationException {
if (!hasFullAccessOnPacOf(user))
throw new AuthorisationException(getLoginUser(), method, user);
}
// throws an AuthorisationException if the login user has no read acess on
// the pac of the given UnixUser
private void needsPartialAccessOnPacOf(UnixUser user, String method)
throws AuthorisationException {
if (!hasFullAccessOnPacOf(user)
&& getLoginUser().getPac().id() != user.getPac().id())
throw new AuthorisationException(getLoginUser(), method, user);
}
// throws an AuthorisationException if the login user has not even partial
// write access on the given UnixUser
private void needsFullAccessOnUser(UnixUser user, String method)
throws AuthorisationException {
// neither pac admin (same name as pac), pac owner (customer) nor the
// user itself?
if (!hasFullAccessOnPacOf(user) && !getLoginUser().sameIdAs(user))
throw new AuthorisationException(getLoginUser(), method, user);
}
// returns true if the given shell is a login shell
private static boolean isLoginShell(String shell) {
// TODO: list of login shells should not be hardcoded
if (shell.equals("/bin/sh"))
return true;
if (shell.equals("/bin/bash"))
return true;
if (shell.equals("/bin/csh"))
return true;
if (shell.equals("/bin/tcsh"))
return true;
if (shell.equals("/bin/zsh"))
return true;
if (shell.equals("/bin/ksh"))
return true;
return false;
}
}

View File

@ -0,0 +1,105 @@
package de.hsadmin.mods.user;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.persistence.EntityManager;
import de.hsadmin.core.model.Entity;
import de.hsadmin.core.qserv.CompoundProcessor;
import de.hsadmin.core.qserv.EntityProcessorFactory;
import de.hsadmin.core.qserv.Processor;
import de.hsadmin.core.qserv.ShellProcessor;
/**
* Factory class which creates Processor instances for dealing with UNIX user
* accounts.
*
* @author mi
*/
public class UnixUserProcessorFactory implements EntityProcessorFactory {
/**
* @return a Processor which creates a new UNIX user account
*/
public <T extends Entity> Processor createCreateProcessor(EntityManager em,
T entity) {
UnixUser user = (UnixUser) entity;
CompoundProcessor aCP = new CompoundProcessor(new ShellProcessor(
"newusers", user.getName() + ":" + user.getPassword() + ":"
+ user.getUserId() + ":" + user.getPac().getName()
+ ":" + user.getComment() + ":" + user.getHomedir()
+ ":" + user.getShell() + "\n"));
appendSetQuotaProcessor(aCP, user);
appendMakeMaildirProcessor(aCP, user);
return aCP;
}
/**
* @return a Processor which updates an existing UNIX user account
*/
public <T extends Entity> Processor createUpdateProcessor(EntityManager em,
T entity) {
UnixUser user = (UnixUser) entity;
CompoundProcessor aCP = new CompoundProcessor(new ShellProcessor(
"usermod -c '" + user.getComment() + "'" + " -d '"
+ user.getHomedir() + "'" + " -s '" + user.getShell()
+ "' " + user.getName()));
if (user.getPassword() != null && user.getPassword().length() > 0)
aCP.appendProcessor(new ShellProcessor("chpasswd ", user.getName()
+ ":" + user.getPassword() + "\n"));
appendSetQuotaProcessor(aCP, user);
return aCP;
}
/**
* @return a Processor which deletes an existing UNIX user account
*/
public <T extends Entity> Processor createDeleteProcessor(EntityManager em,
T entity) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyMMdd-HHmm-");
String trashPrefix = "/home/trash/" + sdf.format(new Date());
UnixUser user = (UnixUser) entity;
CompoundProcessor aCP = new CompoundProcessor();
if (user.isDefaultHomedir())
aCP.appendProcessor(new ShellProcessor("mv '" + user.getHomedir()
+ "' '" + trashPrefix + user.getName() + "'"));
aCP.appendProcessor(new ShellProcessor("userdel " + user.getName()));
return aCP;
}
private void appendSetQuotaProcessor(CompoundProcessor aCP, UnixUser user) {
Integer quotaSoft = user.getQuotaSoftlimit();
if (quotaSoft == null || quotaSoft.intValue() == 0) {
aCP.appendProcessor(new ShellProcessor("setquota -u "
+ user.getName() + " 0 0 0 0 "
+ "`df /home/pacs/ | tail -n1 | cut -d' ' -f1`"));
return;
}
Integer userSoftQuota = quotaSoft * 1024;
Integer quotaHard = user.getQuotaHardlimit();
if (quotaHard == null) {
quotaHard = new Integer(0);
}
Integer userHardQuota = quotaHard * 1024;
if (userHardQuota.intValue() < userSoftQuota.intValue()) {
// set default value
userHardQuota = ((Double) (userSoftQuota * 1.5 + 32)).intValue();
}
aCP.appendProcessor(new ShellProcessor("setquota -u "
+ user.getName() + " " + userSoftQuota + " "
+ userHardQuota + " 0 0 "
+ "`df /home/pacs/ | tail -n1 | cut -d' ' -f1`"));
}
private void appendMakeMaildirProcessor(CompoundProcessor aCP, UnixUser user) {
aCP.appendProcessor(
new ShellProcessor(
"su -l " + user.getName() + " -s \"/bin/bash\" -c \"maildirmake " +
user.getHomedir() + "/Maildir" +
"\""
));
}
}

View File

@ -0,0 +1,229 @@
package de.hsadmin.remote;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import de.hsadmin.core.model.AuthenticationException;
import de.hsadmin.core.model.AuthorisationException;
import de.hsadmin.core.model.Entity;
import de.hsadmin.core.model.GenericModuleImpl;
import de.hsadmin.core.model.HSAdminException;
import de.hsadmin.core.model.ModuleInterface;
import de.hsadmin.core.model.TicketAuthentication;
import de.hsadmin.core.model.Transaction;
import de.hsadmin.mods.user.UnixUser;
public abstract class AbstractRemote implements IRemote {
private TicketAuthentication authentication;
public AbstractRemote() {
authentication = new TicketAuthentication();
}
protected abstract Class<? extends Entity> getEntityClass();
protected abstract void entity2map(Entity entity, Map<String, String> resultMap);
protected abstract void map2entity(Map<String, String> setParams, Entity entity);
protected abstract void regularizeKeys(Map<String, String> whereParams);
/* (non-Javadoc)
* @see de.hsadmin.remote.IRemote#search(java.lang.String, java.lang.String, java.util.Map)
*/
public List<Map<String, String>> search(String runAsUser, String ticket,
Map<String, String> whereParams) throws HSAdminException {
String user = runAsUser;
Transaction transaction = new Transaction(user);
try {
if (authentication.login(user, ticket)) {
ModuleInterface module = new GenericModuleImpl(transaction);
UnixUser unixUser = null;
unixUser = (UnixUser) module.findByString(UnixUser.class, user);
List<Entity> list = module.search(getEntityClass(),
buildQueryCondition(whereParams), null);
ArrayList<Map<String, String>> result = new ArrayList<Map<String, String>>();
for (Entity e : list) {
HashMap<String, String> entry = new HashMap<String, String>();
entity2map(e, entry);
if (e.isReadAllowedFor(unixUser)) {
result.add(entry);
}
}
return result;
} else {
throw new AuthenticationException("authentication failed");
}
} catch (SecurityException e) {
throw new HSAdminException(e);
} catch (IllegalArgumentException e) {
throw new HSAdminException(e);
} finally {
transaction.close();
}
}
/* (non-Javadoc)
* @see de.hsadmin.remote.IRemote#add(java.lang.String, java.lang.String, java.util.Map)
*/
public Map<String, String> add(String runAsUser, String ticket,
Map<String, String> setParams) throws HSAdminException {
String user = runAsUser;
Transaction transaction = new Transaction(user);
try {
if (authentication.login(user, ticket)) {
ModuleInterface module = new GenericModuleImpl(transaction);
Constructor<? extends Entity> constructor =
getEntityClass().getConstructor();
Entity entity = constructor.newInstance();
map2entity(setParams, entity);
transaction.beginTransaction();
Entity insertedEntity = module.add(entity);
transaction.commitTransaction();
HashMap<String, String> entry = new HashMap<String, String>();
entity2map(insertedEntity, entry);
return entry;
} else {
throw new AuthenticationException("authentication failed");
}
} catch (Exception e) {
throw new HSAdminException(e);
} finally {
transaction.close();
}
}
/* (non-Javadoc)
* @see de.hsadmin.remote.IRemote#delete(java.lang.String, java.lang.String, java.util.Map)
*/
public void delete(String runAsUser, String ticket,
Map<String, String> whereParams) throws HSAdminException {
String user = runAsUser;
Transaction transaction = new Transaction(user);
try {
if (authentication.login(user, ticket)) {
ModuleInterface module = new GenericModuleImpl(transaction);
UnixUser unixUser = null;
unixUser = (UnixUser) module.findByString(UnixUser.class, user);
String queryCondition = buildQueryCondition(whereParams);
if (queryCondition == null || queryCondition.length() == 0) {
throw new HSAdminException(
"better safe than sorry: no where parameter found");
}
List<Entity> list = module.search(getEntityClass(),
queryCondition, null);
transaction.beginTransaction();
for (Entity e : list) {
if (e.isWriteAllowedFor(unixUser)) {
module.delete(e);
} else {
throw new AuthorisationException(unixUser, "delete", e);
}
}
transaction.commitTransaction();
} else {
throw new AuthenticationException("authentication failed");
}
} catch (SecurityException e) {
throw new HSAdminException(e);
} catch (IllegalArgumentException e) {
throw new HSAdminException(e);
} finally {
transaction.close();
}
}
/* (non-Javadoc)
* @see de.hsadmin.remote.IRemote#update(java.lang.String, java.lang.String, java.util.Map, java.util.Map)
*/
public List<Map<String, String>> update(String runAsUser, String ticket,
Map<String, String> setParams, Map<String, String> whereParams)
throws HSAdminException {
String user = runAsUser;
Transaction transaction = new Transaction(user);
try {
if (authentication.login(user, ticket)) {
ModuleInterface module = new GenericModuleImpl(transaction);
UnixUser unixUser = null;
unixUser = (UnixUser) module.findByString(UnixUser.class, user);
ArrayList<Map<String, String>> result = new ArrayList<Map<String, String>>();
String queryCondition = buildQueryCondition(whereParams);
if (queryCondition == null || queryCondition.length() == 0) {
throw new HSAdminException(
"better safe than sorry: no where parameter found");
}
List<Entity> list = module.search(getEntityClass(),
queryCondition, "ORDER BY name ASC");
transaction.beginTransaction();
for (Entity update : list) {
if (update.isWriteAllowedFor(unixUser)) {
transaction.detach(update);
map2entity(setParams, update);
update = module.update(update);
HashMap<String, String> entry = new HashMap<String, String>();
entity2map(update, entry);
result.add(entry);
} else {
throw new AuthorisationException(unixUser, "update", update);
}
}
transaction.commitTransaction();
return result;
} else {
throw new AuthenticationException("authentication failed");
}
} catch (SecurityException e) {
throw new HSAdminException(e);
} catch (IllegalArgumentException e) {
throw new HSAdminException(e);
} finally {
transaction.close();
}
}
protected boolean assertNotNull(String string) {
return string != null && string.length() > 0;
}
protected boolean assertNotNull(Integer integ) {
return integ != null;
}
private String buildQueryCondition(Map<String, String> whereParams) {
regularizeKeys(whereParams);
StringBuffer cond = new StringBuffer();
Iterator<String> keyIterator = whereParams.keySet().iterator();
while (keyIterator.hasNext()) {
if (cond.length() > 0) {
cond.append(" AND ");
}
String field = keyIterator.next();
String value = whereParams.get(field).replaceAll("'", "\'");
cond.append("obj.");
cond.append(field);
cond.append(" = '");
cond.append(value);
cond.append("'");
}
return cond.toString();
}
protected void replaceKey(Map<String, String> whereParams, String shortKey, String regularKey) {
if (whereParams.containsKey(shortKey)) {
String value = whereParams.get(shortKey);
whereParams.remove(shortKey);
whereParams.put(regularKey, value);
}
}
protected boolean assertNotNull(Date aDate) {
return aDate != null;
}
}

View File

@ -0,0 +1,35 @@
package de.hsadmin.remote;
import java.util.List;
import java.util.Map;
import de.hsadmin.core.model.HSAdminException;
public interface IRemote {
public abstract List<Map<String, String>> search(
String runAsUser,
String ticket,
Map<String, String> whereParams
) throws HSAdminException;
public abstract Map<String, String> add(
String runAsUser,
String ticket,
Map<String, String> setParams
) throws HSAdminException;
public abstract void delete(
String runAsUser,
String ticket,
Map<String, String> whereParams
) throws HSAdminException;
public abstract List<Map<String, String>> update(
String runAsUser,
String ticket,
Map<String, String> setParams,
Map<String, String> whereParams
) throws HSAdminException;
}

View File

@ -0,0 +1,49 @@
package de.hsadmin.remote;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import de.hsadmin.core.model.Entity;
import de.hsadmin.core.qserv.QueueTask;
public class QueueTaskRemote extends AbstractRemote {
private static final DateFormat df = SimpleDateFormat.getDateInstance(DateFormat.SHORT);
@Override
protected Class<? extends Entity> getEntityClass() {
return QueueTask.class;
}
@Override
protected void entity2map(Entity entity, Map<String, String> resultMap) {
QueueTask task = (QueueTask) entity;
resultMap.put("id", Long.toString(task.getId()));
resultMap.put("status", task.getStatus().toString());
resultMap.put("title", task.getTitle());
resultMap.put("details", task.getDetails());
resultMap.put("exception", task.getException());
resultMap.put("user", task.getUser().getName());
Date started = task.getStarted();
if (assertNotNull(started)) {
resultMap.put("started", df.format(started));
}
Date finished = task.getFinished();
if (assertNotNull(finished)) {
resultMap.put("finished", df.format(finished));
}
}
@Override
protected void map2entity(Map<String, String> setParams, Entity entity) {
// never used
}
@Override
protected void regularizeKeys(Map<String, String> whereParams) {
replaceKey(whereParams, "user", "user.name");
}
}

View File

@ -0,0 +1,81 @@
package de.hsadmin.remote;
import java.util.Map;
import de.hsadmin.core.model.Entity;
import de.hsadmin.mods.user.UnixUser;
public class UnixUserRemote extends AbstractRemote {
@Override
protected Class<? extends Entity> getEntityClass() {
return UnixUser.class;
}
@Override
protected void entity2map(Entity entity, Map<String, String> map) {
UnixUser user = (UnixUser) entity;
map.put("id", Long.toString(user.getId()));
map.put("name", user.getName());
map.put("comment", user.getComment());
map.put("userid", Long.toString(user.getUserId()));
map.put("pac", user.getPac().getName());
map.put("shell", user.getShell());
map.put("homedir", user.getHomedir());
Integer quotaSoft = user.getQuotaSoftlimit();
if (assertNotNull(quotaSoft)) {
map.put("quota_softlimit", quotaSoft.toString());
}
Integer quotaHard = user.getQuotaHardlimit();
if (assertNotNull(quotaHard)) {
map.put("quota_hardlimit", quotaHard.toString());
}
}
@Override
protected void map2entity(Map<String, String> map, Entity entity) {
UnixUser user = (UnixUser) entity;
String id = map.get("id");
if (assertNotNull(id)) {
user.setId(Long.parseLong(id));
}
String name = map.get("name");
if (assertNotNull(name)) {
user.setName(name);
}
String password = map.get("password");
if (assertNotNull(password)) {
user.setPassword(password);
}
String comment = map.get("comment");
if (assertNotNull(comment)) {
user.setComment(comment);
}
String userid = map.get("userid");
if (assertNotNull(userid)) {
user.setUserId(Long.parseLong(userid));
}
String shell = map.get("shell");
if (assertNotNull(shell)) {
user.setShell(shell);
}
String homedir = map.get("homedir");
if (assertNotNull(homedir)) {
user.setHomedir(homedir);
}
String quota = map.get("quota_softlimit");
if (assertNotNull(quota)) {
user.setQuotaSoftlimit(Integer.parseInt(quota));
}
String quotaLimit = map.get("quota_hardlimit");
if (assertNotNull(quotaLimit)) {
user.setQuotaHardlimit(Integer.parseInt(quotaLimit));
}
}
@Override
protected void regularizeKeys(Map<String, String> whereParams) {
replaceKey(whereParams, "pac", "pac.name");
}
}

View File

@ -0,0 +1,307 @@
/*
Copyright 2009 jtpl.sourceforge.net
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package net.sf.jtpl;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* <b>Jtpl: a very simple template engine for Java</b><br>
* Contact: <a href="mailto:emmanuel.alliel@gmail.com">emmanuel.alliel@gmail.com</a><br>
* Web: <a href="http://jtpl.sourceforge.net">http://jtpl.sourceforge.net</a><br>
*
* @version $LastChangedRevision: 51 $
* @author Emmanuel ALLIEL
* @author Staffan Olsson
*
* <p>
* Template syntax:<br>
* &nbsp;&nbsp;&nbsp;Variables:<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>{VARIABLE_NAME}</code><br>
* &nbsp;&nbsp;&nbsp;Blocks:<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;!-- BEGIN: BlockName --&gt;</code><br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;!-- BEGIN: SubBlockName --&gt;</code><br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;!-- END: SubBlockName --&gt;</code><br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;!-- END: BlockName --&gt;</code><br>
* <p>
* License: Apache 2.0<br>
*/
public class Jtpl implements Serializable
{
private static final long serialVersionUID = -7175035307912229580L;
private HashMap<String, String> blocks = new HashMap<String, String>();
private HashMap<String, String> parsedBlocks = new HashMap<String, String>();
private HashMap<String, String> subBlocks = new HashMap<String, String>();
private HashMap<String, String> vars = new HashMap<String, String>();
// flag for backwards compatibility, will probably be reomved in future releases
private boolean failSilently = false;
private boolean implicitMain = false;
/**
* Constructs a Jtpl object and reads the template from a file.
* For backwards compatibility this constructor enables 'failSilently'.
* @param fileName the <code>file name</code> of the template, exemple: "java/folder/index.tpl"
* @throws IOException when an i/o error occurs while reading the template.
*/
public Jtpl(String fileName) throws IOException
{
this(new File(fileName));
// this is the old constructor so it enables the old (pre-1.3) behavior on errors
this.failSilently = true;
}
/**
* Constructs a Jtpl object and reads the template from a file.
* @param file readable file containing template source
* @throws IOException when an i/o error occurs while reading the template.
*/
public Jtpl(File file) throws IOException
{
FileReader fr = new FileReader(file);
String fileText = readFile(fr);
makeTree(fileText);
}
/**
* Constructs a Jtpl object and reads the template from arbitrary input source.
* @param template the template source
* @throws IOException when an i/o error occurs while reading the template.
*/
public Jtpl(Reader template) throws IOException
{
String fileText = readFile(template);
makeTree(fileText);
}
/**
* Assign a template variable.
* For variables that are used in blocks, the variable value
* must be set before <code>parse</code> is called.
* @param varName the name of the variable to be set.
* @param varData the new value of the variable.
*/
public void assign(String varName, String varData)
{
vars.put(varName, varData);
}
/**
* Generates the HTML page and return it into a String.
*/
public String out()
{
if (this.implicitMain) {
this.parse("main");
}
Object main = parsedBlocks.get("main");
if (main == null) {
throw new IllegalStateException("'main' block not parsed");
}
return(main.toString());
}
/**
* Parse a template block.
* If the block contains variables, these variables must be set
* before the block is added.
* If the block contains subblocks, the subblocks
* must be parsed before this block.
* @param blockName the name of the block to be parsed.
* @throws IllegalArgumentException if the block name is not found (and failSiletly==false)
*/
public void parse(String blockName) throws IllegalArgumentException
{
String copy = "";
if (implicitMain && !"main".equals(blockName) && !blockName.startsWith("main.")) {
blockName = "main." + blockName;
}
try {
copy = blocks.get(blockName).toString();
} catch (NullPointerException e) {
if (!this.failSilently) throw new IllegalArgumentException(
"Block '" + blockName + "' not found." +
" Matches " + locateBlock(blockName));
}
Pattern pattern = Pattern.compile("\\{([\\w\\.]+)\\}");
Matcher matcher = pattern.matcher(copy);
pattern = Pattern.compile("_BLOCK_\\.(.+)");
for (Matcher matcher2; matcher.find();)
{
String match = matcher.group(1);
matcher2 = pattern.matcher(match);
if (matcher2.find())
{
if (parsedBlocks.containsKey(matcher2.group(1)))
{
copy = copy.replaceFirst("\\{"+match+"\\}", escape(
parsedBlocks.get(matcher2.group(1)).toString()));
}
else
{
copy = copy.replaceFirst("\\{"+match+"\\}", "");
}
}
else
{
if (vars.containsKey(match))
{
copy = copy.replaceFirst("\\{"+match+"\\}", escape(
vars.get(match).toString()));
}
else
{
// Leave unchanged because it might be wanted in output.
// Can always be removed by assigning empty value.
//copy = copy.replaceFirst("\\{"+match+"\\}", "");
}
}
}
if (parsedBlocks.containsKey(blockName))
{
parsedBlocks.put(blockName, parsedBlocks.get(blockName) + copy);
}
else
{
parsedBlocks.put(blockName, copy);
}
if (subBlocks.containsKey(blockName))
{
parsedBlocks.put(subBlocks.get(blockName), "");
}
}
/**
* Template parsing uses regex replace to insert result text,
* which means that special characters in replacement string must be escaped.
* @param replacement The text that should appear in output.
* @return Text escaped so that it works as String.replaceFirst replacement.
*/
protected String escape(String replacement) {
return replacement.replace("\\", "\\\\").replace("$", "\\$");
}
/**
* Lists the blocks that end with the given blockName.
* @param blockName The name as used in parse
* @return Blocks where blockName is the child
* (the Set's toString lists the full names)
*/
protected Set<Object> locateBlock(final String blockName) {
Set<Object> matches = new java.util.HashSet<Object>();
for (Iterator<String> it = blocks.keySet().iterator(); it.hasNext(); ) {
Object b = it.next();
if (b.toString().endsWith('.' + blockName)) matches.add(b);
}
return matches;
}
private String readFile(Reader fr) throws IOException
{
StringBuffer content = new StringBuffer();
for (int c; (c = fr.read()) != -1; content.append((char)c));
fr.close();
return content.toString();
}
private void makeTree(String fileText)
{
// BEGIN: implicit main
if (!Pattern.compile(".*<!--\\s*BEGIN\\s*:\\s*main\\s*-->.*", Pattern.DOTALL)
.matcher(fileText).matches()) {
this.implicitMain = true; // affects parse(block) and out()
fileText = "<!-- BEGIN: main -->" + fileText + "<!-- END: main -->";
}
// END: implicit main
Pattern pattern = Pattern.compile("<!--\\s*(BEGIN|END)\\s*:\\s*(\\w+)\\s*-->(.*?)(?=(?:<!--\\s*(?:BEGIN|END)\\s*:\\s*\\w+\\s*-->)|(?:\\s*$))", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Matcher matcher = pattern.matcher(fileText);
ArrayList<String> blockNames = new ArrayList<String>();
String parentName = "";
int lastlength = 0; // used in newline trimming to see if one block immediately follows the previous
while (matcher.find())
{
// BEGIN: newline trimming
String after = matcher.group(3); // contents after tag
if (lastlength == 0 || fileText.charAt(matcher.start() - 1) == '\n') {
after = after.replaceFirst("^\\r?\\n", "");
}
lastlength = after.length();
// END: newline trimming
if (matcher.group(1).toUpperCase().equals("BEGIN"))
{
parentName = implode(blockNames);
blockNames.add(matcher.group(2));
String currentBlockName = implode(blockNames);
if (blocks.containsKey(currentBlockName))
{
blocks.put(currentBlockName, blocks.get(currentBlockName) + after);
}
else
{
blocks.put(currentBlockName, after);
}
if (blocks.containsKey(parentName))
{
blocks.put(parentName, blocks.get(parentName) + "{_BLOCK_." + currentBlockName + "}");
}
else
{
blocks.put(parentName, "{_BLOCK_." + currentBlockName + "}");
}
subBlocks.put(parentName, currentBlockName);
subBlocks.put(currentBlockName, "");
}
else if (matcher.group(1).toUpperCase().equals("END"))
{
blockNames.remove(blockNames.size()-1);
parentName = implode(blockNames);
if (blocks.containsKey(parentName))
{
blocks.put(parentName, blocks.get(parentName) + after);
}
else
{
blocks.put(parentName, after);
}
}
}
}
private String implode(ArrayList<String> al)
{
String ret = "";
for (int i = 0; al.size() > i; i++)
{
if (i != 0)
{
ret += ".";
}
ret += al.get(i);
}
return (ret);
}
}

View File

@ -0,0 +1,136 @@
/*
Copyright 2009 jtpl.sourceforge.net
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package net.sf.jtpl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sf.jtpl.Jtpl;
/**
* The forward compatible template engine interface,
* replacing {@link Jtpl}.
*/
public class Template implements Serializable {
private static final long serialVersionUID = 3916690583929137140L;
private Jtpl t;
public Template(Reader template) throws IOException {
t = new Jtpl(template);
}
public Template(String templateSource) {
try {
t = new Jtpl(new StringReader(templateSource));
} catch (IOException e) {
throw new RuntimeException(e); // should be impossible with StringReader
}
}
public Template(File templateFile) throws FileNotFoundException {
FileReader r = new FileReader(templateFile);
try {
t = new Jtpl(templateFile);
} catch (IOException e) {
try {
r.close();
} catch (Exception nothingToDoAboutIt) {}
}
}
// proxying methods from Jtpl1
public Template assign(String varName, String varData) {
t.assign(varName, varData);
return this;
}
public Template parse(String blockName) throws IllegalArgumentException {
t.parse(blockName);
return this;
}
public String out() {
return t.out();
}
// bean properties support
public Template parse(String blockName, Object bean) {
assignAll(bean);
return parse(blockName);
}
public String out(Object bean) {
assignAll(bean);
return out();
}
protected void assignAll(Object bean) {
Map<String, Object> p = getBeanProperties(bean);
Iterator<String> i = p.keySet().iterator();
while (i.hasNext()) {
String key = (String) i.next();
assign(key.toUpperCase(), "" + p.get(key));
}
}
/**
* @param bean The instance that has properties named according to JavaBean standard.
* @return Map<String, Object> that should be considered immutable
*/
protected Map<String, Object> getBeanProperties(Object bean) {
HashMap<String, Object> values = new HashMap<String, Object>();
if (bean == null) return values;
Method[] m = bean.getClass().getMethods();
Pattern p = Pattern.compile("get([A-Z]\\w+)");
for (int i = 0; i < m.length; i++) {
if (m[i].getName().equals("getClass")) continue;
if (m[i].getParameterTypes().length > 0) continue;
Matcher r = p.matcher(m[i].getName());
if (r.matches()) {
try {
values.put(r.group(1).toLowerCase(), m[i].invoke(bean, new Object[0]));
} catch (IllegalArgumentException e) {
throw e;
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
return values;
}
}

View File

@ -0,0 +1,2 @@
user=de.hsadmin.remote.UnixUserRemote
q=de.hsadmin.remote.QueueTaskRemote