taylor 2004/12/03 01:37:59 Modified: portal/src/java/org/apache/jetspeed/deployment/impl DeployDecoratorEventListener.java DeployPortletAppEventListener.java portal/src/java/org/apache/jetspeed/velocity JetspeedPowerTool.java portal/src/test/org/apache/jetspeed/deployment TestSimpleDeployment.java portal/src/webapp/WEB-INF/assembly jetspeed-spring.xml Log: decorator and layout autodeploy feature completed. Submitted by: Randy Watler Reviewed by: David Taylor CVS: ---------------------------------------------------------------------- CVS: PR: CVS: If this change addresses a PR in the problem report tracking CVS: database, then enter the PR number(s) here. CVS: Obtained from: CVS: If this change has been taken from another system, such as NCSA, CVS: then name the system in this line, otherwise delete it. CVS: Submitted by: CVS: If this code has been contributed to Apache by someone else; i.e., CVS: they sent us a patch or a new module, then include their name/email CVS: address here. If this is your work then delete this line. CVS: Reviewed by: CVS: If we are doing pre-commit code reviews and someone else has CVS: reviewed your changes, include their name(s) here. CVS: If you have not had it reviewed then delete this line. Revision Changes Path 1.7 +317 -81 jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/deployment/impl/DeployDecoratorEventListener.java Index: DeployDecoratorEventListener.java =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/deployment/impl/DeployDecoratorEventListener.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- DeployDecoratorEventListener.java 1 Dec 2004 17:06:28 -0000 1.6 +++ DeployDecoratorEventListener.java 3 Dec 2004 09:37:59 -0000 1.7 @@ -7,9 +7,13 @@ package org.apache.jetspeed.deployment.impl; import java.io.File; +import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.logging.Log; @@ -34,11 +38,15 @@ */ public class DeployDecoratorEventListener implements DeploymentEventListener { - protected SimpleRegistry registry; protected static final Log log = LogFactory.getLog("deployment"); + + protected static final String DEPLOYMENT_OBJECT_PATH_ATTR = "DEPLOYMENT_OBJECT_PATH"; + protected static final String DEPLOYMENT_CONFIGURATION_ATTR = "DEPLOYMENT_CONFIGURATION"; + + protected SimpleRegistry registry; protected String deployToDir; - public DeployDecoratorEventListener( SimpleRegistry registry, String deployToDir ) throws IOException + public DeployDecoratorEventListener(SimpleRegistry registry, String deployToDir) throws IOException { this.registry = registry; @@ -55,138 +63,366 @@ } /** - * @see org.apache.jetspeed.deployment.DeploymentEventListener#invoke(org.apache.jetspeed.deployment.DeploymentEvent) + * <p> + * invokeDeploy + * </p> + * + * @see org.apache.jetspeed.deployment.DeploymentEventListener#invokeDeploy(org.apache.jetspeed.deployment.DeploymentEvent) + * @param event + * @throws DeploymentException */ - public void invokeDeploy( DeploymentEvent event ) throws DeploymentException + public void invokeDeploy(DeploymentEvent event) throws DeploymentException { - InputStream configStream = null; + // get decorator configuration if available + PropertiesConfiguration conf = getDecoratorConfiguration(event); + // silently return if configuration not available, (assumes + // probably not a decorator) + if (conf == null) + { + return; + } - PropertiesConfiguration conf; - try + // process decorator by id + String id = conf.getString("id"); + if (id != null) { + log.info("Found decorator deployment archive " + id); + Entry entry = new Entry(); + entry.setId(id); + entry.setAttribute(DEPLOYMENT_OBJECT_PATH_ATTR, event.getDeploymentObject().getPath()); + entry.setAttribute(DEPLOYMENT_CONFIGURATION_ATTR, conf); - configStream = event.getDeploymentObject().getConfiguration("decorator.properties"); - if (configStream == null) + FileSystemHelper sourceObject = null; + FileSystemHelper deployObject = null; + try { - return; + // construct decorator deploy path + String baseDeployPath = getBaseDeployPath(conf); + String deployPath = baseDeployPath + File.separator + id; + File deployPathFile = new File(deployPath); + + // undeploy decorator if it already exists and is a redeploy or + // skip deployment if initial deployment + if (deployPathFile.exists()) + { + if (event.getEventType().equals(DeploymentEvent.EVENT_TYPE_REDEPLOY)) + { + invokeUndeploy(event); + } + else if (event.getEventType().equals(DeploymentEvent.EVENT_TYPE_DEPLOY)) + { + log.info("Skipping initial deployment of decorator " + id + " to " + deployPath); + + // register deployed decorator + registry.register(entry); + log.info("Registering decorator " + id); + return; + } + } + + // redeploy/deploy decorator w/o META_INF jar metadata + log.info("Deploying decorator " + id + " to " + deployPath); + deployPathFile.mkdirs(); + deployObject = new DirectoryHelper(deployPathFile); + sourceObject = event.getDeploymentObject().getFileObject(); + deployObject.copyFrom(sourceObject.getRootDirectory()); + File metaInf = new File(deployPathFile, "META-INF"); + if (metaInf.exists()) + { + DirectoryHelper cleanup = new DirectoryHelper(metaInf); + cleanup.remove(); + cleanup.close(); + } + + // detect language/country localized decorator components + final List localeSpecificDeployPathsList = getLocaleSpecificDeployPaths(deployPathFile); + + // deploy individual locale specific decorator components + Iterator deployPathsIter = localeSpecificDeployPathsList.iterator(); + while (deployPathsIter.hasNext()) + { + File localeDeployPathFile = (File) deployPathsIter.next(); + + // deploy to locale specific location + File deployToPathFile = new File(baseDeployPath + localeDeployPathFile.getPath().substring(deployPath.length()) + File.separator + id); + log.info("Deploying decorator " + id + " to " + deployToPathFile.getPath()); + deployToPathFile.mkdirs(); + + // deploy decorator components by moving from deployed decorator + File [] filesToDeploy = localeDeployPathFile.listFiles(new FileFilter() + { + public boolean accept(File pathname) + { + return !localeSpecificDeployPathsList.contains(pathname); + } + }); + for (int i = 0; (i < filesToDeploy.length); i++) + { + filesToDeploy[i].renameTo(new File(deployToPathFile, filesToDeploy[i].getName())); + } + } + + // cleanup locale specific deployment directories + Iterator cleanupDeployPathsIter = localeSpecificDeployPathsList.iterator(); + while (cleanupDeployPathsIter.hasNext()) + { + File cleanupLocaleDeployPathFile = (File) cleanupDeployPathsIter.next(); + if (cleanupLocaleDeployPathFile.exists()) + { + DirectoryHelper cleanup = new DirectoryHelper(cleanupLocaleDeployPathFile); + cleanup.remove(); + cleanup.close(); + } + } + + // register + registry.register(entry); + log.info("Registering decorator " + id); + + log.info("Decorator " + id + " deployed and registered successfuly."); } - else + catch (Exception e) { - conf = new PropertiesConfiguration(); - conf.load(configStream); + log.error("Error deploying or registering decorator " + id + ": " + e.toString(), e); } - } - catch (Exception e1) - { - // TODO Auto-generated catch block - - throw new DeploymentException("Error reading configuration from jar: " + e1.toString(), e1); - } - finally - { - if (configStream != null) + finally { try { - configStream.close(); + if (sourceObject != null) + { + sourceObject.close(); + } + if (deployObject != null) + { + deployObject.close(); + } } - catch (IOException e) + catch (IOException e2) { - } } } + else + { + log.error("Unable to register directory, \"id\" attribute not defined in configuration"); + } + } - String id = conf.getString("id"); - if (id != null) + /** + * <p> + * invokeUndeploy + * </p> + * + * @see org.apache.jetspeed.deployment.DeploymentEventListener#invokeUndeploy(org.apache.jetspeed.deployment.DeploymentEvent) + * @param event + * @throws DeploymentException + */ + public void invokeUndeploy(DeploymentEvent event) throws DeploymentException + { + // get deployment configuration from decorator configuration + // if available or lookup based on registered attributes + PropertiesConfiguration conf = getDecoratorConfiguration(event); + if ((conf == null) && (event.getPath() != null)) { - log.info("Found decorator deployment archive " + id); - Entry entry = new Entry(); - entry.setId(id); - if (!registry.isRegistered(entry)) + Iterator registrationsIter = registry.getRegistry().iterator(); + while ((conf == null) && registrationsIter.hasNext()) { - log.info("Deploying decorator " + id); - FileSystemHelper sourceObject = null; - FileSystemHelper deployObject = null; - try + Entry entry = (Entry)registrationsIter.next(); + String deploymentObjectPath = (String) entry.getAttribute(DEPLOYMENT_OBJECT_PATH_ATTR); + if (event.getPath().equals(deploymentObjectPath)) { + conf = (PropertiesConfiguration) entry.getAttribute(DEPLOYMENT_CONFIGURATION_ATTR); + } + } + } + // silently return if configuration not available, (assumes + // probably not a decorator) + if (conf == null) + { + return; + } - String mediaType = conf.getString("media.type", "html"); - log.info("Decorator " + id + " supports media type \"" + mediaType + "\""); - String deployPath = deployToDir + File.separator + mediaType + File.separator + id; - log.info("Deploying decorator " + id + " to " + deployPath); - sourceObject = event.getDeploymentObject().getFileObject(); - - File deployPathFile = new File(deployPath); - deployPathFile.mkdirs(); - deployObject = new DirectoryHelper(deployPathFile); - deployObject.copyFrom(sourceObject.getRootDirectory()); + // process decorator by id + String id = conf.getString("id"); + if (id != null) + { + log.info("Found decorator deployment configuration " + id); - registry.register(entry); - log.info("Registering decorator " + deployToDir + "/" + id); - } - catch (Exception e) + try + { + // find and construct decorator deploy path + String baseDeployPath = getBaseDeployPath(conf); + String deployPath = baseDeployPath + File.separator + id; + + // undeploy decorator + File deployPathFile = new File(deployPath); + if (deployPathFile.exists()) { - log.error("Error deploying decorator " + id + ": " + e.toString(), e); - + log.info("Undeploying decorator " + id + " at " + deployPath); + DirectoryHelper cleanup = new DirectoryHelper(deployPathFile); + cleanup.remove(); + cleanup.close(); } - finally + + // detect language/country localized decorator components + final List localeSpecificDeployPathsList = getLocaleSpecificDeployPaths(new File(baseDeployPath)); + + // undeploy individual locale specific decorator components + Iterator deployPathsIter = localeSpecificDeployPathsList.iterator(); + while (deployPathsIter.hasNext()) { - try - { - if (sourceObject != null) - { - sourceObject.close(); - } - - if (deployObject != null) - { - deployObject.close(); - } - } - catch (IOException e2) + File localeDeployPathFile = new File((File) deployPathsIter.next(), id); + if (localeDeployPathFile.exists()) { - + log.info("Undeploying decorator " + id + " at " + localeDeployPathFile.getPath()); + DirectoryHelper cleanup = new DirectoryHelper(localeDeployPathFile); + cleanup.remove(); + cleanup.close(); + localeDeployPathFile.getParentFile().delete(); } } - } - log.info("Decorator " + id + " deployed and registered successfuly."); + + // deregister + Entry entry = new Entry(); + entry.setId(id); + registry.deRegister(entry); + log.info("Deregistering decorator " + id); + log.info("Decorator " + id + " undeployed and deregistered successfuly."); + } + catch (Exception e) + { + log.error("Error undeploying or deregistering decorator " + id + ": " + e.toString(), e); + } } else { - log.error("Unable to register directory, \"id\" attribute not defined in configuration"); + log.error("Unable to deregister directory, \"id\" attribute not defined in configuration or configuration not available"); } - } /** * <p> - * invokeUndeploy + * invokeRedeploy * </p> * - * @see org.apache.jetspeed.deployment.DeploymentEventListener#invokeUndeploy(org.apache.jetspeed.deployment.DeploymentEvent) + * @see org.apache.jetspeed.deployment.DeploymentEventListener#invokeRedeploy(org.apache.jetspeed.deployment.DeploymentEvent) * @param event * @throws DeploymentException */ - public void invokeUndeploy( DeploymentEvent event ) throws DeploymentException + public void invokeRedeploy(DeploymentEvent event) throws DeploymentException { - // TODO Auto-generated method stub - + invokeDeploy(event); } /** * <p> - * invokeRedeploy + * getDecorationConfiguration * </p> * - * @see org.apache.jetspeed.deployment.DeploymentEventListener#invokeRedeploy(org.apache.jetspeed.deployment.DeploymentEvent) * @param event + @ @return configuration * @throws DeploymentException */ - public void invokeRedeploy( DeploymentEvent event ) throws DeploymentException + private PropertiesConfiguration getDecoratorConfiguration(DeploymentEvent event) throws DeploymentException { - // TODO Auto-generated method stub + InputStream stream = null; + try + { + if (event.getDeploymentObject() == null) + { + return null; + } + stream = event.getDeploymentObject().getConfiguration("decorator.properties"); + if (stream == null) + { + return null; + } + else + { + PropertiesConfiguration configuration = new PropertiesConfiguration(); + configuration.load(stream); + return configuration; + } + } + catch (Exception e1) + { + throw new DeploymentException("Error reading configuration from jar: " + e1.toString(), e1); + } + finally + { + if (stream != null) + { + try + { + stream.close(); + } + catch (IOException e) + { + + } + } + } + } + + /** + * <p> + * getBaseDeployPath + * </p> + * + * @param configuration + * @return base deploy path + */ + private String getBaseDeployPath(PropertiesConfiguration configuration) + { + // construct decorator deploy base path + String decorates = configuration.getString("decorates", "generic"); + String layoutType = decorates; + if (layoutType.equalsIgnoreCase("any")) + { + layoutType = "generic"; + } + String mediaType = configuration.getString("media.type", "html"); + return deployToDir + File.separator + layoutType + File.separator + mediaType; + } + /** + * <p> + * getLocaleSpecificDeployPaths + * </p> + * + * @param rootPath + * @return locale paths list + */ + private List getLocaleSpecificDeployPaths(File rootPath) + { + // detect language/country localized deploy paths + List localeSpecificDeployPathsList = new ArrayList(); + File [] localeLanguageSpecificRoots = rootPath.listFiles(new FileFilter() + { + public boolean accept(File pathname) + { + // filter language code dirs, (assume length test is accurate enough) + return (pathname.isDirectory() && (pathname.getName().length() == 2)); + } + }); + for (int i = 0; (i < localeLanguageSpecificRoots.length); i++) + { + localeSpecificDeployPathsList.add(localeLanguageSpecificRoots[i]); + File [] localeCountrySpecificPaths = localeLanguageSpecificRoots[i].listFiles(new FileFilter() + { + public boolean accept(File pathname) + { + // filter country code dirs, (assume length test is accurate enough) + return (pathname.isDirectory() && (pathname.getName().length() == 2)); + } + }); + for (int j = 0; (j < localeCountrySpecificPaths.length); j++) + { + localeSpecificDeployPathsList.add(localeCountrySpecificPaths[j]); + } + } + return localeSpecificDeployPathsList; } -} \ No newline at end of file +} 1.20 +4 -7 jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/deployment/impl/DeployPortletAppEventListener.java Index: DeployPortletAppEventListener.java =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/deployment/impl/DeployPortletAppEventListener.java,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- DeployPortletAppEventListener.java 29 Oct 2004 14:18:04 -0000 1.19 +++ DeployPortletAppEventListener.java 3 Dec 2004 09:37:59 -0000 1.20 @@ -93,18 +93,15 @@ String paName = null; try { - - boolean isLocal = event.getName().startsWith("jetspeed-"); - String filePath = event.getPath(); paName = (String) appNameToFile.get(filePath); if (paName == null) { - String msg = "Unable to locate application name for archive \"" + filePath + "\""; - log.warn(msg); - throw new DeploymentException(msg); + return; } + boolean isLocal = event.getName().startsWith("jetspeed-"); + PortletApplicationWar deployedWar = null; PortletApplicationDefinition pa = registry.getPortletApplicationByIdentifier(paName); @@ -348,4 +345,4 @@ PortletApplicationWar targetWar = new PortletApplicationWar(target, id, "/" + id); return targetWar.createClassloader(parent); } -} \ No newline at end of file +} 1.37 +3 -2 jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/velocity/JetspeedPowerTool.java Index: JetspeedPowerTool.java =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/velocity/JetspeedPowerTool.java,v retrieving revision 1.36 retrieving revision 1.37 diff -u -r1.36 -r1.37 --- JetspeedPowerTool.java 19 Nov 2004 03:07:43 -0000 1.36 +++ JetspeedPowerTool.java 3 Dec 2004 09:37:59 -0000 1.37 @@ -743,7 +743,8 @@ TemplateDescriptor propsTemp = getTemplate(decorator + "/" + DECORATOR_TYPE + ".properties", fragmentType, decorationLocator, decorationLocatorDescriptor); if(propsTemp == null) { - propsTemp = getTemplate(decorator + "/" + DECORATOR_TYPE + ".properties", GENERIC_TEMPLATE_TYPE, decorationLocator, decorationLocatorDescriptor); + fragmentType = GENERIC_TEMPLATE_TYPE; + propsTemp = getTemplate(decorator + "/" + DECORATOR_TYPE + ".properties", fragmentType, decorationLocator, decorationLocatorDescriptor); } // get decorator template 1.21 +3 -3 jakarta-jetspeed-2/portal/src/test/org/apache/jetspeed/deployment/TestSimpleDeployment.java Index: TestSimpleDeployment.java =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/portal/src/test/org/apache/jetspeed/deployment/TestSimpleDeployment.java,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- TestSimpleDeployment.java 29 Oct 2004 14:33:27 -0000 1.20 +++ TestSimpleDeployment.java 3 Dec 2004 09:37:59 -0000 1.21 @@ -151,7 +151,7 @@ autoDeployment.start(); autoDeployment.fireDeploymentEvent(); - File decoratorVm = new File(deployRootFile.getAbsolutePath() + File.separator + "html" + File.separator + File decoratorVm = new File(deployRootFile.getAbsolutePath() + File.separator + "generic" + File.separator + "html" + File.separator + "portletstd" + File.separator + "decorator.vm"); File demoAppDeployed = new File(webAppsDirFile, TEST_PORTLET_APP_NAME); @@ -490,4 +490,4 @@ } -} \ No newline at end of file +} 1.35 +13 -6 jakarta-jetspeed-2/portal/src/webapp/WEB-INF/assembly/jetspeed-spring.xml Index: jetspeed-spring.xml =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/portal/src/webapp/WEB-INF/assembly/jetspeed-spring.xml,v retrieving revision 1.34 retrieving revision 1.35 diff -u -r1.34 -r1.35 --- jetspeed-spring.xml 26 Nov 2004 18:50:26 -0000 1.34 +++ jetspeed-spring.xml 3 Dec 2004 09:37:59 -0000 1.35 @@ -722,11 +722,7 @@ <property name="searchEngine"><ref bean="org.apache.jetspeed.search.SearchEngine"/></property> </bean> - - - - - <!-- Portlet Application deployment event listener --> + <!-- Portlet Application and Decorator deployment event listeners --> <bean id="portletAppDeploymentListener" class="org.apache.jetspeed.deployment.impl.DeployPortletAppEventListener" > @@ -735,7 +731,17 @@ <constructor-arg ><ref bean="org.apache.jetspeed.components.portletregistry.PortletRegistry" /></constructor-arg> <constructor-arg><ref bean="portletFactory"/></constructor-arg> </bean> - + <bean id="decoratorDeploymentRegistry" + class="org.apache.jetspeed.deployment.simpleregistry.impl.InMemoryRegistryImpl" + > + </bean> + <bean id="decoratorDeploymentListener" + class="org.apache.jetspeed.deployment.impl.DeployDecoratorEventListener" + > + <constructor-arg ><ref bean="decoratorDeploymentRegistry"/></constructor-arg> + <constructor-arg ><value>${applicationRoot}/WEB-INF/decorations</value></constructor-arg> + </bean> + <!-- The deployment manager watches a specific staging directory for deploying components. What components get deployed depend of DeploymentEventListeners registered to it. @@ -749,6 +755,7 @@ <constructor-arg > <list> <ref bean="portletAppDeploymentListener"/> + <ref bean="decoratorDeploymentListener"/> </list> </constructor-arg> </bean>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]