-
1. Re: Overriding xhtml and paga.xml files in a transparent way
swd847 Feb 16, 2009 10:34 PM (in response to demetrio812)Create a custom facelets ResourceResolver, if you override the resolveUrl method you can make it look in your override directory first.
As for the pages.xml you will probably have to override the seam component org.jboss.seam.navigation.pages, have a look at the code and you can probably figure out with methods need overriding.
Stuart
-
2. Re: Overriding xhtml and paga.xml files in a transparent way
demetrio812 Feb 17, 2009 1:04 AM (in response to demetrio812)I will try!
Thank you very much!
Demetrio
-
3. Re: Overriding xhtml and paga.xml files in a transparent way
swd847 Feb 17, 2009 4:04 AM (in response to demetrio812)The method you probably want to override on the Pages class is initialize, it will probably look something like this:
public void initialize(Set<String> fileNames) { Set<String newFileNames = new HashSet<String>(); for(String i: fileNames) { //lookup override here and add new (or old) path to the set } super.initialize(newFileNames); }
i am not sure how this will go with hot deploy, but it should point you in the right direction. There are plenty of tutorials on using the facelets ResourceResolver if you google for them.
Stuart
-
4. Re: Overriding xhtml and paga.xml files in a transparent way
demetrio812 Feb 17, 2009 9:29 PM (in response to demetrio812)Hi,
the ResourceResolver works perfectly, but I don't know if there is a way to override the Page component, I will look at the Seam source code tonight, in the mean time I wrote here and wait for other suggestions while looking also by myself... :)Thanks again!
Demetrio
-
5. Re: Overriding xhtml and paga.xml files in a transparent way
barakka Feb 17, 2009 10:08 PM (in response to demetrio812)Ciao Demetrio,
this is my attempt (working so far) at doing what you are asking for:
/** * This class adds pages.xml defined in jar files to the same page handler, as * this files don't get scanned by default by seam. * * @see ClasspathPagesDeploymentHandler * @see org.jboss.seam.navigation.Pages * @author rserafin * @version $Rev: 1027 $ $Date: 2009-01-28 23:50:23 +0100 (Wed, 28 Jan 2009) $ */ @Name("es.tsbsoluciones.platform.utils.web.classpathPagesAdder") @Scope(ScopeType.APPLICATION) @Startup(depends = "org.jboss.seam.navigation.pages") @Install(classDependencies = "org.jboss.seam.navigation.Pages", dependencies = { "org.jboss.seam.navigation.pages" }) public class ClasspathPagesAdder { /** Handler that has collected all pages.xml files. */ protected ClasspathPagesDeploymentHandler pagesHandler; /** Handler that has collected all .page.xml files. */ protected ClasspathDotPagesDeploymentHandler dotPagesHandler; /** Logger. */ @Logger protected Log log; /** * Startup method that will add all collected files. */ @Create public void create() { log.trace("Created."); // Retrieve deployment handlers final DeploymentStrategy strategy = (DeploymentStrategy) Contexts .lookupInStatefulContexts("deploymentStrategy"); if (strategy == null) { throw new IllegalStateException("Unable to locate seam deployment strategy."); } log.trace("Current deployment strategy: " + strategy); pagesHandler = (ClasspathPagesDeploymentHandler) strategy.getDeploymentHandlers().get( ClasspathPagesDeploymentHandler.class.getName()); if (pagesHandler == null) { throw new IllegalStateException("Unable to locate ClasspathPagesDeploymentHandler."); } dotPagesHandler = (ClasspathDotPagesDeploymentHandler) strategy.getDeploymentHandlers().get( ClasspathDotPagesDeploymentHandler.class.getName()); if (dotPagesHandler == null) { throw new IllegalStateException("Unable to locate ClasspathDotPagesDeploymentHandler."); } // First get a ref to the Pages component final Pages pages = (Pages) Component.getInstance(Pages.class, false); if (pages == null) { throw new IllegalStateException("Unable to locate the pages component."); } // The get the parse method final Method parse = getParseMethod(pages); if (parse == null) { throw new IllegalStateException("Unable to access the parse method."); } // The get the parse method final Method parsePages = getParsePagesMethod(pages); if (parsePages == null) { throw new IllegalStateException("Unable to access the parsePages method."); } // now add all pages.xml for (final FileDescriptor file : pagesHandler.getCollectedFileDescriptors()) { addPagesFile(file, pages, parse); } // finally add all .page.xml addPageFiles(dotPagesHandler.getCollectedFileDescriptors(), pages, parsePages); } /** * Adds a files to pages by reflection. * * @param files list of filenames to add * @param pages pages object to add it * @param parsePages method to be called */ protected void addPageFiles(final Set<FileDescriptor> files, final Pages pages, final Method parsePages) { // Try to call the pages object to add it try { for (final FileDescriptor fileDescriptor : files) { log.trace("Adding .pages.xml file: #0", fileDescriptor.getUrl()); } parsePages.invoke(pages, (Object) files); } catch (final IllegalArgumentException e) { log.warn("IllegalArgumentException while trying to invoke the parsePages method.", e); } catch (final IllegalAccessException e) { log.warn("IllegalAccessException while trying to invoke the parsePages method."); } catch (final InvocationTargetException e) { log.warn("IllegalAccessException while trying to invoke the parsePages method."); } } /** * Adds a files to pages by reflection. * * @param file file descriptor to parse * @param pages pages object to add it * @param parse method to be called */ protected void addPagesFile(final FileDescriptor file, final Pages pages, final Method parse) { // Try to call the pages object to add it try { log.trace("Adding pages.xml file: #0", file.getUrl()); // Try to get an input stream for the file final InputStream fileStream = file.getUrl().openStream(); parse.invoke(pages, fileStream); } catch (final IllegalArgumentException e) { log.warn("IllegalArgumentException while trying to invoke the parse method.", e); } catch (final IllegalAccessException e) { log.warn("IllegalAccessException while trying to invoke the parse method.", e); } catch (final InvocationTargetException e) { log.warn("IllegalAccessException while trying to invoke the parse method.", e); } catch (final IOException e) { log.warn("Unable to access pages.xml file: " + file.getUrl(), e); } } /** * Return the parse method of the pages object obtaining it by reflection * (as it private, sigh). * * @param pages the pages object. * @return the parse method, if possible, null otherwise. */ protected Method getParseMethod(final Pages pages) { try { final Method parse = pages.getClass().getDeclaredMethod("parse", InputStream.class); parse.setAccessible(true); return parse; } catch (final SecurityException e) { log.warn("SecurityException while trying to get the parse method."); } catch (final NoSuchMethodException e) { log.warn("NoSuchMethodException while trying to get the parse method."); } return null; } /** * Return the parsePages method of the pages object obtaining it by * reflection (as it private, sigh). * * @param pages the pages object. * @return the parsePages method, if possible, null otherwise. */ protected Method getParsePagesMethod(final Pages pages) { try { for (final Method m : pages.getClass().getDeclaredMethods()) { if (m.getName().equals("parsePages")) { m.setAccessible(true); return m; } } } catch (final SecurityException e) { log.warn("SecurityException while trying to get the parse method."); } return null; } }
where ClasspathPagesDeploymentHandler and ClasspathDotPagesDeploymentHandler are custom seam deployers handlers for pages.xml and .page.xml. The class uses reflection to manipulate the pages component, as the methods I needed where private. I definitely don't like it very much (I know, i was the one making it... but in retrospective), and if some seam developer would make those methods public or at least protected it would really help.
You might also want to have a look at the seam wiki example, as I believe to remember that they do something similar to manage the plugins.
Hope this can help,
Riccardo. -
6. Re: Overriding xhtml and paga.xml files in a transparent way
demetrio812 Feb 18, 2009 3:37 AM (in response to demetrio812)Ciao Riccardo!
Thank you very much for your code!My problem is different but I will solve it using
your way
;)Rewriting (without mistakes) the example I've done in the first post:
/root/ /page1.page.xml /page1.xhtml /page2.page.xml /page2.xhtml /override/ /page1.page.xml /page1.xhtml
I have to make seam to use /override/page1.page.xml as the page file for the viewId /file1.xhtml
Initially Seam adds also the .page.xml files that are inside the override directory so I have to remove all the file with an override (both the normal viewId and the override one) and then add another page with the normal view but reading the content of the .page.xml file inside the override.
I hope I explained well, another problem I'll have to solve will be the hot deploy (it adds all the pages again).
I hope that next version of Seam will have more support for this kind of personalizations. :)
I'll write here how I am going :)
Thanks again!
Demetrio
-
7. Re: Overriding xhtml and paga.xml files in a transparent way
demetrio812 Feb 19, 2009 1:49 AM (in response to demetrio812)Hi,
I didn't have a lot of time today but it seems it is working and I will post the final version very soon...I have also to check it against the url rewrite of the page and the overridden ones but I don't think there will be problems...thanks again!!
Demetrio