Author: jleroux
Date: Wed Oct 23 20:48:36 2013 New Revision: 1535171 URL: http://svn.apache.org/r1535171 Log: Create a branch for easier exchanges on OFBIZ-5312 Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/ (props changed) - copied from r1535157, ofbiz/trunk/ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/SeoConfig.xml (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/urlregexp.xml (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/SeoConfig.xsd (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/urlregexp.xsd (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CatalogUrlSeoFilter.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CategoryUrlServlet.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ControlServlet.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ProductUrlServlet.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlFilter.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlServlet.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoConfigUtil.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoContentUrlFilter.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoContextFilter.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoControlServlet.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoUrlUtil.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/UrlRegexpConfigUtil.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/UrlRegexpContextFilter.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/UrlUtil.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ftl/ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ftl/CatalogAltUrlSeoTransform.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ftl/CatalogUrlSeoTransform.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ftl/OfbizCatalogAltUrlTransform.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ftl/OfbizCatalogUrlTransform.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ftl/SeoTransform.java (with props) ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ftl/UrlRegexpTransform.java (with props) Removed: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/OfbizCatalogAltUrlTransform.java ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/OfbizCatalogUrlTransform.java Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/build.xml ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/freemarkerTransforms.properties ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/web.xml Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Wed Oct 23 20:48:36 2013 @@ -0,0 +1,12 @@ +ofbiz.jar +bin +*.patch +*.iml +*.ipr +*.iws +*.time +.settings +.project +changelog +.idea +dependencyCheck.groovy Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/ ------------------------------------------------------------------------------ --- svn:mergeinfo (added) +++ svn:mergeinfo Wed Oct 23 20:48:36 2013 @@ -0,0 +1,6 @@ +/ofbiz/branches/2013_RemoveJavolution:1462755 +/ofbiz/branches/addbirt:831210-885099,885686-886087 +/ofbiz/branches/dojo1.4:951708-952957 +/ofbiz/branches/jackrabbit20100709:962442-1231517 +/ofbiz/branches/jquery:952958-1044489 +/ofbiz/branches/multitenant20100310:921280-927264 Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/build.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/build.xml?rev=1535171&r1=1535157&r2=1535171&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/build.xml (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/build.xml Wed Oct 23 20:48:36 2013 @@ -44,6 +44,7 @@ under the License. <fileset dir="../../framework/webapp/lib" includes="*.jar"/> <fileset dir="../../framework/webapp/build/lib" includes="*.jar"/> <fileset dir="../../framework/common/build/lib" includes="*.jar"/> + <fileset dir="../../framework/base/lib/scripting" includes="*.jar"/> <fileset dir="../content/lib" includes="*.jar"/> <fileset dir="../content/build/lib" includes="*.jar"/> <fileset dir="../party/build/lib" includes="*.jar"/> Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/SeoConfig.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/SeoConfig.xml?rev=1535171&view=auto ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/SeoConfig.xml (added) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/SeoConfig.xml Wed Oct 23 20:48:36 2013 @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<seo-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../dtd/SeoConfig.xsd"> + <regexpifmatch>^.*/.*$</regexpifmatch> + + <debug>false</debug> + + <config> + <description>sample: remove jsessionid</description> + <seo> + <url-pattern>^(.*);jsessionid=(.*)jvm[1-9](.*)$</url-pattern> + <replacement>$1$3</replacement> + </seo> + <forward> + <url-pattern>^(.*);jsessionid=(.*)jvm[1-9](.*)$</url-pattern> + <replacement>$1$3</replacement> + <responsecode>301</responsecode> + </forward> + </config> + + <config> + <description>sample: remove /ecommerce/main</description> + <seo> + <url-pattern>^/ecommerce/main$</url-pattern> + <replacement>/ecommerce/</replacement> + </seo> + <forward> + <url-pattern>^/ecommerce/main$</url-pattern> + <replacement>/ecommerce/</replacement> + <responsecode>301</responsecode> + </forward> + </config> + + <config> + <description>sample: remove /main</description> + <seo> + <url-pattern>^/main$</url-pattern> + <replacement>/</replacement> + </seo> + <forward> + <url-pattern>^/main$</url-pattern> + <replacement>/</replacement> + <responsecode>301</responsecode> + </forward> + </config> + +</seo-config> Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/SeoConfig.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/SeoConfig.xml ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/SeoConfig.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Modified: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/freemarkerTransforms.properties URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/freemarkerTransforms.properties?rev=1535171&r1=1535157&r2=1535171&view=diff ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/freemarkerTransforms.properties (original) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/freemarkerTransforms.properties Wed Oct 23 20:48:36 2013 @@ -21,6 +21,8 @@ # entries are in the form: key=transform name, property=transform class name -ofbizCatalogAltUrl=org.ofbiz.product.category.OfbizCatalogAltUrlTransform -ofbizCatalogUrl=org.ofbiz.product.category.CatalogUrlDirective +#ofbizCatalogAltUrl=org.ofbiz.product.category.ftl.OfbizCatalogAltUrlTransform +#ofbizCatalogUrl=org.ofbiz.product.category.ftl.CatalogUrlDirective +ofbizCatalogAltUrl=org.ofbiz.product.category.ftl.CatalogAltUrlSeoTransform +ofbizCatalogUrl=org.ofbiz.product.category.ftl.CatalogUrlSeoTransform Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/urlregexp.xml URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/urlregexp.xml?rev=1535171&view=auto ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/urlregexp.xml (added) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/urlregexp.xml Wed Oct 23 20:48:36 2013 @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<urlregexp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../dtd/urlregexp.xsd"> + <regexpifmatch>^.*/.*$</regexpifmatch> + + <debug>false</debug> + + <category-url> + <value>enable</value><!-- enable/disable + 1. if enable, the product seo url will be /product-name-product-id.html or /category-name-product-name-product-id.html + 2. if disable, the CatalogUrlServlet.makeCatalogUrl will be used --> + <allowed-context-paths>/:/ecommerce</allowed-context-paths><!-- if category-url is enabled, + only context paths listed here will be allowed to use the new seo transformers --> + <category-name>disable</category-name><!-- enable/disable + 1. if enable, the product seo url will be /category-name-product-name-product-id.html + 2. if disable, the product seo url will be /product-name-product-id.html --> + <category-url-suffix>.html</category-url-suffix><!-- suffix to add to the product seo url --> + </category-url> + + <jsessionid> + <anonymous> + <value>disable</value><!-- enable/disable + 1. when disable, the seo url patterns that contains jsessionid will be applied; + 2. when enable, the seo url patterns that contains jsessionid will be skipped --> + </anonymous> + <user> + <value>disable</value><!-- enable/disable + 1. when disable, the url-patterns under exceptions will be used to skip the seo url patterns that contains jsessionid; + 2. when enable, the seo url patterns that contains jsessionid will be skipped --> + <exceptions> + <url-pattern>^.*/(keywordsearch|logout).*$</url-pattern><!-- sample: ^.*/(keywordsearch|logout).*$ --> + </exceptions> + </user> + </jsessionid> + + <name-filters> + <filter> + <character-pattern>\u00fc</character-pattern> + <replacement>ue</replacement> + </filter> + <filter> + <character-pattern>\u00e4</character-pattern> + <replacement>ae</replacement> + </filter> + <filter> + <character-pattern>\u00f6</character-pattern> + <replacement>oe</replacement> + </filter> + <filter> + <character-pattern>\u00df</character-pattern> + <replacement>ss</replacement> + </filter> + <filter> + <character-pattern>\\+</character-pattern> + <replacement>und</replacement> + </filter> + <filter> + <character-pattern>\u0026</character-pattern> + <replacement>und</replacement> + </filter> + <filter> + <character-pattern>è</character-pattern> + <replacement>e</replacement> + </filter> + <!-- please keep the following 2 filters, don't remove them --> + <filter> + <character-pattern>[^A-Za-z0-9+-]</character-pattern> + <replacement>-</replacement> + </filter> + <filter> + <character-pattern>-{2,}</character-pattern> + <replacement>-</replacement> + </filter> + </name-filters> +<!-- + <config> + <description>sample: remove /control/main</description> + <seo> + <url-pattern>^/control/main$</url-pattern> + <replacement>/</replacement> + </seo> + <forward> + <url-pattern>^/control/main$</url-pattern> + <replacement>/</replacement> + <responsecode>301</responsecode> + </forward> + </config> + --> + + <config> + <description>sample: remove /main</description> + <seo> + <url-pattern>^/main$</url-pattern> + <replacement>/</replacement> + </seo> + <forward> + <url-pattern>^/main$</url-pattern> + <replacement>/</replacement> + <responsecode>301</responsecode> + </forward> + </config> + + <!-- <config> + <description>sample: remove all controller urls</description> + <seo> + <url-pattern>^/control/(.*)$</url-pattern> + <replacement>/$1</replacement> + </seo> + <forward> + <url-pattern>^/control/(.*)$</url-pattern> + <replacement>/$1</replacement> + <responsecode>301</responsecode> + </forward> + </config> --> + + <config> + <description>sample: remove jsessionid</description> + <seo> + <url-pattern>^(.*);jsessionid=(.*)jvm[1-9](.*)$</url-pattern> + <replacement>$1$3</replacement> + </seo> + </config> + +</urlregexp> Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/urlregexp.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/urlregexp.xml ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/config/urlregexp.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/SeoConfig.xsd URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/SeoConfig.xsd?rev=1535171&view=auto ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/SeoConfig.xsd (added) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/SeoConfig.xsd Wed Oct 23 20:48:36 2013 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + <xs:element name="seo-config"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="1" ref="regexpifmatch"/> + <xs:element minOccurs="0" maxOccurs="1" ref="debug"/> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="config"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="regexpifmatch"/> + <xs:element name="debug"/> + <xs:element name="config"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="1" ref="description"/> + <xs:element minOccurs="1" maxOccurs="1" ref="seo"/> + <xs:element minOccurs="0" maxOccurs="1" ref="forward"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="description"/> + <xs:element name="seo"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="1" maxOccurs="1" ref="url-pattern"/> + <xs:element minOccurs="1" maxOccurs="1" ref="replacement"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="forward"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="1" maxOccurs="1" ref="url-pattern"/> + <xs:element minOccurs="1" maxOccurs="1" ref="replacement"/> + <xs:element minOccurs="0" maxOccurs="1" ref="responsecode"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="url-pattern"/> + <xs:element name="replacement"/> + <xs:element name="responsecode" default="301"/> +</xs:schema> Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/SeoConfig.xsd ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/SeoConfig.xsd ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/SeoConfig.xsd ------------------------------------------------------------------------------ svn:mime-type = text/xsd Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/urlregexp.xsd URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/urlregexp.xsd?rev=1535171&view=auto ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/urlregexp.xsd (added) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/urlregexp.xsd Wed Oct 23 20:48:36 2013 @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + <xs:element name="urlregexp"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="1" ref="regexpifmatch"/> + <xs:element minOccurs="0" maxOccurs="1" ref="debug"/> + <xs:element minOccurs="0" maxOccurs="1" ref="category-url"/> + <xs:element minOccurs="0" maxOccurs="1" ref="jsessionid"/> + <xs:element minOccurs="0" maxOccurs="1" ref="name-filters"/> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="config"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="regexpifmatch"/> + <xs:element name="debug"/> + <xs:element name="category-url"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="1" maxOccurs="1" ref="value"/> + <xs:element minOccurs="0" maxOccurs="1" ref="allowed-context-paths"/> + <xs:element minOccurs="0" maxOccurs="1" ref="category-name"/> + <xs:element minOccurs="0" maxOccurs="1" ref="category-url-suffix"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="value" default="disable"/> + <xs:element name="allowed-context-paths"/> + <xs:element name="category-name" default="disable"/> + <xs:element name="category-url-suffix" default=".html"/> + <xs:element name="jsessionid"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="1" ref="anonymous"/> + <xs:element minOccurs="0" maxOccurs="1" ref="user"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="anonymous"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="1" ref="value"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="user"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="1" ref="value"/> + <xs:element minOccurs="0" maxOccurs="1" ref="exceptions"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="name-filters"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="filter"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="filter"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="1" maxOccurs="1" ref="character-pattern"/> + <xs:element minOccurs="1" maxOccurs="1" ref="replacement"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="character-pattern"/> + <xs:element name="exceptions"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="unbounded" ref="url-pattern"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="config"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="0" maxOccurs="1" ref="description"/> + <xs:element minOccurs="1" maxOccurs="1" ref="seo"/> + <xs:element minOccurs="0" maxOccurs="1" ref="forward"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="description"/> + <xs:element name="seo"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="1" maxOccurs="1" ref="url-pattern"/> + <xs:element minOccurs="1" maxOccurs="1" ref="replacement"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="forward"> + <xs:complexType> + <xs:sequence> + <xs:element minOccurs="1" maxOccurs="1" ref="url-pattern"/> + <xs:element minOccurs="1" maxOccurs="1" ref="replacement"/> + <xs:element minOccurs="0" maxOccurs="1" ref="responsecode"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="url-pattern"/> + <xs:element name="replacement"/> + <xs:element name="responsecode" default="301"/> +</xs:schema> Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/urlregexp.xsd ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/urlregexp.xsd ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/dtd/urlregexp.xsd ------------------------------------------------------------------------------ svn:mime-type = text/xsd Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CatalogUrlSeoFilter.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CatalogUrlSeoFilter.java?rev=1535171&view=auto ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CatalogUrlSeoFilter.java (added) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CatalogUrlSeoFilter.java Wed Oct 23 20:48:36 2013 @@ -0,0 +1,71 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.ofbiz.product.category; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.common.UrlServletHelper; +import org.ofbiz.entity.Delegator; +import org.ofbiz.product.category.ftl.CatalogUrlSeoTransform; + +public class CatalogUrlSeoFilter extends CatalogUrlFilter { + + public final static String module = CatalogUrlSeoFilter.class.getName(); + + protected static String defaultLocaleString = null; + protected static String redirectUrl = null; + + /** + * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) + */ + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; + Delegator delegator = (Delegator) httpRequest.getSession().getServletContext().getAttribute("delegator"); + + // Get ServletContext + ServletContext servletContext = config.getServletContext(); + + // Set request attribute and session + UrlServletHelper.setRequestAttributes(request, delegator, servletContext); + + // set initial parameters + String initDefaultLocalesString = config.getInitParameter("defaultLocaleString"); + String initRedirectUrl = config.getInitParameter("redirectUrl"); + defaultLocaleString = UtilValidate.isNotEmpty(initDefaultLocalesString) ? initDefaultLocalesString : ""; + redirectUrl = UtilValidate.isNotEmpty(initRedirectUrl) ? initRedirectUrl : ""; + + // set the ServletContext in the request for future use + httpRequest.setAttribute("servletContext", config.getServletContext()); + if (CatalogUrlSeoTransform.forwardUri(httpRequest, httpResponse, delegator, ControlServlet.controlServlet)) { + return; + } + super.doFilter(httpRequest, httpResponse, chain); + } + +} Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CatalogUrlSeoFilter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CatalogUrlSeoFilter.java ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CatalogUrlSeoFilter.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CategoryUrlServlet.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CategoryUrlServlet.java?rev=1535171&view=auto ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CategoryUrlServlet.java (added) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CategoryUrlServlet.java Wed Oct 23 20:48:36 2013 @@ -0,0 +1,78 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.ofbiz.product.category; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.ofbiz.entity.Delegator; +import org.ofbiz.product.category.ftl.CatalogUrlSeoTransform; + +/** + * ControlServlet.java - Master servlet for the web application. + */ +@SuppressWarnings("serial") +public class CategoryUrlServlet extends HttpServlet { + + public static final String module = CategoryUrlServlet.class.getName(); + public static final String CATEGORY_URL_MOUNT_POINT = "category"; + + public CategoryUrlServlet() { + super(); + } + + /** + * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) + */ + @Override + public void init(ServletConfig config) throws ServletException { + super.init(config); + } + + /** + * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + doGet(request, response); + } + + /** + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Delegator delegator = (Delegator) getServletContext().getAttribute("delegator"); + CatalogUrlSeoTransform.forwardCategoryUri(request, response, delegator, null); + } + + /** + * @see javax.servlet.Servlet#destroy() + */ + @Override + public void destroy() { + super.destroy(); + } + +} Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CategoryUrlServlet.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CategoryUrlServlet.java ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/CategoryUrlServlet.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ControlServlet.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ControlServlet.java?rev=1535171&view=auto ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ControlServlet.java (added) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ControlServlet.java Wed Oct 23 20:48:36 2013 @@ -0,0 +1,68 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.ofbiz.product.category; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.ofbiz.base.util.UtilValidate; + +/** + * ControlServlet.java - Master servlet for the web application. + */ +@SuppressWarnings("serial") +public class ControlServlet extends org.ofbiz.webapp.control.ControlServlet { + + public static final String module = ControlServlet.class.getName(); + + protected static String defaultPage = null; + protected static String pageNotFound = null; + protected static String controlServlet = null; + + public ControlServlet() { + super(); + } + + /** + * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + + ServletContext context = this.getServletContext(); + if (UtilValidate.isEmpty(defaultPage)) { + defaultPage = context.getInitParameter("defaultPage"); + } + if (UtilValidate.isEmpty(defaultPage)) { + defaultPage = "/main"; + } + if (UtilValidate.isEmpty(pageNotFound)) { + pageNotFound = context.getInitParameter("pageNotFound"); + } + if (UtilValidate.isEmpty(pageNotFound)) { + pageNotFound = "/pagenotfound"; + } + + if (defaultPage.startsWith("/") && defaultPage.lastIndexOf("/") > 0) { + controlServlet = defaultPage.substring(1); + controlServlet = controlServlet.substring(0, controlServlet.indexOf("/")); + } + } +} Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ControlServlet.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ControlServlet.java ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ControlServlet.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ProductUrlServlet.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ProductUrlServlet.java?rev=1535171&view=auto ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ProductUrlServlet.java (added) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ProductUrlServlet.java Wed Oct 23 20:48:36 2013 @@ -0,0 +1,78 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.ofbiz.product.category; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.ofbiz.entity.Delegator; +import org.ofbiz.product.category.ftl.CatalogUrlSeoTransform; + +/** + * ControlServlet.java - Master servlet for the web application. + */ +@SuppressWarnings("serial") +public class ProductUrlServlet extends HttpServlet { + + public static final String module = ProductUrlServlet.class.getName(); + public static final String PRODUCT_URL_MOUNT_POINT = "product"; + + public ProductUrlServlet() { + super(); + } + + /** + * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) + */ + @Override + public void init(ServletConfig config) throws ServletException { + super.init(config); + } + + /** + * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + doGet(request, response); + } + + /** + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Delegator delegator = (Delegator) getServletContext().getAttribute("delegator"); + CatalogUrlSeoTransform.forwardProductUri(request, response, delegator); + } + + /** + * @see javax.servlet.Servlet#destroy() + */ + @Override + public void destroy() { + super.destroy(); + } + +} Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ProductUrlServlet.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ProductUrlServlet.java ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/ProductUrlServlet.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlFilter.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlFilter.java?rev=1535171&view=auto ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlFilter.java (added) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlFilter.java Wed Oct 23 20:48:36 2013 @@ -0,0 +1,474 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.ofbiz.product.category; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import javax.servlet.FilterChain; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import javolution.util.FastList; + +import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.StringUtil; +import org.ofbiz.base.util.StringUtil.StringWrapper; +import org.ofbiz.base.util.UtilMisc; +import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.common.UrlServletHelper; +import org.ofbiz.entity.Delegator; +import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.GenericValue; +import org.ofbiz.entity.condition.EntityCondition; +import org.ofbiz.entity.util.EntityUtil; +import org.ofbiz.product.product.ProductContentWrapper; +import org.ofbiz.webapp.control.ContextFilter; + +public class SeoCatalogUrlFilter extends ContextFilter { + + public final static String module = SeoCatalogUrlFilter.class.getName(); + public static final String PRODUCT_REQUEST = "product"; + public static final String CATEGORY_REQUEST = "category"; + + protected static String defaultLocaleString = null; + protected static String redirectUrl = null; + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; + Delegator delegator = (Delegator) httpRequest.getSession().getServletContext().getAttribute("delegator"); + + // Get ServletContext + ServletContext servletContext = config.getServletContext(); + + // Set request attribute and session + UrlServletHelper.setRequestAttributes(request, delegator, servletContext); + + // set initial parameters + String initDefaultLocalesString = config.getInitParameter("defaultLocaleString"); + String initRedirectUrl = config.getInitParameter("redirectUrl"); + defaultLocaleString = UtilValidate.isNotEmpty(initDefaultLocalesString) ? initDefaultLocalesString : ""; + redirectUrl = UtilValidate.isNotEmpty(initRedirectUrl) ? initRedirectUrl : ""; + + String pathInfo = httpRequest.getServletPath(); + String alternativeUrl = ""; + if (UtilValidate.isEmpty(pathInfo)) { + pathInfo = SeoUrlUtil.removeContextPath(httpRequest.getRequestURI(), httpRequest.getContextPath()); + } + if (UtilValidate.isNotEmpty(pathInfo)) { + List<String> pathElements = StringUtil.split(pathInfo, "/"); + if (UtilValidate.isNotEmpty(pathElements)) { + alternativeUrl = pathElements.get(0); + } + } + if (UtilValidate.isNotEmpty(alternativeUrl)) { + String productId = null; + String productCategoryId = null; + String urlContentId = null; + try { + // look for productId + if (alternativeUrl.endsWith("-p")) { + List<EntityCondition> productContentConds = FastList.newInstance(); + productContentConds.add(EntityCondition.makeCondition("productContentTypeId", "ALTERNATIVE_URL")); + productContentConds.add(EntityUtil.getFilterByDateExpr()); + List<GenericValue> productContentInfos = delegator.findList("ProductContentAndInfo", EntityCondition.makeCondition(productContentConds), null, + UtilMisc.toList("-fromDate"), null, true); + if (UtilValidate.isNotEmpty(productContentInfos)) { + for (GenericValue productContentInfo : productContentInfos) { + String contentId = (String) productContentInfo.get("contentId"); + List<GenericValue> ContentAssocDataResourceViewTos = delegator.findByAnd("ContentAssocDataResourceViewTo", + UtilMisc.toMap("contentIdStart", contentId, "caContentAssocTypeId", "ALTERNATE_LOCALE", "drDataResourceTypeId", "ELECTRONIC_TEXT"), null, true); + if (UtilValidate.isNotEmpty(ContentAssocDataResourceViewTos)) { + for (GenericValue ContentAssocDataResourceViewTo : ContentAssocDataResourceViewTos) { + GenericValue ElectronicText = ContentAssocDataResourceViewTo.getRelatedOne("ElectronicText", true); + if (UtilValidate.isNotEmpty(ElectronicText)) { + String textData = (String) ElectronicText.get("textData"); + textData = UrlServletHelper.invalidCharacter(textData); + if (alternativeUrl.matches(textData + ".+$")) { + String productIdStr = null; + productIdStr = alternativeUrl.replace(textData + "-", ""); + productIdStr = productIdStr.replace("-p", ""); + String checkProductId = (String) productContentInfo.get("productId"); + if (productIdStr.equalsIgnoreCase(checkProductId)) { + productId = checkProductId; + break; + } + } + } + } + } + if (UtilValidate.isEmpty(productId)) { + List<GenericValue> contentDataResourceViews = delegator.findByAnd("ContentDataResourceView", + UtilMisc.toMap("contentId", contentId, "drDataResourceTypeId", "ELECTRONIC_TEXT"), null, true); + for (GenericValue contentDataResourceView : contentDataResourceViews) { + GenericValue ElectronicText = contentDataResourceView.getRelatedOne("ElectronicText", true); + if (UtilValidate.isNotEmpty(ElectronicText)) { + String textData = (String) ElectronicText.get("textData"); + if (UtilValidate.isNotEmpty(textData)) { + textData = UrlServletHelper.invalidCharacter(textData); + if (alternativeUrl.matches(textData + ".+$")) { + String productIdStr = null; + productIdStr = alternativeUrl.replace(textData + "-", ""); + productIdStr = productIdStr.replace("-p", ""); + String checkProductId = (String) productContentInfo.get("productId"); + if (productIdStr.equalsIgnoreCase(checkProductId)) { + productId = checkProductId; + break; + } + } + } + } + } + } + } + } + } + + // look for productCategoryId + if (alternativeUrl.endsWith("-c")) { + List<EntityCondition> productCategoryContentConds = FastList.newInstance(); + productCategoryContentConds.add(EntityCondition.makeCondition("prodCatContentTypeId", "ALTERNATIVE_URL")); + productCategoryContentConds.add(EntityUtil.getFilterByDateExpr()); + List<GenericValue> productCategoryContentInfos = delegator.findList("ProductCategoryContentAndInfo", + EntityCondition.makeCondition(productCategoryContentConds), null, UtilMisc.toList("-fromDate"), null, true); + if (UtilValidate.isNotEmpty(productCategoryContentInfos)) { + for (GenericValue productCategoryContentInfo : productCategoryContentInfos) { + String contentId = (String) productCategoryContentInfo.get("contentId"); + List<GenericValue> ContentAssocDataResourceViewTos = delegator.findByAnd("ContentAssocDataResourceViewTo", + UtilMisc.toMap("contentIdStart", contentId, "caContentAssocTypeId", "ALTERNATE_LOCALE", "drDataResourceTypeId", "ELECTRONIC_TEXT"), null, true); + if (UtilValidate.isNotEmpty(ContentAssocDataResourceViewTos)) { + for (GenericValue ContentAssocDataResourceViewTo : ContentAssocDataResourceViewTos) { + GenericValue ElectronicText = ContentAssocDataResourceViewTo.getRelatedOne("ElectronicText", true); + if (UtilValidate.isNotEmpty(ElectronicText)) { + String textData = (String) ElectronicText.get("textData"); + if (UtilValidate.isNotEmpty(textData)) { + textData = UrlServletHelper.invalidCharacter(textData); + if (alternativeUrl.matches(textData + ".+$")) { + String productCategoryStr = null; + productCategoryStr = alternativeUrl.replace(textData + "-", ""); + productCategoryStr = productCategoryStr.replace("-c", ""); + String checkProductCategoryId = (String) productCategoryContentInfo.get("productCategoryId"); + if (productCategoryStr.equalsIgnoreCase(checkProductCategoryId)) { + productCategoryId = checkProductCategoryId; + break; + } + } + } + } + } + } + if (UtilValidate.isEmpty(productCategoryId)) { + List<GenericValue> contentDataResourceViews = delegator.findByAnd("ContentDataResourceView", + UtilMisc.toMap("contentId", contentId, "drDataResourceTypeId", "ELECTRONIC_TEXT"), null, true); + for (GenericValue contentDataResourceView : contentDataResourceViews) { + GenericValue ElectronicText = contentDataResourceView.getRelatedOne("ElectronicText", true); + if (UtilValidate.isNotEmpty(ElectronicText)) { + String textData = (String) ElectronicText.get("textData"); + if (UtilValidate.isNotEmpty(textData)) { + textData = UrlServletHelper.invalidCharacter(textData); + if (alternativeUrl.matches(textData + ".+$")) { + String productCategoryStr = null; + productCategoryStr = alternativeUrl.replace(textData + "-", ""); + productCategoryStr = productCategoryStr.replace("-c", ""); + String checkProductCategoryId = (String) productCategoryContentInfo.get("productCategoryId"); + if (productCategoryStr.equalsIgnoreCase(checkProductCategoryId)) { + productCategoryId = checkProductCategoryId; + break; + } + } + } + } + } + } + } + } + } + + } catch (GenericEntityException e) { + Debug.logWarning("Cannot look for product and product category", module); + } + + // generate forward URL + StringBuilder urlBuilder = new StringBuilder(); + if (UtilValidate.isNotEmpty(SeoControlServlet.controlServlet)) { + urlBuilder.append("/" + SeoControlServlet.controlServlet); + } + + if (UtilValidate.isNotEmpty(productId)) { + try { + List<EntityCondition> conds = FastList.newInstance(); + conds.add(EntityCondition.makeCondition("productId", productId)); + conds.add(EntityUtil.getFilterByDateExpr()); + List<GenericValue> productCategoryMembers = delegator.findList("ProductCategoryMember", EntityCondition.makeCondition(conds), + UtilMisc.toSet("productCategoryId"), UtilMisc.toList("-fromDate"), null, true); + if (UtilValidate.isNotEmpty(productCategoryMembers)) { + GenericValue productCategoryMember = EntityUtil.getFirst(productCategoryMembers); + productCategoryId = productCategoryMember.getString("productCategoryId"); + } + } catch (GenericEntityException e) { + Debug.logError(e, "Cannot find product category for product: " + productId, module); + } + urlBuilder.append("/" + PRODUCT_REQUEST); + + } else { + urlBuilder.append("/" + CATEGORY_REQUEST); + } + + // generate trail belong to a top category + String topCategoryId = CategoryWorker.getCatalogTopCategory(httpRequest, null); + List<GenericValue> trailCategories = CategoryWorker.getRelatedCategoriesRet(httpRequest, "trailCategories", topCategoryId, false, false, true); + List<String> trailCategoryIds = EntityUtil.getFieldListFromEntityList(trailCategories, "productCategoryId", true); + + // look for productCategoryId from productId + if (UtilValidate.isNotEmpty(productId)) { + try { + List<EntityCondition> rolllupConds = FastList.newInstance(); + rolllupConds.add(EntityCondition.makeCondition("productId", productId)); + rolllupConds.add(EntityUtil.getFilterByDateExpr()); + List<GenericValue> productCategoryMembers = delegator.findList("ProductCategoryMember", EntityCondition.makeCondition(rolllupConds), null, + UtilMisc.toList("-fromDate"), null, true); + for (GenericValue productCategoryMember : productCategoryMembers) { + String trailCategoryId = productCategoryMember.getString("productCategoryId"); + if (trailCategoryIds.contains(trailCategoryId)) { + productCategoryId = trailCategoryId; + break; + } + } + } catch (GenericEntityException e) { + Debug.logError(e, "Cannot generate trail from product category", module); + } + } + + // generate trail elements from productCategoryId + if (UtilValidate.isNotEmpty(productCategoryId)) { + List<String> trailElements = FastList.newInstance(); + trailElements.add(productCategoryId); + String parentProductCategoryId = productCategoryId; + while (UtilValidate.isNotEmpty(parentProductCategoryId)) { + // find product category rollup + try { + List<EntityCondition> rolllupConds = FastList.newInstance(); + rolllupConds.add(EntityCondition.makeCondition("productCategoryId", parentProductCategoryId)); + rolllupConds.add(EntityUtil.getFilterByDateExpr()); + List<GenericValue> productCategoryRollups = delegator.findList("ProductCategoryRollup", EntityCondition.makeCondition(rolllupConds), null, + UtilMisc.toList("-fromDate"), null, true); + if (UtilValidate.isNotEmpty(productCategoryRollups)) { + // add only categories that belong to the top category to trail + for (GenericValue productCategoryRollup : productCategoryRollups) { + String trailCategoryId = productCategoryRollup.getString("parentProductCategoryId"); + parentProductCategoryId = trailCategoryId; + if (trailCategoryIds.contains(trailCategoryId)) { + trailElements.add(trailCategoryId); + break; + } + } + } else { + parentProductCategoryId = null; + } + } catch (GenericEntityException e) { + Debug.logError(e, "Cannot generate trail from product category", module); + } + } + Collections.reverse(trailElements); + + List<String> trail = CategoryWorker.getTrail(httpRequest); + if (trail == null) { + trail = FastList.newInstance(); + } + + // adjust trail + String previousCategoryId = null; + if (trail.size() > 0) { + previousCategoryId = trail.get(trail.size() - 1); + } + trail = CategoryWorker.adjustTrail(trail, productCategoryId, previousCategoryId); + + if (trailElements.size() == 1) { + CategoryWorker.setTrail(request, trailElements.get(0), null); + } else if (trailElements.size() == 2) { + CategoryWorker.setTrail(request, trailElements.get(1), trailElements.get(0)); + } else if (trailElements.size() > 2) { + if (trail.contains(trailElements.get(0))) { + // first category is in the trail, so remove it everything after that and fill it in with the list from the pathInfo + int firstElementIndex = trail.indexOf(trailElements.get(0)); + while (trail.size() > firstElementIndex) { + trail.remove(firstElementIndex); + } + trail.addAll(trailElements); + } else { + // first category is NOT in the trail, so clear out the trail and use the trailElements list + trail.clear(); + trail.addAll(trailElements); + } + CategoryWorker.setTrail(request, trail); + } + + request.setAttribute("productCategoryId", productCategoryId); + + if (productId != null) { + request.setAttribute("product_id", productId); + request.setAttribute("productId", productId); + } + } + + // Set view query parameters + UrlServletHelper.setViewQueryParameters(request, urlBuilder); + if (UtilValidate.isNotEmpty(productId) || UtilValidate.isNotEmpty(productCategoryId) || UtilValidate.isNotEmpty(urlContentId)) { + Debug.logInfo("[Filtered request]: " + pathInfo + " (" + urlBuilder + ")", module); + RequestDispatcher dispatch = request.getRequestDispatcher(urlBuilder.toString()); + dispatch.forward(request, response); + return; + } + + // Check path alias + UrlServletHelper.checkPathAlias(request, httpResponse, delegator, pathInfo); + } + + // we're done checking; continue on + chain.doFilter(request, response); + } + + public static String makeCategoryUrl(HttpServletRequest request, String previousCategoryId, String productCategoryId, String productId, String viewSize, String viewIndex, + String viewSort, String searchString) { + Delegator delegator = (Delegator) request.getAttribute("delegator"); + try { + GenericValue productCategory = delegator.findOne("ProductCategory", UtilMisc.toMap("productCategoryId", productCategoryId), true); + CategoryContentWrapper wrapper = new CategoryContentWrapper(productCategory, request); + List<String> trail = CategoryWorker.getTrail(request); + return makeCategoryUrl(delegator, wrapper, trail, request.getSession().getServletContext().getContextPath(), previousCategoryId, productCategoryId, productId, + viewSize, viewIndex, viewSort, searchString); + } catch (GenericEntityException e) { + Debug.logWarning(e, "Cannot create category's URL for: " + productCategoryId, module); + return redirectUrl; + } + } + + public static String makeCategoryUrl(Delegator delegator, CategoryContentWrapper wrapper, List<String> trail, String contextPath, String previousCategoryId, + String productCategoryId, String productId, String viewSize, String viewIndex, String viewSort, String searchString) { + String url = ""; + StringWrapper alternativeUrl = wrapper.get("ALTERNATIVE_URL"); + + if (UtilValidate.isNotEmpty(alternativeUrl) && UtilValidate.isNotEmpty(alternativeUrl.toString())) { + StringBuilder urlBuilder = new StringBuilder(); + urlBuilder.append(contextPath); + if (urlBuilder.charAt(urlBuilder.length() - 1) != '/') { + urlBuilder.append("/"); + } + // append alternative URL + url = UrlServletHelper.invalidCharacter(alternativeUrl.toString()); + urlBuilder.append(url); + if (UtilValidate.isNotEmpty(productCategoryId)) { + urlBuilder.append("-"); + urlBuilder.append(productCategoryId); + urlBuilder.append("-c"); + } + // append view index + if (UtilValidate.isNotEmpty(viewIndex)) { + if (!urlBuilder.toString().endsWith("?") && !urlBuilder.toString().endsWith("&")) { + urlBuilder.append("?"); + } + urlBuilder.append("viewIndex=" + viewIndex + "&"); + } + // append view size + if (UtilValidate.isNotEmpty(viewSize)) { + if (!urlBuilder.toString().endsWith("?") && !urlBuilder.toString().endsWith("&")) { + urlBuilder.append("?"); + } + urlBuilder.append("viewSize=" + viewSize + "&"); + } + // append view sort + if (UtilValidate.isNotEmpty(viewSort)) { + if (!urlBuilder.toString().endsWith("?") && !urlBuilder.toString().endsWith("&")) { + urlBuilder.append("?"); + } + urlBuilder.append("viewSort=" + viewSort + "&"); + } + // append search string + if (UtilValidate.isNotEmpty(searchString)) { + if (!urlBuilder.toString().endsWith("?") && !urlBuilder.toString().endsWith("&")) { + urlBuilder.append("?"); + } + urlBuilder.append("searchString=" + searchString + "&"); + } + if (urlBuilder.toString().endsWith("&")) { + return urlBuilder.toString().substring(0, urlBuilder.toString().length() - 1); + } + + url = urlBuilder.toString(); + } else { + if (UtilValidate.isEmpty(trail)) { + trail = FastList.newInstance(); + } + url = SeoCatalogUrlServlet.makeCatalogUrl(contextPath, trail, productId, productCategoryId, previousCategoryId); + } + + return url; + } + + public static String makeProductUrl(HttpServletRequest request, String previousCategoryId, String productCategoryId, String productId) { + Delegator delegator = (Delegator) request.getAttribute("delegator"); + String url = null; + try { + GenericValue product = delegator.findOne("Product", UtilMisc.toMap("productId", productId), true); + ProductContentWrapper wrapper = new ProductContentWrapper(product, request); + List<String> trail = CategoryWorker.getTrail(request); + url = makeProductUrl(delegator, wrapper, trail, request.getSession().getServletContext().getContextPath(), previousCategoryId, productCategoryId, productId); + } catch (GenericEntityException e) { + Debug.logWarning(e, "Cannot create product's URL for: " + productId, module); + return redirectUrl; + } + return url; + } + + public static String makeProductUrl(Delegator delegator, ProductContentWrapper wrapper, List<String> trail, String contextPath, String previousCategoryId, + String productCategoryId, String productId) { + String url = ""; + StringWrapper alternativeUrl = wrapper.get("ALTERNATIVE_URL"); + if (UtilValidate.isNotEmpty(alternativeUrl) && UtilValidate.isNotEmpty(alternativeUrl.toString())) { + StringBuilder urlBuilder = new StringBuilder(); + urlBuilder.append(contextPath); + if (urlBuilder.charAt(urlBuilder.length() - 1) != '/') { + urlBuilder.append("/"); + } + // append alternative URL + url = UrlServletHelper.invalidCharacter(alternativeUrl.toString()); + urlBuilder.append(url); + if (UtilValidate.isNotEmpty(productId)) { + urlBuilder.append("-"); + urlBuilder.append(productId); + urlBuilder.append("-p"); + } + url = urlBuilder.toString(); + } else { + if (UtilValidate.isEmpty(trail)) { + trail = FastList.newInstance(); + } + url = SeoCatalogUrlServlet.makeCatalogUrl(contextPath, trail, productId, productCategoryId, previousCategoryId); + } + return url; + } +} Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlFilter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlFilter.java ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlFilter.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlServlet.java URL: http://svn.apache.org/viewvc/ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlServlet.java?rev=1535171&view=auto ============================================================================== --- ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlServlet.java (added) +++ ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlServlet.java Wed Oct 23 20:48:36 2013 @@ -0,0 +1,206 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.ofbiz.product.category; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import javolution.util.FastList; + +import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.StringUtil; +import org.ofbiz.base.util.UtilMisc; +import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.entity.Delegator; +import org.ofbiz.entity.GenericEntityException; + +/** + * SeoCatalogUrlServlet.java + */ +@SuppressWarnings("serial") +public class SeoCatalogUrlServlet extends HttpServlet { + + public static final String module = SeoCatalogUrlServlet.class.getName(); + public static final String CATALOG_URL_MOUNT_POINT = "products"; + public static final String PRODUCT_REQUEST = "product"; + public static final String CATEGORY_REQUEST = "category"; + + public SeoCatalogUrlServlet() { + super(); + } + + /** + * @see javax.servlet.http.HttpServlet#init(javax.servlet.ServletConfig) + */ + @Override + public void init(ServletConfig config) throws ServletException { + super.init(config); + } + + /** + * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + doGet(request, response); + } + + /** + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + Delegator delegator = (Delegator) getServletContext().getAttribute("delegator"); + + String pathInfo = request.getPathInfo(); + List<String> pathElements = StringUtil.split(pathInfo, "/"); + + // look for productId + String productId = null; + try { + String lastPathElement = pathElements.get(pathElements.size() - 1); + if (lastPathElement.startsWith("p_") || delegator.findOne("Product", UtilMisc.toMap("productId", lastPathElement), true) != null) { + if (lastPathElement.startsWith("p_")) { + productId = lastPathElement.substring(2); + } else { + productId = lastPathElement; + } + pathElements.remove(pathElements.size() - 1); + } + } catch (GenericEntityException e) { + Debug.logError(e, "Error looking up product info for ProductUrl with path info [" + pathInfo + "]: " + e.toString(), module); + } + + // get category info going with the IDs that remain + String categoryId = null; + if (pathElements.size() == 1) { + CategoryWorker.setTrail(request, pathElements.get(0), null); + categoryId = pathElements.get(0); + } else if (pathElements.size() == 2) { + CategoryWorker.setTrail(request, pathElements.get(1), pathElements.get(0)); + categoryId = pathElements.get(1); + } else if (pathElements.size() > 2) { + List<String> trail = CategoryWorker.getTrail(request); + if (trail == null) { + trail = FastList.newInstance(); + } + + if (trail.contains(pathElements.get(0))) { + // first category is in the trail, so remove it everything after that and fill it in with the list from the pathInfo + int firstElementIndex = trail.indexOf(pathElements.get(0)); + while (trail.size() > firstElementIndex) { + trail.remove(firstElementIndex); + } + trail.addAll(pathElements); + } else { + // first category is NOT in the trail, so clear out the trail and use the pathElements list + trail.clear(); + trail.addAll(pathElements); + } + CategoryWorker.setTrail(request, trail); + categoryId = pathElements.get(pathElements.size() - 1); + } + if (categoryId != null) { + request.setAttribute("productCategoryId", categoryId); + } + + String rootCategoryId = null; + if (pathElements.size() >= 1) { + rootCategoryId = pathElements.get(0); + } + if (rootCategoryId != null) { + request.setAttribute("rootCategoryId", rootCategoryId); + } + + if (productId != null) { + request.setAttribute("product_id", productId); + request.setAttribute("productId", productId); + } + + RequestDispatcher rd = request.getRequestDispatcher("/" + (UtilValidate.isEmpty(SeoControlServlet.controlServlet) ? "" : (SeoControlServlet.controlServlet + "/")) + + (productId != null ? PRODUCT_REQUEST : CATEGORY_REQUEST)); + rd.forward(request, response); + } + + /** + * @see javax.servlet.http.HttpServlet#destroy() + */ + @Override + public void destroy() { + super.destroy(); + } + + public static String makeCatalogUrl(HttpServletRequest request, String productId, String currentCategoryId, String previousCategoryId) { + StringBuilder urlBuilder = new StringBuilder(); + urlBuilder.append(request.getSession().getServletContext().getContextPath()); + if (urlBuilder.charAt(urlBuilder.length() - 1) != '/') { + urlBuilder.append("/"); + } + urlBuilder.append(CATALOG_URL_MOUNT_POINT); + + if (UtilValidate.isNotEmpty(currentCategoryId)) { + List<String> trail = CategoryWorker.getTrail(request); + trail = CategoryWorker.adjustTrail(trail, currentCategoryId, previousCategoryId); + for (String trailCategoryId : trail) { + if ("TOP".equals(trailCategoryId)) continue; + urlBuilder.append("/"); + urlBuilder.append(trailCategoryId); + } + } + + if (UtilValidate.isNotEmpty(productId)) { + urlBuilder.append("/p_"); + urlBuilder.append(productId); + } + + return urlBuilder.toString(); + } + + public static String makeCatalogUrl(String contextPath, List<String> crumb, String productId, String currentCategoryId, String previousCategoryId) { + StringBuilder urlBuilder = new StringBuilder(); + urlBuilder.append(contextPath); + if (urlBuilder.charAt(urlBuilder.length() - 1) != '/') { + urlBuilder.append("/"); + } + urlBuilder.append(CATALOG_URL_MOUNT_POINT); + + if (UtilValidate.isNotEmpty(currentCategoryId)) { + crumb = CategoryWorker.adjustTrail(crumb, currentCategoryId, previousCategoryId); + for (String trailCategoryId : crumb) { + if ("TOP".equals(trailCategoryId)) continue; + urlBuilder.append("/"); + urlBuilder.append(trailCategoryId); + } + } + + if (UtilValidate.isNotEmpty(productId)) { + urlBuilder.append("/p_"); + urlBuilder.append(productId); + } + + return urlBuilder.toString(); + } +} Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlServlet.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlServlet.java ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/branches/OFBIZ-5312-ofbiz-ecommerce-seo-2013-10-23/applications/product/src/org/ofbiz/product/category/SeoCatalogUrlServlet.java ------------------------------------------------------------------------------ svn:mime-type = text/plain |
Free forum by Nabble | Edit this page |