[Yanel-dev] [HEADS UP] ResourceManager and
ResourceConfigurationMap class may die soon;
resource-types' URL matching (e.g. on request parameters)
Guillaume Déflache
guillaume.deflache at wyona.com
Fri Dec 4 22:19:58 CET 2009
Some progress report as Simon showed some renewed interest in this =
lately! ;)
Cf. =
http://lists.wyona.org/pipermail/yanel-development/2009-December/004192.html
Guillaume D=E9flache a =E9crit :
> Hi!
> =
> As discussed with Simon some time ago (unfortunately no one took notes =
> :(...) we would like to be able to choose the resource-type to use for a =
> request by matching the value or presence of HTTP request parameters =
> (ATM one can only match on the request URI).
> =
> As far as Michi and I can remember, we then considered at least 2 options:
> =
> =
> *Option 1*: allow a syntax similar to "**?my-param-name=3D*" in map.rc-ma=
p =
> files in "matcher" elements for the "pattern" attribute.
> =
> Some issues:
> - most probably we want to ignore the order of the request parameters as =
> they are written in the pattern, as anyway AFAIK the servlet spec does =
> not define it
> - should we also match parameters passed through POST, albeit the syntax =
> of the pattern could make use think it would only work for GET: Mich and =
> I would say we should, and the servlet API makes that choice easier
> - what would "**" mean in the query string part? I'd suggest it should =
> either throw some parsing exception, or match any other parameter that =
> could also be present (would allow use to distinguish between the two =
> cases "only these parameters" and "these parameters and some others we =
> do not care about", although that might be somewhat counter-intuitive)
Any opinion about these issues, esp. Simon? On the 3rd I'd personally go =
for the "match any other parameter" solution.
> *Option 2*: allow full customization of the matching policy by =
> introducing a new Java interface for it.
> (1st please note that #1 can readily be implemented independently of #2 =
> but of course we'd rather put new functionality in the new places if =
> possible.)
I did some (unfinished) work on this, please review the attachment.
There is still some unfinished stuff, mainly around the TODO and XXX =
markers, please ask me as they probably won't make any sense to anyone =
else than me.
> This interface would be almost identical to the =
> org.wyona.yanel.core.ResourceManager class's (minus the deprecated =
> parts) and especially provide getResource(Environment environment, Realm =
> realm, String path, ResourceConfiguration rc): having access to the =
> environment should allow any future kind of matching imaginable (see =
> Apache Cocoon for wild ideas! ;) ).
> I'd suggest to use a better name (*Manager is rather uninspiring): =
> org.wyona.yanel.core.api.ResourceTypeMatcherV1 maybe?
The current interface has the same name but provide =
getResourceConfiguration(Environment environment, Realm realm, String =
path) instead: indeed IMHO what we need to be configurable is only the =
RC object selector, not a Resource selector (all Resource objects may be =
instantiated in the same way for now, better not expose classloading =
guts before we get our runtime-modularity story right).
> Then as 1st step we would have to reimplement =
> org.wyona.yanel.core.ResourceManager using the new interface and still =
> use it as the default for backward-compatibility.
> Then we would have to allow configuration of the concrete matching =
> class. ATM this is done in the Yanel class, but Michi would like it to =
That's more or less what is done in the patch.
> be configurable per realm, and thanks to the way it's currently =
> encapsulated there this is also possible only with some more =
> deprecations (namely Yanel.getResourceManager).
I did not tackle that yet.
We may not need to change Yanel#getResourceManager or even =
ResourceManager to do this, as ResourceManager#getResource has already =
the realm as parameter.
Maybe the ResourceManager should/could become a registry of =
ResourceTypeMatcherV1 objects for all realms, adn then we would only =
need =
ResourceManager#setResourceTypeMatcherForRealm(ResourceTypeMatcherV1 =
matcher, Realm realm)??? But then maybe we would only need =
ResourceTypeMatcherV1#getResourceConfiguration(Environment environment, =
String path) without the realm parameter?
Or maybe we should wait and do that in ResourceTypeMatcherV2?
> I'd also suggest we hide functionality actually in =
> ResourceConfigurationMap in the concrete matcher implementations: the =
> class only has static methods and needlessly expose mechanics. It also =
This still can/should be done once dust has settled on all things above.
> needs changing because Michi would like to be able to parametrize the =
> "map.rc-map" file name.
This will probably be left as an exercise to casual contributors! :P
Cheers,
Guillaume
-------------- next part --------------
Index: conf/spring-yanel-config.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- conf/spring-yanel-config.xml (Revision 45854)
+++ conf/spring-yanel-config.xml (Arbeitskopie)
@@ -23,6 +23,8 @@
-->
<bean id=3D"PolicyManagerFactory" class=3D"org.wyona.security.impl.Polic=
yManagerFactoryImpl"/>
<bean id=3D"IdentityManagerFactory" class=3D"org.wyona.security.impl.Ide=
ntityManagerFactoryImpl"/>
+ <bean id=3D"ResourceTypeMatcherV1" class=3D"org.wyona.yanel.impl.Resourc=
eTypeDefaultMatcher"/>
+ <!--bean id=3D"ResourceTypeMatcherV1" class=3D"org.wyona.yanel.core.Reso=
urceManager"/-->
=
<bean id=3D"repo-navigation" class=3D"org.wyona.yanel.impl.navigation.Si=
tetreeResConfigAndDataRepoImpl"/>
<!--
Index: src/core/java/org/wyona/yanel/core/Yanel.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/core/java/org/wyona/yanel/core/Yanel.java (Revision 45854)
+++ src/core/java/org/wyona/yanel/core/Yanel.java (Arbeitskopie)
@@ -16,6 +16,7 @@
=
package org.wyona.yanel.core;
=
+import org.wyona.yanel.core.api.ResourceTypeMatcherV1;
import org.wyona.yanel.core.map.Map;
import org.wyona.yanel.core.map.Realm;
import org.wyona.yanel.core.map.RealmManager;
@@ -79,6 +80,13 @@
rtr =3D new ResourceTypeRegistry();
resourceManager =3D new ResourceManager();
resourceManager.setResourceTypeRegistry(rtr);
+ ResourceTypeMatcherV1 rtm =3D getServiceInstance(ResourceTypeMatche=
rV1.class);
+ if (rtm =3D=3D null) {
+ log.info("No custom resource type matcher service found, using =
default one.");
+ } else {
+ resourceManager.setResourceTypeMatcher(rtm);
+ log.info("Found "+rtm.getClass().getCanonicalName()+" resource =
type matcher service, using that!");
+ }
=
/* TODO: Why is this commented?
PolicyManager pm =3D (PolicyManager) yanel.getBeanFactory().getBean=
("policyManager");
@@ -133,7 +141,13 @@
log.warn("DEPRECATED");
return applicationContext;
}
- =
+
+ @SuppressWarnings("unchecked")
+ private <O extends Object> O getServiceInstance(Class<O> clazz) throws=
Exception {
+ O service =3D (O) yanel.getBeanFactory().getBean(clazz.getSimpleNa=
me());
+ return service;
+ }
+
/**
* Get repository factory
* @param id Repository factory bean ID
Index: src/core/java/org/wyona/yanel/core/ResourceManager.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/core/java/org/wyona/yanel/core/ResourceManager.java (Revision 45854)
+++ src/core/java/org/wyona/yanel/core/ResourceManager.java (Arbeitskopie)
@@ -22,6 +22,7 @@
import javax.servlet.http.HttpServletRequest;
=
import org.apache.log4j.Logger;
+import org.wyona.yanel.core.api.ResourceTypeMatcherV1;
import org.wyona.yanel.core.map.Realm;
import org.wyona.yanel.core.util.HttpServletRequestHelper;
import org.wyona.yanel.core.util.PathUtil;
@@ -32,16 +33,22 @@
* given some initial resource-type-related configuration
* and some context for the request.
*/
-public class ResourceManager {
+public class ResourceManager implements ResourceTypeMatcherV1 {
=
private static Logger log =3D Logger.getLogger(ResourceManager.class);
=
protected ResourceTypeRegistry rtRegistry;
=
+ private ResourceTypeMatcherV1 RTmatcher =3D this;
+
public void setResourceTypeRegistry(ResourceTypeRegistry registry) {
this.rtRegistry =3D registry;
}
=
+ public void setResourceTypeMatcher(ResourceTypeMatcherV1 matcher) { //=
XXX maybe use constructor injection
+ this.RTmatcher =3D matcher;
+ }
+
/**
* Creates a new resource object in the given realm with the given pat=
h and the given type.
* @deprecated Use {@link #getResource(Environment, Realm, String, Res=
ourceConfiguration)} instead,
@@ -110,10 +117,17 @@
* @param path Path relative to realm (e.g. yanel.getMap().getPath(rea=
lm, request.getServletPath()))
*/
public Resource getResource(Environment environment, Realm realm, Stri=
ng path) throws Exception {
+ ResourceConfiguration rc =3D RTmatcher.getResourceConfiguration(en=
vironment, realm, path);
+ Resource resource =3D getResource(environment, realm, path, rc);
+ return resource;
+ }
+
+ //XXX won't fallback if class not found
+ public ResourceConfiguration getResourceConfiguration(Environment envi=
ronment, Realm realm, String path) throws Exception {
// Check first if a one-to-one mapping exists
if (realm.getRTIRepository().existsNode(PathUtil.getRCPath(path)))=
{
ResourceConfiguration rc =3D new ResourceConfiguration(realm.g=
etRTIRepository().getNode(PathUtil.getRCPath(path)));
- if (rc !=3D null) return getResource(environment, realm, path,=
rc);
+ return rc; //TODO check null check!
}
=
// Fallback to deprecated RTI (one-to-one mapping)
@@ -121,7 +135,7 @@
log.warn("DEPRECATED: RTI should be replaced by ResourceConfig=
uration: " + realm + ", " + path);
ResourceTypeIdentifier rti =3D getResourceTypeIdentifier(realm=
, path);
ResourceConfiguration rc =3D new RTIbasedResourceConfiguration=
(rti);
- return getResource(environment, realm, path, rc);
+ return rc; //TODO check null check!
} =
=
// Check on resource configuration map
@@ -129,22 +143,23 @@
if (rcPath !=3D null) {
if (realm.getRTIRepository().existsNode(rcPath)) {
ResourceConfiguration rc =3D new ResourceConfiguration(rea=
lm.getRTIRepository().getNode(ResourceConfigurationMap.getRCPath(realm, pat=
h)));
- if (rc !=3D null) return getResource(environment, realm, p=
ath, rc);
+ return rc; //TODO check null check!
} else {
throw new Exception("Request did match within resource con=
figuration map of realm '" + realm.getName() + "', but no such resource typ=
e configuration node exist: " + rcPath);
}
} =
=
- // Fallback to file/node resource
- return getResource(environment, realm, path, new ResourceConfigura=
tion("file", "http://www.wyona.org/yanel/resource/1.0", null));
+ // Fallback to file/node resource configuration
+ return new ResourceConfiguration("file", "http://www.wyona.org/yan=
el/resource/1.0", null);
=
}
=
/**
* Returns the abstraction of the rti file for the given path in the r=
ealm.
* TODO: move this method to some RTIManager class ?
- * @deprecated
+ * @deprecated Use {@link #getResourceConfiguration(Environment, Realm=
, String)} instead.
*/
+ @Deprecated
public ResourceTypeIdentifier getResourceTypeIdentifier(Realm realm, S=
tring path) throws Exception {
log.debug("Original path: " + path);
try {
Index: src/impl/java/org/wyona/yanel/impl/ResourceTypeDefaultMatcher.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/impl/java/org/wyona/yanel/impl/ResourceTypeDefaultMatcher.java (Rev=
ision 0)
+++ src/impl/java/org/wyona/yanel/impl/ResourceTypeDefaultMatcher.java (Rev=
ision 0)
@@ -0,0 +1,23 @@
+package org.wyona.yanel.impl;
+
+import java.util.Map;
+
+import org.wyona.yanel.core.Environment;
+import org.wyona.yanel.core.ResourceConfiguration;
+import org.wyona.yanel.core.ResourceManager;
+import org.wyona.yanel.core.api.ResourceTypeMatcherV1;
+import org.wyona.yanel.core.map.Realm;
+
+public class ResourceTypeDefaultMatcher implements ResourceTypeMatcherV1 {
+
+ private static final ResourceManager rm =3D new ResourceManager();
+
+ public ResourceConfiguration getResourceConfiguration(Environment envi=
ronment, Realm realm, String path) throws Exception {
+ // TODO handle parameters
+ Map<String, String> parameterMap =3D (Map<String, String>) environ=
ment.getRequest().getParameterMap();
+
+ //throw new UnsupportedOperationException();
+ return rm.getResourceConfiguration(environment, realm, path);
+ }
+
+}
Index: src/core/java/org/wyona/yanel/core/api/ResourceTypeMatcherV1.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/core/java/org/wyona/yanel/core/api/ResourceTypeMatcherV1.java (Revi=
sion 0)
+++ src/core/java/org/wyona/yanel/core/api/ResourceTypeMatcherV1.java (Revi=
sion 0)
@@ -0,0 +1,11 @@
+package org.wyona.yanel.core.api;
+
+import org.wyona.yanel.core.Environment;
+import org.wyona.yanel.core.ResourceConfiguration;
+import org.wyona.yanel.core.map.Realm;
+
+public interface ResourceTypeMatcherV1 {
+
+ public ResourceConfiguration getResourceConfiguration(Environment envi=
ronment, Realm realm, String path) throws Exception;
+
+}
Index: src/webapp/src/java/org/wyona/yanel/servlet/YanelGlobalResourceTypeM=
atcher.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/webapp/src/java/org/wyona/yanel/servlet/YanelGlobalResourceTypeMatc=
her.java (Revision 45854)
+++ src/webapp/src/java/org/wyona/yanel/servlet/YanelGlobalResourceTypeMatc=
her.java (Arbeitskopie)
@@ -8,9 +8,10 @@
import org.apache.commons.io.IOUtils;
import org.wyona.yanel.core.Environment;
import org.wyona.yanel.core.ResourceConfiguration;
+import org.wyona.yanel.core.api.ResourceTypeMatcherV1;
import org.wyona.yanel.core.map.Realm;
=
-class YanelGlobalResourceTypeMatcher {
+class YanelGlobalResourceTypeMatcher implements ResourceTypeMatcherV1 {
=
private String pathPrefix;
private String globalRCsBasePath;
Index: src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java (Revision=
45854)
+++ src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java (Arbeitsk=
opie)
@@ -38,6 +38,7 @@
import org.wyona.yanel.core.ResourceConfiguration;
import org.wyona.yanel.core.ResourceTypeRegistry;
import org.wyona.yanel.core.Yanel;
+import org.wyona.yanel.core.api.ResourceTypeMatcherV1;
import org.wyona.yanel.core.api.attributes.IntrospectableV1;
import org.wyona.yanel.core.api.attributes.ModifiableV1;
import org.wyona.yanel.core.api.attributes.ModifiableV2;
@@ -1635,7 +1636,7 @@
Realm realm;
Environment environment =3D getEnvironment(request, response);
ResourceConfiguration rc;
- YanelGlobalResourceTypeMatcher RTmatcher =3D new YanelGlobalResour=
ceTypeMatcher(pathPrefix, servletContextRealPath);
+ ResourceTypeMatcherV1 RTmatcher =3D new YanelGlobalResourceTypeMat=
cher(pathPrefix, servletContextRealPath);
try {
realm =3D getRealm(request);
rc =3D RTmatcher.getResourceConfiguration(environment, realm, =
path);
More information about the Yanel-development
mailing list