diff options
author | wbauer <wbauer@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4> | 2008-09-04 14:56:54 +0000 |
---|---|---|
committer | wbauer <wbauer@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4> | 2008-09-04 14:56:54 +0000 |
commit | e0f2c64ad6360e2ecec983cb5e0a60f812672106 (patch) | |
tree | 75040ef0d3424c8722d81163570c6770125b4d8c /bkucommon/src/main/java/at | |
parent | ea5a30db385d2859cc45c889877954bda00ac560 (diff) | |
download | mocca-e0f2c64ad6360e2ecec983cb5e0a60f812672106.tar.gz mocca-e0f2c64ad6360e2ecec983cb5e0a60f812672106.tar.bz2 mocca-e0f2c64ad6360e2ecec983cb5e0a60f812672106.zip |
finished access controller, accessed it from command invoker and
configured everything within onlinebku
git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@14 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4
Diffstat (limited to 'bkucommon/src/main/java/at')
18 files changed, 1302 insertions, 976 deletions
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/AccessControllerFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/AccessControllerFactory.java index 3b75a5f2..cd837cd7 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/AccessControllerFactory.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/AccessControllerFactory.java @@ -15,8 +15,9 @@ import at.gv.egiz.bku.accesscontrol.config.AccessControl; import at.gv.egiz.bku.accesscontrol.config.Chain;
import at.gv.egiz.bku.accesscontrol.config.Command;
import at.gv.egiz.bku.accesscontrol.config.ObjectFactory;
+import at.gv.egiz.bku.accesscontrol.config.Param;
import at.gv.egiz.bku.accesscontrol.config.Rule;
-import at.gv.egiz.bku.slcommands.impl.InfoboxReadCommandImpl;
+import at.gv.egiz.bku.accesscontroller.RuleChecker.PEER_TYPE;
import at.gv.egiz.bku.slexceptions.SLRuntimeException;
public class AccessControllerFactory {
@@ -24,6 +25,8 @@ public class AccessControllerFactory { private static AccessControllerFactory instance = new AccessControllerFactory();
private static Log log = LogFactory.getLog(AccessControllerFactory.class);
private static JAXBContext jaxbContext;
+ public static String INPUT_CHAIN = "InputChain";
+ public static String OUTPUT_CHAIN = "OutputChain";
static {
try {
@@ -63,43 +66,72 @@ public class AccessControllerFactory { public void registerChainChecker(ChainChecker cc) {
chainTable.put(cc.getId(), cc);
}
-
+
+ public CommandParamChecker createParamChecker(String cmd) {
+ if ((cmd != null) && (cmd.startsWith("Infobox"))) {
+ return new InfoboxParamChecker();
+ } else {
+ return null;
+ }
+ }
+
public RuleChecker createRuleChecker(Rule rule) {
RuleChecker rc;
+ rc = new RuleChecker(rule.getId());
Command cmd = rule.getCommand();
if (cmd != null) {
- if ((cmd.getParam() != null) && (cmd.getParam().size()>0)) {
- if (cmd.getName().startsWith("Infobox")) {
- rc = new InfoboxRuleChecker(rule.getId());
- } else {
- throw new SLRuntimeException("Cannot handle parameters for command "+cmd.getName());
- }
- } else {
- rc = new RuleChecker(rule.getId());
+ rc.setCommandName(cmd.getName());
+ for (Param p : cmd.getParam()) {
+ rc.addParameter(p.getName(), p.getValue());
}
- } else {
- rc = new RuleChecker(rule.getId());
}
- // FIXME TODO cont. here
-
-
- return rc;
+ rc.setAuthenticationClass(rule.getAuthClass());
+ if (rule.getIPv4Address() != null) {
+ rc.setPeerId(rule.getIPv4Address(), PEER_TYPE.IP);
+ } else if (rule.getDomainName() != null) {
+ rc.setPeerId(rule.getDomainName(), PEER_TYPE.HOST);
+ } else if (rule.getURL() != null) {
+ rc.setPeerId(rule.getURL(), PEER_TYPE.URL);
+ }
+ rc.setAction(rule.getAction().getRuleAction());
+ rc.setChainId(rule.getAction().getChainRef());
+ rc.setUserAction(rule.getUserInteraction());
+ return rc;
}
-
-
+
public void init(InputStream is) throws JAXBException {
+ chainTable.clear();
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
AccessControl ac = (AccessControl) unmarshaller.unmarshal(is);
List<Chain> chainList = ac.getChains().getChain();
- log.debug("Found "+chainList.size()+" chains in config");
+ log.debug("Found " + chainList.size() + " chains in config");
for (Chain chain : chainList) {
+ log.trace("Creating chain: " + chain.getId());
+ ChainChecker cc = createChainChecker(chain.getId(), false);
List<Rule> ruleList = chain.getRules().getRule();
- log.debug("Found "+ruleList.size()+" rules in chain "+chain.getId());
+ log
+ .debug("Found " + ruleList.size() + " rules in chain "
+ + chain.getId());
for (Rule rule : ruleList) {
- //rule.g
+ log.trace("Creating rule: " + rule.getId());
+ cc.addRule(createRuleChecker(rule));
+ }
+ registerChainChecker(cc);
+ }
+ validate();
+ }
+
+ private void validate() {
+ for (ChainChecker chain : chainTable.values()) {
+ for (RuleChecker rule : chain.getRules()) {
+ if (rule.getChainId() != null) {
+ log.trace("Checking reference to chain: "+rule.getChainId());
+ if (getChainChecker(rule.getChainId()) == null) {
+ throw new SLRuntimeException("Invalid reference to unknown chain: "+rule.getChainId());
+ }
+ }
}
}
-
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/ChainChecker.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/ChainChecker.java index 242d9b02..a290fe8d 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/ChainChecker.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/ChainChecker.java @@ -1,5 +1,6 @@ package at.gv.egiz.bku.accesscontroller;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -35,6 +36,10 @@ public class ChainChecker implements AccessChecker { rules.add(rule);
}
}
+
+ public List<RuleChecker> getRules() {
+ return Collections.unmodifiableList(rules);
+ }
@Override
public ChainResult check(AccessCheckerContext checkCtx) throws SLException {
@@ -43,7 +48,6 @@ public class ChainChecker implements AccessChecker { log.trace("Checking rule: "+rule.getId());
RuleResult result = rule.check(checkCtx);
if (result.matchFound()) {
- log.debug("Found matching rule: "+rule.getId());
if (result.getDelegateChainId() != null) {
// process chain
ChainChecker cc = AccessControllerFactory.getInstance().getChainChecker(result.getDelegateChainId());
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/CommandParamChecker.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/CommandParamChecker.java new file mode 100644 index 00000000..3927c3c9 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/CommandParamChecker.java @@ -0,0 +1,52 @@ +package at.gv.egiz.bku.accesscontroller;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import at.gv.egiz.bku.slcommands.SLCommand;
+
+public abstract class CommandParamChecker {
+
+ protected List<Tupel<String, String>> paramList = new LinkedList<Tupel<String, String>>();
+
+ public static class Tupel<T, Q> {
+ private T key;
+ private Q val;
+
+ public Tupel(T key, Q val) {
+ if ((key == null) || (val == null)) {
+ throw new NullPointerException("Tupel key and value must not be null");
+ }
+ this.key = key;
+ this.val = val;
+ }
+
+ public T getKey() {
+ return key;
+ }
+
+ public Q getVal() {
+ return val;
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean equals(Object other) {
+ if (other instanceof Tupel) {
+ Tupel ot = (Tupel) other;
+ return (key.equals(ot.key) && val.equals(ot.val));
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ return key.hashCode();
+ }
+ }
+
+ public void addParameter(String key, String value) {
+ paramList.add(new Tupel<String, String>(key, value));
+ }
+
+ public abstract boolean checkParameter(SLCommand cmd);
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/InfoboxParamChecker.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/InfoboxParamChecker.java new file mode 100644 index 00000000..33689ae0 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/InfoboxParamChecker.java @@ -0,0 +1,58 @@ +package at.gv.egiz.bku.accesscontroller;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.bku.slcommands.InfoboxReadCommand;
+import at.gv.egiz.bku.slcommands.SLCommand;
+import at.gv.egiz.bku.slexceptions.SLRuntimeException;
+
+public class InfoboxParamChecker extends CommandParamChecker {
+ private static Log log = LogFactory.getLog(InfoboxParamChecker.class);
+
+ public final static String INFOBOX_ID = "InfoboxIdentifier";
+ public final static String PERSON_ID = "PersonIdentifier";
+ public final static String DERIVED = "derived";
+
+ @Override
+ public boolean checkParameter(SLCommand cmd) {
+ if (paramList.size() == 0) {
+ return true;
+ }
+
+ if (cmd instanceof InfoboxReadCommand) {
+ InfoboxReadCommand irc = (InfoboxReadCommand) cmd;
+ for (Tupel<String, String> param : paramList) {
+ if (param.getKey().equals(INFOBOX_ID)) {
+ if (!param.getVal().equals(irc.getInfoboxIdentifier())) {
+ return false;
+ }
+ } else if (param.getKey().equals(PERSON_ID)) {
+ if (param.getVal().equals(DERIVED)) {
+ if (irc.getIdentityLinkDomainId() == null) {
+ return false;
+ }
+ } else {
+ Pattern p = Pattern.compile(param.getVal());
+ Matcher m = p.matcher(irc.getIdentityLinkDomainId());
+ if (!m.matches()) {
+ return false;
+ }
+ }
+
+ } else {
+ throw new SLRuntimeException("Cannot handle parameter "
+ + param.getKey());
+ }
+ }
+ return true;
+ } else {
+ log.error("Cannot handle parameter for command: " + cmd.getName());
+ throw new SLRuntimeException("Cannot handle parameters for command: "
+ + cmd.getName());
+ }
+ }
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/InfoboxRuleChecker.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/InfoboxRuleChecker.java deleted file mode 100644 index 2981d24e..00000000 --- a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/InfoboxRuleChecker.java +++ /dev/null @@ -1,14 +0,0 @@ -package at.gv.egiz.bku.accesscontroller;
-
-/**
- * Adds infobox parameter checks
- * @author wbauer
- *
- */
-public class InfoboxRuleChecker extends RuleChecker {
-
- public InfoboxRuleChecker(String id) {
- super(id);
- }
-
-}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/RuleChecker.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/RuleChecker.java index c59f5b70..b0bf7fac 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/RuleChecker.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/RuleChecker.java @@ -31,6 +31,7 @@ public class RuleChecker implements AccessChecker { protected Action action;
protected UserAction userAction;
protected String chainId;
+ protected CommandParamChecker paramChecker;
public RuleChecker(String id) {
if (id == null) {
@@ -40,27 +41,33 @@ public class RuleChecker implements AccessChecker { }
public void setAuthenticationClass(String ac) {
- AuthenticationClass tmp = AuthenticationClass.fromString(ac);
- if (tmp == null) {
- throw new SLRuntimeException("Unknown authentication class " + ac);
+ if (ac != null) {
+ AuthenticationClass tmp = AuthenticationClass.fromString(ac);
+ if (tmp == null) {
+ throw new SLRuntimeException("Unknown authentication class " + ac);
+ }
+ authenticationClass = tmp;
}
- authenticationClass = tmp;
}
public void setAction(String ac) {
- Action tmp = Action.fromString(ac);
- if (tmp == null) {
- throw new SLRuntimeException("Unknown action " + ac);
+ if (ac != null) {
+ Action tmp = Action.fromString(ac);
+ if (tmp == null) {
+ throw new SLRuntimeException("Unknown action " + ac);
+ }
+ action = tmp;
}
- action = tmp;
}
public void setUserAction(String uac) {
- UserAction tmp = UserAction.fromString(uac);
- if (tmp == null) {
- throw new SLRuntimeException("Unknown user action " + uac);
+ if (uac != null) {
+ UserAction tmp = UserAction.fromString(uac);
+ if (tmp == null) {
+ throw new SLRuntimeException("Unknown user action " + uac);
+ }
+ userAction = tmp;
}
- userAction = tmp;
}
public void setChainId(String chainId) {
@@ -76,6 +83,22 @@ public class RuleChecker implements AccessChecker { public void setCommandName(String commandName) {
this.commandName = commandName;
commandNamePattern = Pattern.compile(commandName);
+ paramChecker = AccessControllerFactory.getInstance().createParamChecker(
+ commandName);
+ }
+
+ /**
+ * Make sure to set the commandName first
+ *
+ * @param key
+ * @param value
+ */
+ public void addParameter(String key, String value) {
+ if (paramChecker == null) {
+ throw new IllegalArgumentException("Cannot set parameters for command "
+ + commandName);
+ }
+ paramChecker.addParameter(key, value);
}
public String getId() {
@@ -83,22 +106,30 @@ public class RuleChecker implements AccessChecker { }
protected boolean matchAuthenticationClass(AuthenticationClass cls) {
- if (this.authenticationClass == null) {
+ if ((this.authenticationClass == null) || (cls == null)) {
return true;
}
return this.authenticationClass.compareTo(cls) <= 0;
}
protected boolean matchCommandName(SLCommand cmd) {
- if (commandName == null) {
+ if ((commandName == null) || (cmd == null)) {
return true;
}
Matcher matcher = commandNamePattern.matcher(cmd.getName());
- return matcher.matches();
+ if (matcher.matches()) {
+ if (paramChecker != null) {
+ return paramChecker.checkParameter(cmd);
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
}
protected boolean matchPeerId(String peerUrl) {
- if (peerId == null) {
+ if ((peerId == null) || (peerUrl == null)) {
return true;
}
if (peerType == PEER_TYPE.URL) {
@@ -110,7 +141,8 @@ public class RuleChecker implements AccessChecker { if (peerType == PEER_TYPE.HOST) {
try {
String host = url.getHost();
- String hostName = InetAddress.getByName(host).getCanonicalHostName();
+ String hostName = InetAddress.getByName(host)
+ .getCanonicalHostName();
Matcher matcher = peerIdPattern.matcher(hostName);
return matcher.matches();
} catch (UnknownHostException e) {
@@ -143,9 +175,13 @@ public class RuleChecker implements AccessChecker { && matchPeerId(checkCtx.getPeerUrl())) {
log.debug("Match found for rule: " + id);
return new RuleResult(action, userAction, true, chainId);
- }
+ }
log.debug("No match found for rule: " + id);
return new RuleResult(action, userAction, false, chainId);
}
+ public String getChainId() {
+ return chainId;
+ }
+
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/SecurityManagerFacade.java b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/SecurityManagerFacade.java new file mode 100644 index 00000000..32242772 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/accesscontroller/SecurityManagerFacade.java @@ -0,0 +1,102 @@ +package at.gv.egiz.bku.accesscontroller;
+
+import java.io.InputStream;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.bku.slcommands.SLCommand;
+import at.gv.egiz.bku.slcommands.SLSourceContext;
+import at.gv.egiz.bku.slcommands.SLTargetContext;
+
+/**
+ * Facade for the access controller
+ */
+public class SecurityManagerFacade {
+
+ private static Log log = LogFactory.getLog(SecurityManagerFacade.class);
+
+ private boolean allowUnmatched = false;
+ private ChainChecker inputFilter = null;
+ private ChainChecker outputFilter = null;
+
+ public boolean mayInvokeCommand(SLCommand cmd, SLSourceContext ctx) {
+ if (inputFilter != null) {
+ AuthenticationClass ac = AuthenticationClassifier.getAuthenticationClass(
+ ctx.isSourceIsDataURL(), ctx.getSourceUrl(), ctx
+ .getSourceCertificate());
+ AccessCheckerContext acc = new AccessCheckerContext(cmd, ac, ctx
+ .getSourceUrl().toString());
+ try {
+ ChainResult cr = inputFilter.check(acc);
+ if (cr.matchFound()) {
+ if (cr.getAction() == Action.ALLOW) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return allowUnmatched;
+ }
+ } catch (Exception e) {
+ log.error(e);
+ return false;
+ }
+ } else {
+ log.warn("No input chain defined");
+ return allowUnmatched;
+ }
+ }
+
+ public boolean maySendResult(SLCommand cmd, SLTargetContext ctx) {
+ if (outputFilter != null) {
+ AuthenticationClass ac = AuthenticationClassifier.getAuthenticationClass(
+ ctx.isTargetIsDataURL(), ctx.getTargetUrl(), ctx
+ .getTargetCertificate());
+ AccessCheckerContext acc = new AccessCheckerContext(cmd, ac, ctx
+ .getTargetUrl().toString());
+ try {
+ ChainResult cr = outputFilter.check(acc);
+ if (cr.matchFound()) {
+ if (cr.getAction() == Action.ALLOW) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return allowUnmatched;
+ }
+ } catch (Exception e) {
+ log.error(e);
+ return false;
+ }
+ } else {
+ log.warn("No output chain defined");
+ return allowUnmatched;
+ }
+ }
+
+ /**
+ * Default policy if not match was found
+ *
+ * @param allow
+ */
+ public void setAllowUnmatched(boolean allow) {
+ this.allowUnmatched = allow;
+ }
+
+ public void init(InputStream is) {
+ inputFilter = null;
+ outputFilter = null;
+ AccessControllerFactory fab = AccessControllerFactory.getInstance();
+ try {
+ fab.init(is);
+ } catch (JAXBException e) {
+ log.error(e);
+ }
+ inputFilter = fab.getChainChecker(AccessControllerFactory.INPUT_CHAIN);
+ outputFilter = fab.getChainChecker(AccessControllerFactory.OUTPUT_CHAIN);
+ }
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManager.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManager.java index a4e5bd90..ed37f08f 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManager.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManager.java @@ -16,6 +16,7 @@ */ package at.gv.egiz.bku.binding;
+import java.net.MalformedURLException; import java.util.Locale;
import java.util.Set;
@@ -34,28 +35,28 @@ public interface BindingProcessorManager { * FactoryMethod creating a new BindingProcessor object.
* The created binding processor must be passed to the process method to execute.
*
- * @param protcol
- * the transport binding protocol
+ * @param urlString
+ * the source url
* @param aSessionId
* optional an external sessionId (e.g. http session) could be
* provided. This parameter may be null.
* @param locale the locale used for user interaction, may be null
*/
- public BindingProcessor createBindingProcessor(String protcol,
- String aSessionId, Locale locale);
+ public BindingProcessor createBindingProcessor(String urlString,
+ String aSessionId, Locale locale) throws MalformedURLException;
/**
* FactoryMethod creating a new BindingProcessor object.
* The created binding processor must be passed to the process method to execute.
*
* @param protcol
- * the transport binding protocol
+ * the source url
* @param aSessionId
* optional an external sessionId (e.g. http session) could be
* provided. This parameter may be null.
*/
- public BindingProcessor createBindingProcessor(String protcol,
- String aSessionId);
+ public BindingProcessor createBindingProcessor(String urlString,
+ String aSessionId) throws MalformedURLException;
/**
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManagerImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManagerImpl.java index 7a3b1bb9..6f5ca2d2 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManagerImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManagerImpl.java @@ -16,6 +16,8 @@ */ package at.gv.egiz.bku.binding;
+import java.net.MalformedURLException; +import java.net.URL; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -152,20 +154,22 @@ public class BindingProcessorManagerImpl implements BindingProcessorManager { /**
* Uses the default locale
*/
- public BindingProcessor createBindingProcessor(String protocol,
- String aSessionId) {
- return createBindingProcessor(protocol, aSessionId, null);
+ public BindingProcessor createBindingProcessor(String srcUrl,
+ String aSessionId) throws MalformedURLException {
+ return createBindingProcessor(srcUrl, aSessionId, null);
}
/**
* FactoryMethod creating a new BindingProcessor object.
*
* @param protocol
- * must not be null
+ * must not be null + * @throws MalformedURLException
*/
- public BindingProcessor createBindingProcessor(String protocol,
- String aSessionId, Locale locale) {
- String low = protocol.toLowerCase();
+ public BindingProcessor createBindingProcessor(String srcUrl,
+ String aSessionId, Locale locale) throws MalformedURLException { + URL url = new URL(srcUrl);
+ String low = url.getProtocol().toLowerCase();
Protocol proto = null;
for (int i = 0; i < SUPPORTED_PROTOCOLS.length; i++) {
if (SUPPORTED_PROTOCOLS[i].toString().equals(low)) {
@@ -177,7 +181,7 @@ public class BindingProcessorManagerImpl implements BindingProcessorManager { throw new UnsupportedOperationException();
}
BindingProcessor bindingProcessor = new HTTPBindingProcessor(aSessionId,
- commandInvokerClass.newInstance(), proto);
+ commandInvokerClass.newInstance(), url);
STAL stal = stalFactory.createSTAL();
bindingProcessor.init(stal, commandInvokerClass.newInstance());
if (locale != null) {
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java index e6d5e075..6d654639 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java @@ -16,12 +16,13 @@ */ package at.gv.egiz.bku.binding;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.SocketTimeoutException;
-import java.security.cert.X509Certificate;
-
-import at.gv.egiz.bku.slcommands.SLResult;
+import java.io.IOException; +import java.io.InputStream; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.security.cert.X509Certificate; + +import at.gv.egiz.bku.slcommands.SLResult; /**
* Transmit a security layer result to DataURL via HTTP POST, encoded as multipart/form-data.
@@ -41,7 +42,9 @@ public interface DataUrlConnection { public static final String XML_RESPONSE_ENCODING = "UTF-8";
- public String getProtocol();
+ public String getProtocol(); + + public URL getUrl();
/**
* Set a HTTP Header.
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java index 134d765e..9f5d70cb 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java @@ -212,5 +212,10 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI { @Override
public DataUrlConnectionSPI newInstance() {
return new DataUrlConnectionImpl();
- }
+ } + + @Override + public URL getUrl() { + return url; + }
}
\ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index b79f7d55..19f22126 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -1,820 +1,818 @@ /* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.bku.binding;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.net.ssl.SSLHandshakeException;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.URIResolver;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import at.gv.egiz.bku.slcommands.SLCommand;
-import at.gv.egiz.bku.slcommands.SLCommandContext;
-import at.gv.egiz.bku.slcommands.SLCommandFactory;
-import at.gv.egiz.bku.slcommands.SLCommandInvoker;
-import at.gv.egiz.bku.slcommands.SLResult;
-import at.gv.egiz.bku.slcommands.SLSourceContext;
-import at.gv.egiz.bku.slcommands.SLTargetContext;
-import at.gv.egiz.bku.slcommands.impl.ErrorResultImpl;
-import at.gv.egiz.bku.slexceptions.SLBindingException;
-import at.gv.egiz.bku.slexceptions.SLCanceledException;
-import at.gv.egiz.bku.slexceptions.SLException;
-import at.gv.egiz.bku.slexceptions.SLRuntimeException;
-import at.gv.egiz.bku.utils.StreamUtil;
-import at.gv.egiz.bku.utils.binding.Protocol;
-import at.gv.egiz.bku.utils.urldereferencer.FormDataURLSupplier;
-import at.gv.egiz.bku.utils.urldereferencer.SimpleFormDataContextImpl;
-import at.gv.egiz.bku.utils.urldereferencer.StreamData;
-import at.gv.egiz.bku.utils.urldereferencer.URIResolverAdapter;
-import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
-import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext;
-import at.gv.egiz.stal.QuitRequest;
-import at.gv.egiz.stal.STALRequest;
-
-/**
- * Class performing the HTTP binding as defined by the CCE specification.
- * Currently a huge monolithic class.
- * @TODO refactor
- */
-@SuppressWarnings("unchecked")
-public class HTTPBindingProcessor extends AbstractBindingProcessor implements
- FormDataURLSupplier {
-
- private static Log log = LogFactory.getLog(HTTPBindingProcessor.class);
-
- private static enum State {
- INIT, PROCESS, DATAURL, TRANSFORM, FINISHED
- };
-
- public final static Collection<String> XML_REQ_TRANSFER_ENCODING = Arrays
- .asList(new String[] { "binary" });
-
- /**
- * Defines the maximum number of dataurl connects that are allowed within a
- * single SL Request processing.
- */
- protected static int MAX_DATAURL_HOPS = 10;
-
- protected static String XML_MIME_TYPE = "text/xml";
- protected static String BINARY_MIME_TYPE = "application/octet-stream";
-
- /**
- * If null everything is ok and the result is taken from the command invoker.
- */
- protected SLException bindingProcessorError;
- protected SLCommandInvoker commandInvoker;
- protected DataUrlResponse dataUrlResponse;
- protected Map<String, String> headerMap = Collections.EMPTY_MAP;
- protected SLCommand slCommand;
- protected Map<String, FormParameter> formParameterMap = new HashMap<String, FormParameter>();
- protected SLSourceContext srcContex = new SLSourceContext();
- protected SLTargetContext targetContext = new SLTargetContext();
- protected Protocol protocol;
- protected State currentState = State.INIT;
- protected Transformer transformer = null;
- protected String resultContentType = null;
- protected SLResult slResult = null;
- protected int responseCode = 200;
- protected Map<String, String> responseHeaders = Collections.EMPTY_MAP;
- protected Locale locale = Locale.getDefault();
-
- /**
- *
- * @param id
- * may be null. In this case a new session id will be created.
- * @param cmdInvoker
- * must not be null;
- */
- public HTTPBindingProcessor(String id, SLCommandInvoker cmdInvoker,
- Protocol protocol) {
- super(id);
- if ((protocol != Protocol.HTTP) && (protocol != Protocol.HTTPS)) {
- throw new SLRuntimeException("Protocol not supported: " + protocol);
- }
- if (cmdInvoker == null) {
- throw new NullPointerException("Commandinvoker cannot be set to null");
- }
- commandInvoker = cmdInvoker;
- this.protocol = protocol;
- srcContex.setSourceProtocol(protocol);
- srcContex.setSourceIsDataURL(false);
- }
-
- //----------------------------------------------------------------------------
- // ----------- BEGIN CONVENIENCE METHODS -----------
-
- protected void sendSTALQuit() {
- log.info("Sending QUIT command to STAL");
- List<STALRequest> quit = new ArrayList<STALRequest>(1);
- quit.add(new QuitRequest());
- getSTAL().handleRequest(quit);
- }
-
- protected String getFormParameterAsString(String formParameterName) {
- FormParameter fp = formParameterMap.get(formParameterName);
- return getFormParameterAsString(fp);
- }
-
- protected String getFormParameterAsString(FormParameter fp) {
- if (fp == null) {
- return null;
- }
- try {
- return StreamUtil.asString(fp.getFormParameterValue(), HttpUtil
- .getCharset(fp.getFormParameterContentType(), true));
- } catch (IOException e) {
- return null;
- }
- }
-
- protected String getDataUrl() {
- return getFormParameterAsString(FixedFormParameters.DATAURL);
- }
-
- protected String getStyleSheetUrl() {
- return getFormParameterAsString(FixedFormParameters.STYLESHEETURL);
- }
-
- protected List<FormParameter> getFormParameters(String parameterNamePostfix) {
- List<FormParameter> resultList = new ArrayList<FormParameter>();
- for (Iterator<String> fpi = formParameterMap.keySet().iterator(); fpi
- .hasNext();) {
- String paramName = fpi.next();
- if (paramName.endsWith(parameterNamePostfix)) {
- resultList.add(formParameterMap.get(paramName));
- }
- }
- return resultList;
- }
-
- protected List<FormParameter> getTransferHeaders() {
- return getFormParameters("__");
- }
-
- protected List<FormParameter> getTransferForms() {
- List<FormParameter> resultList = new ArrayList<FormParameter>();
- for (Iterator<String> fpi = formParameterMap.keySet().iterator(); fpi
- .hasNext();) {
- String paramName = fpi.next();
- if ((paramName.endsWith("_")) && (!paramName.endsWith("__"))) {
- resultList.add(formParameterMap.get(paramName));
- }
- }
- return resultList;
- }
-
- protected void closeDataUrlConnection() {
- log.debug("Closing data url input stream");
- if (dataUrlResponse == null) {
- return;
- }
- InputStream is = dataUrlResponse.getStream();
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- log.info("Error closing input stream to dataurl server:" + e);
- }
- }
- }
-
- //----------------------------------------------------------------------------
- // ----------- END CONVENIENCE METHODS -----------
-
- //----------------------------------------------------------------------------
- // -- BEGIN Methods that handle the http binding activities as defined in the
- // activity diagram --
-
- protected void init() {
- log.info("Starting Bindingprocessor in Thread: "
- + Thread.currentThread().getId());
- if (bindingProcessorError != null) {
- log.debug("Detected binding processor error, sending quit command");
- // sendSTALQuit();
- currentState = State.FINISHED;
- } else if (slCommand == null) {
- log.error("SLCommand not set (consumeRequest not called ??)");
- bindingProcessorError = new SLException(2000);
- // sendSTALQuit();
- currentState = State.FINISHED;
- } else {
- currentState = State.PROCESS;
- }
- }
-
- protected void processRequest() {
- log.debug("Entered State: " + State.PROCESS);
- log.debug("Processing command: " + slCommand);
- commandInvoker.setCommand(slCommand);
- responseCode = 200;
- responseHeaders = Collections.EMPTY_MAP;
- try {
- commandInvoker.invoke(srcContex);
- } catch (SLCanceledException e) {
- log.info("Caught exception: " + e);
- bindingProcessorError = e;
- currentState = State.TRANSFORM;
- }
- dataUrlResponse = null;
- if (getDataUrl() != null) {
- log.debug("Data Url set to: " + getDataUrl());
- currentState = State.DATAURL;
- } else {
- log.debug("No data url set");
- currentState = State.TRANSFORM;
- }
- }
-
- protected void handleDataUrl() {
- log.debug("Entered State: " + State.DATAURL);
- try {
- DataUrl dataUrl = new DataUrl(getDataUrl());
- DataUrlConnection conn = dataUrl.openConnection();
-
- // set transfer headers
- for (FormParameter fp : getTransferHeaders()) {
- String paramString = getFormParameterAsString(fp);
- if (paramString == null) {
- log.error("Got empty transfer header, ignoring this");
- } else {
- String[] keyVal = paramString.split(":", 2);
- String key = keyVal[0];
- String val = null;
- if (keyVal.length == 2) {
- val = keyVal[1];
- }
- val = val.trim();
- log.debug("Setting header " + key + " to value " + val);
- conn.setHTTPHeader(key, val);
- }
- }
-
- // set transfer form parameters
- for (FormParameter fp : getTransferForms()) {
- String contentTransferEncoding = null;
- String contentType = fp.getFormParameterContentType();
- String charSet = HttpUtil.getCharset(contentType, false);
- if (charSet != null) {
- contentType = contentType.substring(0, contentType
- .lastIndexOf(HttpUtil.SEPERATOR[0]));
- }
- for (Iterator<String> header = fp.getHeaderNames(); header.hasNext();) {
- if (HttpUtil.CONTENT_TRANSFER_ENCODING
- .equalsIgnoreCase(header.next())) {
- contentTransferEncoding = getFormParameterAsString(fp);
- }
- }
- log.debug("Setting form: " + fp.getFormParameterName()
- + " contentType: " + contentType + " charset: " + charSet
- + " contentTransferEncoding: " + contentTransferEncoding);
- conn.setHTTPFormParameter(fp.getFormParameterName(), fp
- .getFormParameterValue(), contentType, charSet,
- contentTransferEncoding);
- }
-
- // connect
- conn.connect();
- // fetch and set SL result
- targetContext.setTargetIsDataURL(true);
- targetContext.setTargetCertificate(conn.getServerCertificate());
- targetContext.setTargetProtocol(conn.getProtocol());
- SLResult result = commandInvoker.getResult(targetContext);
-
- // transfer result
- conn.transmit(result);
-
- // process Dataurl response
- dataUrlResponse = conn.getResponse();
- log.debug("Received data url response code: "
- + dataUrlResponse.getResponseCode());
- protocol = Protocol.fromString(conn.getProtocol());
-
- switch (dataUrlResponse.getResponseCode()) {
- case 200:
- String contentType = dataUrlResponse.getContentType();
- log.debug("Got dataurl response content type: " + contentType);
- if (contentType != null) {
- if ((contentType.startsWith(HttpUtil.APPLICATION_URL_ENCODED))
- || (contentType.startsWith(HttpUtil.MULTIPART_FOTMDATA))) {
- log.debug("Detected SL Request in dataurl response");
- // process headers and request
- setHTTPHeaders(dataUrlResponse.getResponseHeaders());
- consumeRequestStream(dataUrlResponse.getStream());
- closeDataUrlConnection();
- srcContex.setSourceCertificate(conn.getServerCertificate());
- srcContex.setSourceIsDataURL(true);
- srcContex
- .setSourceProtocol(Protocol.fromString(conn.getProtocol()));
- currentState = State.PROCESS;
- } else if (((contentType.startsWith(HttpUtil.TXT_HTML))
- || (contentType.startsWith(HttpUtil.TXT_PLAIN)) || (contentType
- .startsWith(HttpUtil.TXT_XML)))
- && (dataUrlResponse.isHttpResponseXMLOK())) {
- log.info("Dataurl response matches <ok/> with content type: "
- + contentType);
- currentState = State.TRANSFORM;
-
- } else if ((contentType.startsWith(HttpUtil.TXT_XML))
- && (!dataUrlResponse.isHttpResponseXMLOK())) {
- log
- .debug("Detected text/xml dataurl response with content != <ok/>");
- headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType);
- assignXMLRequest(dataUrlResponse.getStream(), HttpUtil.getCharset(
- contentType, true));
- closeDataUrlConnection();
- srcContex.setSourceCertificate(conn.getServerCertificate());
- srcContex.setSourceIsDataURL(true);
- srcContex
- .setSourceProtocol(Protocol.fromString(conn.getProtocol()));
- currentState = State.PROCESS;
- // just to be complete, actually not used
- srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders()
- .get(HttpUtil.HTTP_HEADER_REFERER));
- } else {
- resultContentType = contentType;
- responseHeaders = dataUrlResponse.getResponseHeaders();
- responseCode = dataUrlResponse.getResponseCode();
- currentState = State.FINISHED;
- }
- } else {
- log.debug("Content type not set in dataurl response");
- closeDataUrlConnection();
- throw new SLBindingException(2007);
- }
-
- break;
- case 307:
- contentType = dataUrlResponse.getContentType();
- if ((contentType != null) && (contentType.startsWith(HttpUtil.TXT_XML))) {
- log.debug("Received dataurl response code 307 with XML content");
- String location = dataUrlResponse.getResponseHeaders().get(
- HttpUtil.HTTP_HEADER_LOCATION);
- if (location == null) {
- log
- .error("Did not get a location header for a 307 data url response");
- throw new SLBindingException(2003);
- }
- // consumeRequestStream(dataUrlResponse.getStream());
- FormParameterStore fp = new FormParameterStore();
- fp.init(location.getBytes(HttpUtil.DEFAULT_CHARSET),
- FixedFormParameters.DATAURL, null, null);
- formParameterMap.put(FixedFormParameters.DATAURL, fp);
- headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType);
- assignXMLRequest(dataUrlResponse.getStream(), HttpUtil.getCharset(
- dataUrlResponse.getContentType(), true));
- closeDataUrlConnection();
- srcContex.setSourceCertificate(conn.getServerCertificate());
- srcContex.setSourceIsDataURL(true);
- srcContex.setSourceProtocol(Protocol.fromString(conn.getProtocol()));
- currentState = State.PROCESS;
- // just to be complete, actually not used
- srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders()
- .get(HttpUtil.HTTP_HEADER_REFERER));
-
- } else {
- log.debug("Received dataurl response code 307 non XML content: "
- + dataUrlResponse.getContentType());
- resultContentType = dataUrlResponse.getContentType();
- currentState = State.FINISHED;
- }
- responseHeaders = dataUrlResponse.getResponseHeaders();
- responseCode = dataUrlResponse.getResponseCode();
- break;
-
- case 301:
- case 302:
- case 303:
- responseHeaders = dataUrlResponse.getResponseHeaders();
- responseCode = dataUrlResponse.getResponseCode();
- resultContentType = dataUrlResponse.getContentType();
- currentState = State.FINISHED;
- break;
-
- default:
- // issue error
- log.info("Unexpected response code from dataurl server: "
- + dataUrlResponse.getResponseCode());
- throw new SLBindingException(2007);
- }
-
- } catch (SLException slx) {
- bindingProcessorError = slx;
- log.error("Error during dataurl communication");
- resultContentType = HttpUtil.TXT_XML;
- currentState = State.TRANSFORM;
- } catch (SSLHandshakeException hx) {
- bindingProcessorError = new SLException(2010);
- log.info("Error during dataurl communication", hx);
- resultContentType = HttpUtil.TXT_XML;
- currentState = State.TRANSFORM;
- } catch (IOException e) {
- bindingProcessorError = new SLBindingException(2001);
- log.error("Error while data url handling", e);
- resultContentType = HttpUtil.TXT_XML;
- currentState = State.TRANSFORM;
- return;
- }
- }
-
- protected void transformResult() {
- log.debug("Entered State: " + State.TRANSFORM);
- if (bindingProcessorError != null) {
- resultContentType = HttpUtil.TXT_XML;
- } else if (dataUrlResponse != null) {
- resultContentType = dataUrlResponse.getContentType();
- } else {
- targetContext.setTargetIsDataURL(false);
- targetContext.setTargetProtocol(protocol.toString());
- try {
- slResult = commandInvoker.getResult(targetContext);
- resultContentType = slResult.getMimeType();
- log
- .debug("Successfully got SLResult from commandinvoker, setting mimetype to: "
- + resultContentType);
- } catch (SLCanceledException e) {
- log.info("Cannot get result from invoker:", e);
- bindingProcessorError = new SLException(6002);
- resultContentType = HttpUtil.TXT_XML;
- }
- }
- transformer = getTransformer(getStyleSheetUrl());
- if (transformer != null) {
- log.debug("Output transformation required");
- resultContentType = transformer.getOutputProperty("media-type");
- log.debug("Got media type from stylesheet: " + resultContentType);
- if (resultContentType == null) {
- log.debug("Setting to default text/xml result conent type");
- resultContentType = "text/xml";
- }
- log.debug("Deferring sytylesheet processing");
- }
- currentState = State.FINISHED;
- }
-
- protected void finished() {
- log.debug("Entered State: " + State.FINISHED);
- if (bindingProcessorError != null) {
- log.debug("Binding processor error, sending quit command");
- resultContentType = HttpUtil.TXT_XML;
- }
- sendSTALQuit();
- log.info("Terminating Bindingprocessor; Thread: "
- + Thread.currentThread().getId());
- }
-
- // -- END Methods that handle the http binding activities as defined in the
- // activity diagram --
- //----------------------------------------------------------------------------
-
- /**
- * Sets the headers of the SL Request. IMPORTANT: make sure to set all headers
- * before invoking {@link #consumeRequestStream(InputStream)}
- *
- * @param aHeaderMap
- * if null all header will be cleared.
- */
- public void setHTTPHeaders(Map<String, String> aHeaderMap) {
- headerMap = new HashMap<String, String>();
- // ensure lowercase keys
- if (aHeaderMap != null) {
- for (String s : aHeaderMap.keySet()) {
- if (s != null) {
- headerMap.put(s.toLowerCase(), aHeaderMap.get(s));
- if (s.equalsIgnoreCase(HttpUtil.HTTP_HEADER_REFERER)) {
- String referer = aHeaderMap.get(s);
- log.debug("Got referer header: " + referer);
- srcContex.setSourceHTTPReferer(referer);
- }
- }
- }
- }
- }
-
- public void setSourceCertificate(X509Certificate aCert) {
- srcContex.setSourceCertificate(aCert);
- }
-
- /**
- * The HTTPBindingProcessor does not handle redirect URLs. It only provides
- * the parameter.
- *
- * @return null if redirect url is not set.
- */
- public String getRedirectURL() {
- return getFormParameterAsString(FixedFormParameters.REDIRECTURL);
- }
-
- public String getFormDataContentType(String aParameterName) {
- FormParameter fp = formParameterMap.get(aParameterName);
- if (fp != null) {
- return fp.getFormParameterContentType();
- }
- return null;
- }
-
- public InputStream getFormData(String aParameterName) {
- FormParameter fp = formParameterMap.get(aParameterName);
- if (fp != null) {
- return fp.getFormParameterValue();
- }
- return null;
- }
-
- protected void assignXMLRequest(InputStream is, String charset)
- throws IOException, SLException {
- Reader r = new InputStreamReader(is, charset);
- StreamSource source = new StreamSource(r);
- SLCommandContext commandCtx = new SLCommandContext();
- commandCtx.setSTAL(getSTAL());
- commandCtx.setURLDereferencerContext(new SimpleFormDataContextImpl(this));
- slCommand = SLCommandFactory.getInstance().createSLCommand(source,
- commandCtx);
- log.debug("Created new command: " + slCommand);
- }
-
- @Override
- public void run() {
- boolean done = false;
- int hopcounter = 0;
- if (bindingProcessorError != null) {
- currentState = State.FINISHED;
- }
- try {
- while (!done) {
- try {
- switch (currentState) {
- case INIT:
- init();
- break;
- case PROCESS:
- processRequest();
- break;
- case DATAURL:
- handleDataUrl();
- if (++hopcounter > MAX_DATAURL_HOPS) {
- log.error("Maximum number of dataurl hops reached");
- bindingProcessorError = new SLBindingException(2000);
- currentState = State.FINISHED;
- }
- break;
- case TRANSFORM:
- transformResult();
- break;
- case FINISHED:
- done = true;
- finished();
- break;
- }
- } catch (RuntimeException rte) {
- throw rte;
- } catch (Exception t) {
- log.error("Caught unexpected exception", t);
- responseCode = 200;
- resultContentType = HttpUtil.TXT_XML;
- responseHeaders = Collections.EMPTY_MAP;
- bindingProcessorError = new SLException(2000);
- currentState = State.FINISHED;
- }
- }
- } catch (Throwable t) {
- log.error("Caught unexpected exception", t);
- responseCode = 200;
- resultContentType = HttpUtil.TXT_XML;
- responseHeaders = Collections.EMPTY_MAP;
- bindingProcessorError = new SLException(2000);
- currentState = State.FINISHED;
- }
- log.debug("Terminated http binding processor");
- }
-
- @Override
- public void consumeRequestStream(InputStream is) {
- try {
- log.debug("Start consuming request stream");
- formParameterMap.clear();
- String cl = headerMap
- .get(HttpUtil.HTTP_HEADER_CONTENT_TYPE.toLowerCase());
- if (cl == null) {
- log.info("No content type set in http header");
- throw new SLBindingException(2006);
- }
- InputDecoder id = InputDecoderFactory.getDecoder(cl, is);
- id.setContentType(cl);
- if (id == null) {
- log.error("Cannot get inputdecoder for is");
- throw new SLException(2006);
- }
- for (Iterator<FormParameter> fpi = id.getFormParameterIterator(); fpi
- .hasNext();) {
- FormParameter fp = fpi.next();
- log.debug("Got request parameter with name: "
- + fp.getFormParameterName());
- if (fp.getFormParameterName().equals(FixedFormParameters.XMLREQUEST)) {
- log.debug("Creating XML Request");
- for (Iterator<String> headerIterator = fp.getHeaderNames(); headerIterator
- .hasNext();) {
- String headerName = headerIterator.next();
- if (HttpUtil.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(headerName)) {
- String transferEncoding = fp.getHeaderValue(headerName);
- log.debug("Got transfer encoding for xmlrequest: "
- + transferEncoding);
- if (XML_REQ_TRANSFER_ENCODING.contains(transferEncoding)) {
- log.debug("Supported transfer encoding: " + transferEncoding);
- } else {
- log
- .error("Transferencoding not supported: "
- + transferEncoding);
- throw new SLBindingException(2005);
- }
- }
- }
- String charset = HttpUtil.getCharset(cl, true);
- assignXMLRequest(fp.getFormParameterValue(), charset);
- } else {
- FormParameterStore fps = new FormParameterStore();
- fps.init(fp);
- if (!fps.isEmpty()) {
- log.debug("Setting from parameter: " + fps.getFormParameterName());
- formParameterMap.put(fps.getFormParameterName(), fps);
- }
- }
- }
- if (slCommand == null) {
- throw new SLBindingException(2004);
- }
- if (is.read() != -1) {
- log.error("Request input stream not completely read");
- // consume rest of stream, should never occur
- throw new SLRuntimeException(
- "request input stream not consumed till end");
- }
- } catch (SLException slx) {
- log.info("Error while consuming input stream " + slx);
- bindingProcessorError = slx;
- } catch (Throwable t) {
- log.info("Error while consuming input stream " + t, t);
- bindingProcessorError = new SLException(2000);
- } finally {
- try {
- while (is.read() != -1)
- ;
- } catch (IOException e) {
- log.error(e);
- }
- }
- }
-
- @Override
- public String getResultContentType() {
- return resultContentType;
- }
-
- protected Transformer getTransformer(String styleSheetURL) {
- if (styleSheetURL == null) {
- log.debug("Stylesheet URL not set");
- return null;
- }
- try {
- URLDereferencerContext urlCtx = new SimpleFormDataContextImpl(this);
- URIResolver resolver = new URIResolverAdapter(URLDereferencer
- .getInstance(), urlCtx);
- TransformerFactory factory = TransformerFactory.newInstance();
- StreamData sd = URLDereferencer.getInstance().dereference(styleSheetURL,
- urlCtx);
- Transformer t = factory.newTransformer(new StreamSource(sd.getStream()));
- t.setURIResolver(resolver);
- return t;
- } catch (Exception ex) {
- log.info("Cannot instantiate transformer", ex);
- bindingProcessorError = new SLException(2002);
- return null;
- }
- }
-
- protected void handleBindingProcessorError(OutputStream os, String encoding,
- Transformer transformer) throws IOException {
- log.debug("Writing error as result");
- ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError);
- try {
- error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)),
- transformer);
- } catch (TransformerException e) {
- log.fatal("Cannot write error result to stream", e);
- }
- }
-
- @Override
- public void writeResultTo(OutputStream os, String encoding)
- throws IOException {
- if (encoding == null) {
- encoding = HttpUtil.DEFAULT_CHARSET;
- }
- if (bindingProcessorError != null) {
- log.debug("Detected error in binding processor, writing error as result");
- handleBindingProcessorError(os, encoding, transformer);
- return;
- } else if (dataUrlResponse != null) {
- log.debug("Writing data url response as result");
- String charEnc = HttpUtil.getCharset(dataUrlResponse.getContentType(),
- true);
- InputStreamReader isr = new InputStreamReader(
- dataUrlResponse.getStream(), charEnc);
- OutputStreamWriter osw = new OutputStreamWriter(os, encoding);
- if (transformer == null) {
- StreamUtil.copyStream(isr, osw);
- } else {
- try {
- transformer.transform(new StreamSource(isr), new StreamResult(osw));
- } catch (TransformerException e) {
- log.fatal("Exception occured during result transformation", e);
- // bindingProcessorError = new SLException(2008);
- // handleBindingProcessorError(os, encoding, null);
- return;
- }
- }
- osw.flush();
- isr.close();
- } else if (slResult == null) {
- // result not yet assigned -> must be a cancel
- bindingProcessorError = new SLException(6001);
- handleBindingProcessorError(os, encoding, transformer);
- return;
- } else {
- log.debug("Getting result from invoker");
- OutputStreamWriter osw = new OutputStreamWriter(os, encoding);
- try {
- slResult.writeTo(new StreamResult(osw), transformer);
- } catch (TransformerException e) {
- log.fatal("Cannot write result to stream", e);
- // bindingProcessorError = new SLException(2008);
- // handleBindingProcessorError(os, encoding, transformer);
- }
- osw.flush();
- }
- }
-
- /**
- * The response code from the dataurl server or 200 if no dataurl server
- * created the result
- *
- * @return
- */
- public int getResponseCode() {
- return responseCode;
- }
-
- /**
- * All headers from the data url server in case of a direct forward from the
- * dataurl server.
- *
- * @return
- */
- public Map<String, String> getResponseHeaders() {
- return responseHeaders;
- }
-
- @Override
- public void setLocale(Locale locale) {
- if (locale == null) {
- throw new NullPointerException("Locale must not be set to null");
- }
- this.locale = locale;
- }
-
+ * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.binding; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.net.URL; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import javax.net.ssl.SSLHandshakeException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLCommandInvoker; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slcommands.SLSourceContext; +import at.gv.egiz.bku.slcommands.SLTargetContext; +import at.gv.egiz.bku.slcommands.impl.ErrorResultImpl; +import at.gv.egiz.bku.slexceptions.SLBindingException; +import at.gv.egiz.bku.slexceptions.SLException; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.utils.StreamUtil; +import at.gv.egiz.bku.utils.binding.Protocol; +import at.gv.egiz.bku.utils.urldereferencer.FormDataURLSupplier; +import at.gv.egiz.bku.utils.urldereferencer.SimpleFormDataContextImpl; +import at.gv.egiz.bku.utils.urldereferencer.StreamData; +import at.gv.egiz.bku.utils.urldereferencer.URIResolverAdapter; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; +import at.gv.egiz.stal.QuitRequest; +import at.gv.egiz.stal.STALRequest; + +/** + * Class performing the HTTP binding as defined by the CCE specification. + * Currently a huge monolithic class. + * + * @TODO refactor + */ +@SuppressWarnings("unchecked") +public class HTTPBindingProcessor extends AbstractBindingProcessor implements + FormDataURLSupplier { + + private static Log log = LogFactory.getLog(HTTPBindingProcessor.class); + + private static enum State { + INIT, PROCESS, DATAURL, TRANSFORM, FINISHED + }; + + public final static Collection<String> XML_REQ_TRANSFER_ENCODING = Arrays + .asList(new String[] { "binary" }); + + /** + * Defines the maximum number of dataurl connects that are allowed within a + * single SL Request processing. + */ + protected static int MAX_DATAURL_HOPS = 10; + + protected static String XML_MIME_TYPE = "text/xml"; + protected static String BINARY_MIME_TYPE = "application/octet-stream"; + + /** + * If null everything is ok and the result is taken from the command invoker. + */ + protected SLException bindingProcessorError; + protected SLCommandInvoker commandInvoker; + protected DataUrlResponse dataUrlResponse; + protected Map<String, String> headerMap = Collections.EMPTY_MAP; + protected SLCommand slCommand; + protected Map<String, FormParameter> formParameterMap = new HashMap<String, FormParameter>(); + protected SLSourceContext srcContex = new SLSourceContext(); + protected SLTargetContext targetContext = new SLTargetContext(); + protected URL srcUrl; + protected State currentState = State.INIT; + protected Transformer transformer = null; + protected String resultContentType = null; + protected SLResult slResult = null; + protected int responseCode = 200; + protected Map<String, String> responseHeaders = Collections.EMPTY_MAP; + protected Locale locale = Locale.getDefault(); + + /** + * + * @param id + * may be null. In this case a new session id will be created. + * @param cmdInvoker + * must not be null; + */ + public HTTPBindingProcessor(String id, SLCommandInvoker cmdInvoker, URL source) { + super(id); + this.srcUrl = source; + Protocol protocol = Protocol.fromString(source.getProtocol()); + if ((protocol != Protocol.HTTP) && (protocol != Protocol.HTTPS)) { + throw new SLRuntimeException("Protocol not supported: " + protocol); + } + if (cmdInvoker == null) { + throw new NullPointerException("Commandinvoker cannot be set to null"); + } + commandInvoker = cmdInvoker; + srcContex.setSourceUrl(source); + srcContex.setSourceIsDataURL(false); + } + + //----------------------------------------------------------------------------
+ // ----------- BEGIN CONVENIENCE METHODS -----------
+ + protected void sendSTALQuit() { + log.info("Sending QUIT command to STAL"); + List<STALRequest> quit = new ArrayList<STALRequest>(1); + quit.add(new QuitRequest()); + getSTAL().handleRequest(quit); + } + + protected String getFormParameterAsString(String formParameterName) { + FormParameter fp = formParameterMap.get(formParameterName); + return getFormParameterAsString(fp); + } + + protected String getFormParameterAsString(FormParameter fp) { + if (fp == null) { + return null; + } + try { + return StreamUtil.asString(fp.getFormParameterValue(), HttpUtil + .getCharset(fp.getFormParameterContentType(), true)); + } catch (IOException e) { + return null; + } + } + + protected String getDataUrl() { + return getFormParameterAsString(FixedFormParameters.DATAURL); + } + + protected String getStyleSheetUrl() { + return getFormParameterAsString(FixedFormParameters.STYLESHEETURL); + } + + protected List<FormParameter> getFormParameters(String parameterNamePostfix) { + List<FormParameter> resultList = new ArrayList<FormParameter>(); + for (Iterator<String> fpi = formParameterMap.keySet().iterator(); fpi + .hasNext();) { + String paramName = fpi.next(); + if (paramName.endsWith(parameterNamePostfix)) { + resultList.add(formParameterMap.get(paramName)); + } + } + return resultList; + } + + protected List<FormParameter> getTransferHeaders() { + return getFormParameters("__"); + } + + protected List<FormParameter> getTransferForms() { + List<FormParameter> resultList = new ArrayList<FormParameter>(); + for (Iterator<String> fpi = formParameterMap.keySet().iterator(); fpi + .hasNext();) { + String paramName = fpi.next(); + if ((paramName.endsWith("_")) && (!paramName.endsWith("__"))) { + resultList.add(formParameterMap.get(paramName)); + } + } + return resultList; + } + + protected void closeDataUrlConnection() { + log.debug("Closing data url input stream"); + if (dataUrlResponse == null) { + return; + } + InputStream is = dataUrlResponse.getStream(); + if (is != null) { + try { + is.close(); + } catch (IOException e) { + log.info("Error closing input stream to dataurl server:" + e); + } + } + } + + //----------------------------------------------------------------------------
+ // ----------- END CONVENIENCE METHODS -----------
+ + //----------------------------------------------------------------------------
+ // -- BEGIN Methods that handle the http binding activities as defined in the
+ // activity diagram --
+ + protected void init() { + log.info("Starting Bindingprocessor in Thread: " + + Thread.currentThread().getId()); + if (bindingProcessorError != null) { + log.debug("Detected binding processor error, sending quit command"); + // sendSTALQuit();
+ currentState = State.FINISHED; + } else if (slCommand == null) { + log.error("SLCommand not set (consumeRequest not called ??)"); + bindingProcessorError = new SLException(2000); + // sendSTALQuit();
+ currentState = State.FINISHED; + } else { + currentState = State.PROCESS; + } + } + + protected void processRequest() { + log.debug("Entered State: " + State.PROCESS); + log.debug("Processing command: " + slCommand); + commandInvoker.setCommand(slCommand); + responseCode = 200; + responseHeaders = Collections.EMPTY_MAP; + try { + commandInvoker.invoke(srcContex); + } catch (SLException e) { + log.info("Caught exception: " + e); + bindingProcessorError = e; + currentState = State.TRANSFORM; + } + dataUrlResponse = null; + if (getDataUrl() != null) { + log.debug("Data Url set to: " + getDataUrl()); + currentState = State.DATAURL; + } else { + log.debug("No data url set"); + currentState = State.TRANSFORM; + } + } + + protected void handleDataUrl() { + log.debug("Entered State: " + State.DATAURL); + try { + DataUrl dataUrl = new DataUrl(getDataUrl()); + DataUrlConnection conn = dataUrl.openConnection(); + + // set transfer headers
+ for (FormParameter fp : getTransferHeaders()) { + String paramString = getFormParameterAsString(fp); + if (paramString == null) { + log.error("Got empty transfer header, ignoring this"); + } else { + String[] keyVal = paramString.split(":", 2); + String key = keyVal[0]; + String val = null; + if (keyVal.length == 2) { + val = keyVal[1]; + } + val = val.trim(); + log.debug("Setting header " + key + " to value " + val); + conn.setHTTPHeader(key, val); + } + } + + // set transfer form parameters
+ for (FormParameter fp : getTransferForms()) { + String contentTransferEncoding = null; + String contentType = fp.getFormParameterContentType(); + String charSet = HttpUtil.getCharset(contentType, false); + if (charSet != null) { + contentType = contentType.substring(0, contentType + .lastIndexOf(HttpUtil.SEPERATOR[0])); + } + for (Iterator<String> header = fp.getHeaderNames(); header.hasNext();) { + if (HttpUtil.CONTENT_TRANSFER_ENCODING + .equalsIgnoreCase(header.next())) { + contentTransferEncoding = getFormParameterAsString(fp); + } + } + log.debug("Setting form: " + fp.getFormParameterName() + + " contentType: " + contentType + " charset: " + charSet + + " contentTransferEncoding: " + contentTransferEncoding); + conn.setHTTPFormParameter(fp.getFormParameterName(), fp + .getFormParameterValue(), contentType, charSet, + contentTransferEncoding); + } + + // connect
+ conn.connect(); + // fetch and set SL result
+ targetContext.setTargetIsDataURL(true); + targetContext.setTargetCertificate(conn.getServerCertificate()); + targetContext.setTargetUrl(conn.getUrl()); + SLResult result = commandInvoker.getResult(targetContext); + + // transfer result
+ conn.transmit(result); + + // process Dataurl response
+ dataUrlResponse = conn.getResponse(); + log.debug("Received data url response code: " + + dataUrlResponse.getResponseCode()); + + switch (dataUrlResponse.getResponseCode()) { + case 200: + String contentType = dataUrlResponse.getContentType(); + log.debug("Got dataurl response content type: " + contentType); + if (contentType != null) { + if ((contentType.startsWith(HttpUtil.APPLICATION_URL_ENCODED)) + || (contentType.startsWith(HttpUtil.MULTIPART_FOTMDATA))) { + log.debug("Detected SL Request in dataurl response"); + // process headers and request
+ setHTTPHeaders(dataUrlResponse.getResponseHeaders()); + consumeRequestStream(dataUrlResponse.getStream()); + closeDataUrlConnection(); + srcContex.setSourceCertificate(conn.getServerCertificate()); + srcContex.setSourceIsDataURL(true); + srcContex.setSourceUrl(conn.getUrl()); + currentState = State.PROCESS; + } else if (((contentType.startsWith(HttpUtil.TXT_HTML)) + || (contentType.startsWith(HttpUtil.TXT_PLAIN)) || (contentType + .startsWith(HttpUtil.TXT_XML))) + && (dataUrlResponse.isHttpResponseXMLOK())) { + log.info("Dataurl response matches <ok/> with content type: " + + contentType); + currentState = State.TRANSFORM; + + } else if ((contentType.startsWith(HttpUtil.TXT_XML)) + && (!dataUrlResponse.isHttpResponseXMLOK())) { + log + .debug("Detected text/xml dataurl response with content != <ok/>"); + headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType); + assignXMLRequest(dataUrlResponse.getStream(), HttpUtil.getCharset( + contentType, true)); + closeDataUrlConnection(); + srcContex.setSourceCertificate(conn.getServerCertificate()); + srcContex.setSourceIsDataURL(true); + srcContex.setSourceUrl(conn.getUrl()); + currentState = State.PROCESS; + // just to be complete, actually not used
+ srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders() + .get(HttpUtil.HTTP_HEADER_REFERER)); + } else { + resultContentType = contentType; + responseHeaders = dataUrlResponse.getResponseHeaders(); + responseCode = dataUrlResponse.getResponseCode(); + currentState = State.FINISHED; + } + } else { + log.debug("Content type not set in dataurl response"); + closeDataUrlConnection(); + throw new SLBindingException(2007); + } + + break; + case 307: + contentType = dataUrlResponse.getContentType(); + if ((contentType != null) && (contentType.startsWith(HttpUtil.TXT_XML))) { + log.debug("Received dataurl response code 307 with XML content"); + String location = dataUrlResponse.getResponseHeaders().get( + HttpUtil.HTTP_HEADER_LOCATION); + if (location == null) { + log + .error("Did not get a location header for a 307 data url response"); + throw new SLBindingException(2003); + } + // consumeRequestStream(dataUrlResponse.getStream());
+ FormParameterStore fp = new FormParameterStore(); + fp.init(location.getBytes(HttpUtil.DEFAULT_CHARSET), + FixedFormParameters.DATAURL, null, null); + formParameterMap.put(FixedFormParameters.DATAURL, fp); + headerMap.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, contentType); + assignXMLRequest(dataUrlResponse.getStream(), HttpUtil.getCharset( + dataUrlResponse.getContentType(), true)); + closeDataUrlConnection(); + srcContex.setSourceCertificate(conn.getServerCertificate()); + srcContex.setSourceIsDataURL(true); + srcContex.setSourceUrl(conn.getUrl()); + currentState = State.PROCESS; + // just to be complete, actually not used
+ srcContex.setSourceHTTPReferer(dataUrlResponse.getResponseHeaders() + .get(HttpUtil.HTTP_HEADER_REFERER)); + + } else { + log.debug("Received dataurl response code 307 non XML content: " + + dataUrlResponse.getContentType()); + resultContentType = dataUrlResponse.getContentType(); + currentState = State.FINISHED; + } + responseHeaders = dataUrlResponse.getResponseHeaders(); + responseCode = dataUrlResponse.getResponseCode(); + break; + + case 301: + case 302: + case 303: + responseHeaders = dataUrlResponse.getResponseHeaders(); + responseCode = dataUrlResponse.getResponseCode(); + resultContentType = dataUrlResponse.getContentType(); + currentState = State.FINISHED; + break; + + default: + // issue error
+ log.info("Unexpected response code from dataurl server: " + + dataUrlResponse.getResponseCode()); + throw new SLBindingException(2007); + } + + } catch (SLException slx) { + bindingProcessorError = slx; + log.error("Error during dataurl communication"); + resultContentType = HttpUtil.TXT_XML; + currentState = State.TRANSFORM; + } catch (SSLHandshakeException hx) { + bindingProcessorError = new SLException(2010); + log.info("Error during dataurl communication", hx); + resultContentType = HttpUtil.TXT_XML; + currentState = State.TRANSFORM; + } catch (IOException e) { + bindingProcessorError = new SLBindingException(2001); + log.error("Error while data url handling", e); + resultContentType = HttpUtil.TXT_XML; + currentState = State.TRANSFORM; + return; + } + } + + protected void transformResult() { + log.debug("Entered State: " + State.TRANSFORM); + if (bindingProcessorError != null) { + resultContentType = HttpUtil.TXT_XML; + } else if (dataUrlResponse != null) { + resultContentType = dataUrlResponse.getContentType(); + } else { + targetContext.setTargetIsDataURL(false); + targetContext.setTargetUrl(srcUrl); + try { + slResult = commandInvoker.getResult(targetContext); + resultContentType = slResult.getMimeType(); + log + .debug("Successfully got SLResult from commandinvoker, setting mimetype to: " + + resultContentType); + } catch (SLException e) { + log.info("Cannot get result from invoker:", e); + bindingProcessorError = new SLException(6002); + resultContentType = HttpUtil.TXT_XML; + } + } + transformer = getTransformer(getStyleSheetUrl()); + if (transformer != null) { + log.debug("Output transformation required"); + resultContentType = transformer.getOutputProperty("media-type"); + log.debug("Got media type from stylesheet: " + resultContentType); + if (resultContentType == null) { + log.debug("Setting to default text/xml result conent type"); + resultContentType = "text/xml"; + } + log.debug("Deferring sytylesheet processing"); + } + currentState = State.FINISHED; + } + + protected void finished() { + log.debug("Entered State: " + State.FINISHED); + if (bindingProcessorError != null) { + log.debug("Binding processor error, sending quit command"); + resultContentType = HttpUtil.TXT_XML; + } + sendSTALQuit(); + log.info("Terminating Bindingprocessor; Thread: " + + Thread.currentThread().getId()); + } + + // -- END Methods that handle the http binding activities as defined in the
+ // activity diagram --
+ //----------------------------------------------------------------------------
+ + /** + * Sets the headers of the SL Request. IMPORTANT: make sure to set all headers + * before invoking {@link #consumeRequestStream(InputStream)} + * + * @param aHeaderMap + * if null all header will be cleared. + */ + public void setHTTPHeaders(Map<String, String> aHeaderMap) { + headerMap = new HashMap<String, String>(); + // ensure lowercase keys
+ if (aHeaderMap != null) { + for (String s : aHeaderMap.keySet()) { + if (s != null) { + headerMap.put(s.toLowerCase(), aHeaderMap.get(s)); + if (s.equalsIgnoreCase(HttpUtil.HTTP_HEADER_REFERER)) { + String referer = aHeaderMap.get(s); + log.debug("Got referer header: " + referer); + srcContex.setSourceHTTPReferer(referer); + } + } + } + } + } + + public void setSourceCertificate(X509Certificate aCert) { + srcContex.setSourceCertificate(aCert); + } + + /** + * The HTTPBindingProcessor does not handle redirect URLs. It only provides + * the parameter. + * + * @return null if redirect url is not set. + */ + public String getRedirectURL() { + return getFormParameterAsString(FixedFormParameters.REDIRECTURL); + } + + public String getFormDataContentType(String aParameterName) { + FormParameter fp = formParameterMap.get(aParameterName); + if (fp != null) { + return fp.getFormParameterContentType(); + } + return null; + } + + public InputStream getFormData(String aParameterName) { + FormParameter fp = formParameterMap.get(aParameterName); + if (fp != null) { + return fp.getFormParameterValue(); + } + return null; + } + + protected void assignXMLRequest(InputStream is, String charset) + throws IOException, SLException { + Reader r = new InputStreamReader(is, charset); + StreamSource source = new StreamSource(r); + SLCommandContext commandCtx = new SLCommandContext(); + commandCtx.setSTAL(getSTAL()); + commandCtx.setURLDereferencerContext(new SimpleFormDataContextImpl(this)); + slCommand = SLCommandFactory.getInstance().createSLCommand(source, + commandCtx); + log.debug("Created new command: " + slCommand); + } + + @Override + public void run() { + boolean done = false; + int hopcounter = 0; + if (bindingProcessorError != null) { + currentState = State.FINISHED; + } + try { + while (!done) { + try { + switch (currentState) { + case INIT: + init(); + break; + case PROCESS: + processRequest(); + break; + case DATAURL: + handleDataUrl(); + if (++hopcounter > MAX_DATAURL_HOPS) { + log.error("Maximum number of dataurl hops reached"); + bindingProcessorError = new SLBindingException(2000); + currentState = State.FINISHED; + } + break; + case TRANSFORM: + transformResult(); + break; + case FINISHED: + done = true; + finished(); + break; + } + } catch (RuntimeException rte) { + throw rte; + } catch (Exception t) { + log.error("Caught unexpected exception", t); + responseCode = 200; + resultContentType = HttpUtil.TXT_XML; + responseHeaders = Collections.EMPTY_MAP; + bindingProcessorError = new SLException(2000); + currentState = State.FINISHED; + } + } + } catch (Throwable t) { + log.error("Caught unexpected exception", t); + responseCode = 200; + resultContentType = HttpUtil.TXT_XML; + responseHeaders = Collections.EMPTY_MAP; + bindingProcessorError = new SLException(2000); + currentState = State.FINISHED; + } + log.debug("Terminated http binding processor"); + } + + @Override + public void consumeRequestStream(InputStream is) { + try { + log.debug("Start consuming request stream"); + formParameterMap.clear(); + String cl = headerMap + .get(HttpUtil.HTTP_HEADER_CONTENT_TYPE.toLowerCase()); + if (cl == null) { + log.info("No content type set in http header"); + throw new SLBindingException(2006); + } + InputDecoder id = InputDecoderFactory.getDecoder(cl, is); + id.setContentType(cl); + if (id == null) { + log.error("Cannot get inputdecoder for is"); + throw new SLException(2006); + } + for (Iterator<FormParameter> fpi = id.getFormParameterIterator(); fpi + .hasNext();) { + FormParameter fp = fpi.next(); + log.debug("Got request parameter with name: " + + fp.getFormParameterName()); + if (fp.getFormParameterName().equals(FixedFormParameters.XMLREQUEST)) { + log.debug("Creating XML Request"); + for (Iterator<String> headerIterator = fp.getHeaderNames(); headerIterator + .hasNext();) { + String headerName = headerIterator.next(); + if (HttpUtil.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(headerName)) { + String transferEncoding = fp.getHeaderValue(headerName); + log.debug("Got transfer encoding for xmlrequest: " + + transferEncoding); + if (XML_REQ_TRANSFER_ENCODING.contains(transferEncoding)) { + log.debug("Supported transfer encoding: " + transferEncoding); + } else { + log + .error("Transferencoding not supported: " + + transferEncoding); + throw new SLBindingException(2005); + } + } + } + String charset = HttpUtil.getCharset(cl, true); + assignXMLRequest(fp.getFormParameterValue(), charset); + } else { + FormParameterStore fps = new FormParameterStore(); + fps.init(fp); + if (!fps.isEmpty()) { + log.debug("Setting from parameter: " + fps.getFormParameterName()); + formParameterMap.put(fps.getFormParameterName(), fps); + } + } + } + if (slCommand == null) { + throw new SLBindingException(2004); + } + if (is.read() != -1) { + log.error("Request input stream not completely read"); + // consume rest of stream, should never occur
+ throw new SLRuntimeException( + "request input stream not consumed till end"); + } + } catch (SLException slx) { + log.info("Error while consuming input stream " + slx); + bindingProcessorError = slx; + } catch (Throwable t) { + log.info("Error while consuming input stream " + t, t); + bindingProcessorError = new SLException(2000); + } finally { + try { + while (is.read() != -1) + ; + } catch (IOException e) { + log.error(e); + } + } + } + + @Override + public String getResultContentType() { + return resultContentType; + } + + protected Transformer getTransformer(String styleSheetURL) { + if (styleSheetURL == null) { + log.debug("Stylesheet URL not set"); + return null; + } + try { + URLDereferencerContext urlCtx = new SimpleFormDataContextImpl(this); + URIResolver resolver = new URIResolverAdapter(URLDereferencer + .getInstance(), urlCtx); + TransformerFactory factory = TransformerFactory.newInstance(); + StreamData sd = URLDereferencer.getInstance().dereference(styleSheetURL, + urlCtx); + Transformer t = factory.newTransformer(new StreamSource(sd.getStream())); + t.setURIResolver(resolver); + return t; + } catch (Exception ex) { + log.info("Cannot instantiate transformer", ex); + bindingProcessorError = new SLException(2002); + return null; + } + } + + protected void handleBindingProcessorError(OutputStream os, String encoding, + Transformer transformer) throws IOException { + log.debug("Writing error as result"); + ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError); + try { + error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)), + transformer); + } catch (TransformerException e) { + log.fatal("Cannot write error result to stream", e); + } + } + + @Override + public void writeResultTo(OutputStream os, String encoding) + throws IOException { + if (encoding == null) { + encoding = HttpUtil.DEFAULT_CHARSET; + } + if (bindingProcessorError != null) { + log.debug("Detected error in binding processor, writing error as result"); + handleBindingProcessorError(os, encoding, transformer); + return; + } else if (dataUrlResponse != null) { + log.debug("Writing data url response as result"); + String charEnc = HttpUtil.getCharset(dataUrlResponse.getContentType(), + true); + InputStreamReader isr = new InputStreamReader( + dataUrlResponse.getStream(), charEnc); + OutputStreamWriter osw = new OutputStreamWriter(os, encoding); + if (transformer == null) { + StreamUtil.copyStream(isr, osw); + } else { + try { + transformer.transform(new StreamSource(isr), new StreamResult(osw)); + } catch (TransformerException e) { + log.fatal("Exception occured during result transformation", e); + // bindingProcessorError = new SLException(2008);
+ // handleBindingProcessorError(os, encoding, null);
+ return; + } + } + osw.flush(); + isr.close(); + } else if (slResult == null) { + // result not yet assigned -> must be a cancel
+ bindingProcessorError = new SLException(6001); + handleBindingProcessorError(os, encoding, transformer); + return; + } else { + log.debug("Getting result from invoker"); + OutputStreamWriter osw = new OutputStreamWriter(os, encoding); + try { + slResult.writeTo(new StreamResult(osw), transformer); + } catch (TransformerException e) { + log.fatal("Cannot write result to stream", e); + // bindingProcessorError = new SLException(2008);
+ // handleBindingProcessorError(os, encoding, transformer);
+ } + osw.flush(); + } + } + + /** + * The response code from the dataurl server or 200 if no dataurl server + * created the result + * + * @return + */ + public int getResponseCode() { + return responseCode; + } + + /** + * All headers from the data url server in case of a direct forward from the + * dataurl server. + * + * @return + */ + public Map<String, String> getResponseHeaders() { + return responseHeaders; + } + + @Override + public void setLocale(Locale locale) { + if (locale == null) { + throw new NullPointerException("Locale must not be set to null"); + } + this.locale = locale; + } + }
\ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/SLCommandInvokerImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/SLCommandInvokerImpl.java index ef2affd1..a23d96e8 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/SLCommandInvokerImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/SLCommandInvokerImpl.java @@ -1,66 +1,95 @@ /* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.bku.binding;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import at.gv.egiz.bku.slcommands.SLCommand;
-import at.gv.egiz.bku.slcommands.SLCommandInvoker;
-import at.gv.egiz.bku.slcommands.SLResult;
-import at.gv.egiz.bku.slcommands.SLSourceContext;
-import at.gv.egiz.bku.slcommands.SLTargetContext;
-
-/**
- * This class implements the entry point for the CCEs security management.
- *
- * TODO the secuirty management is currently not implemented.
- */
-public class SLCommandInvokerImpl implements SLCommandInvoker {
-
- private static Log log = LogFactory.getLog(SLCommandInvokerImpl.class);
-
- protected SLCommand command;
- protected SLResult result;
-
- /**
- * Invokes a sl command.
- */
- public void invoke(SLSourceContext aContext) {
- // FIXXME add security policy here.
- log.warn("Security policy not implemented yet, invoking command: "+command);
- result = command.execute();
- }
-
- public SLResult getResult(SLTargetContext aContext) {
- // FIXXME
- log.warn("Security policy not implemented yet, getting result of command: "+command);
- return result;
- }
-
- public void setCommand(SLCommand aCmd) {
- command = aCmd;
- }
-
- @Override
- public SLCommandInvoker newInstance() {
- SLCommandInvokerImpl cmdInv = new SLCommandInvokerImpl();
- return cmdInv;
- }
-
-
+ * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.binding; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.accesscontroller.SecurityManagerFacade; +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandInvoker; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slcommands.SLSourceContext; +import at.gv.egiz.bku.slcommands.SLTargetContext; +import at.gv.egiz.bku.slexceptions.SLException; + +/** + * This class implements the entry point for the CCEs security management. + * + */ +public class SLCommandInvokerImpl implements SLCommandInvoker { + + private static Log log = LogFactory.getLog(SLCommandInvokerImpl.class); + + protected SLCommand command; + protected SLResult result; + protected SecurityManagerFacade securityManager; + + /** + * Invokes a sl command. + * + * @throws SLException + */ + public void invoke(SLSourceContext aContext) throws SLException { + if (securityManager == null) { + log.warn("Security policy not implemented yet, invoking command: " + + command); + result = command.execute(); + } else { + if (securityManager.mayInvokeCommand(command, aContext)) { + result = command.execute(); + } else { + throw new SLException(6002); + } + } + } + + public SLResult getResult(SLTargetContext aContext) throws SLException { + if (securityManager == null) { + log + .warn("Security policy not implemented yet, getting result of command: " + + command); + return result; + } else { + if (securityManager.maySendResult(command, aContext)) { + return result; + } else { + throw new SLException(6002); + } + } + } + + public void setCommand(SLCommand aCmd) { + command = aCmd; + } + + @Override + public SLCommandInvoker newInstance() { + SLCommandInvokerImpl cmdInv = new SLCommandInvokerImpl(); + cmdInv.setSecurityManager(securityManager); + return cmdInv; + } + + public SecurityManagerFacade getSecurityManager() { + return securityManager; + } + + public void setSecurityManager(SecurityManagerFacade securityManager) { + this.securityManager = securityManager; + } + }
\ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxReadCommand.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxReadCommand.java index 77529a36..73fddf1f 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxReadCommand.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxReadCommand.java @@ -16,5 +16,13 @@ */ package at.gv.egiz.bku.slcommands;
-public interface InfoboxReadCommand extends SLCommand {
+public interface InfoboxReadCommand extends SLCommand { + public String getInfoboxIdentifier(); + + /** + * Convenience method to get the domain identifier if the infobox + * referes to a Identitylink. + * @return the domain id or null if the Infobox is not of type Identitylink or no domain parameter was specified + */ + public String getIdentityLinkDomainId();
}
\ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandInvoker.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandInvoker.java index 30c6b68f..c28288c9 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandInvoker.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandInvoker.java @@ -16,7 +16,8 @@ */ package at.gv.egiz.bku.slcommands;
-import at.gv.egiz.bku.slexceptions.SLCanceledException;
+import at.gv.egiz.bku.slexceptions.SLCanceledException; +import at.gv.egiz.bku.slexceptions.SLException; public interface SLCommandInvoker {
@@ -25,7 +26,7 @@ public interface SLCommandInvoker { * @param aContext
* @throws SLCanceledException if the security management prevents execution of this command
*/
- public void invoke(SLSourceContext aContext) throws SLCanceledException;
+ public void invoke(SLSourceContext aContext) throws SLException;
/**
*
@@ -33,7 +34,7 @@ public interface SLCommandInvoker { * @return
* @throws SLCanceledException if the security management prevents execution of this command
*/
- public SLResult getResult(SLTargetContext aContext) throws SLCanceledException;
+ public SLResult getResult(SLTargetContext aContext) throws SLException;
public void setCommand(at.gv.egiz.bku.slcommands.SLCommand aCmd);
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLSourceContext.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLSourceContext.java index ded55b2a..f25a0ea4 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLSourceContext.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLSourceContext.java @@ -16,6 +16,7 @@ */ package at.gv.egiz.bku.slcommands;
+import java.net.URL; import java.security.cert.X509Certificate;
import at.gv.egiz.bku.utils.binding.Protocol;
@@ -23,17 +24,17 @@ import at.gv.egiz.bku.utils.binding.Protocol; public class SLSourceContext {
- private Protocol sourceProtocol;
+ private URL sourceUrl;
private boolean sourceIsDataURL;
private X509Certificate sourceCertificate;
private String sourceHTTPReferer;
- public Protocol getSourceProtocol() {
- return sourceProtocol;
+ public URL getSourceUrl() {
+ return sourceUrl;
}
- public void setSourceProtocol(Protocol sourceProtocol) {
- this.sourceProtocol = sourceProtocol;
+ public void setSourceUrl(URL sourceProtocol) {
+ this.sourceUrl = sourceProtocol;
}
public boolean isSourceIsDataURL() {
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLTargetContext.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLTargetContext.java index cf800406..f9df3ced 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLTargetContext.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLTargetContext.java @@ -16,19 +16,20 @@ */ package at.gv.egiz.bku.slcommands;
-import java.security.cert.X509Certificate;
+import java.net.URL; +import java.security.cert.X509Certificate; public class SLTargetContext {
- private String targetProtocol;
+ private URL targetUrl;
private boolean targetIsDataURL;
private X509Certificate targetCertificate;
- public String getTargetProtocol() {
- return targetProtocol;
+ public URL getTargetUrl() {
+ return targetUrl;
}
- public void setTargetProtocol(String targetProtocol) {
- this.targetProtocol = targetProtocol;
+ public void setTargetUrl(URL targetUrl) {
+ this.targetUrl = targetUrl;
}
public boolean isTargetIsDataURL() {
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java index 93131cf4..b6745e1f 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java @@ -405,5 +405,10 @@ public class InfoboxReadCommandImpl extends SLCommandImpl<InfoboxReadRequestType return result;
- }
+ } + + @Override + public String getIdentityLinkDomainId() { + return identityLinkDomainIdentifier; + }
}
|