View Javadoc
1   /**
2    * This file Copyright (c) 2003-2017 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.cms.beans.config;
35  
36  import info.magnolia.context.MgnlContext;
37  import info.magnolia.context.WebContext;
38  
39  import java.util.ArrayList;
40  import java.util.Iterator;
41  import java.util.List;
42  
43  import org.apache.commons.lang3.StringUtils;
44  
45  /**
46   * Simple VirtualURI mapping that can forward to a different url depending on the request host name. The "mappings" node
47   * contains a list of nodes with "host" and "toURI" properties.
48   * See below for a sample configuration:
49   *
50   * <pre>
51   * [] virtualURIMapping
52   *    [] default
53   *     - class            info.magnolia.cms.beans.config.HostBasedVirtualURIMapping
54   *     - fromURI          /
55   *     - toURI            redirect:/.magnolia/pages/adminCentral.html
56   *       [] mappings
57   *        - [] com
58   *          - host      www.acme.com
59   *          - toURI     forward:/acme/en/index.html
60   *        - [] de
61   *          - host      www.acme.de
62   *          - toURI     forward:/acme/de/index.html
63   * </pre>
64   *
65   * For backwards compatibility The "host" property may still be used, it contains
66   * a list of uri=destination strings.
67   * This technique is deprecated primarily because the properties of a node do not have a deterministic order.
68   * See below for a sample configuration of the deprecated approach using 'hosts' node.:
69   *
70   * <pre>
71   * [] virtualURIMapping
72   *    [] default
73   *     - class            info.magnolia.cms.beans.config.HostBasedVirtualURIMapping
74   *     - fromURI          /
75   *     - toURI            redirect:/.magnolia/pages/adminCentral.html
76   *       [] hosts
77   *        - 1             www.acme.com=forward:/acme/en/index.html
78   *        - 2             www.acme.de=forward:/acme/de/index.html
79   * </pre>
80   *
81   * @deprecated since 5.5.6, host based URI mapping has been relocated to the virtual-uri module (see MAGNOLIA-7016).
82   */
83  @Deprecated
84  public class HostBasedVirtualURIMapping extends DefaultVirtualURIMapping {
85  
86      protected ArrayList<HostURIMapping> hosts;
87  
88      /**
89       *
90       */
91      public HostBasedVirtualURIMapping() {
92          hosts = new ArrayList<HostURIMapping>();
93      }
94  
95      // required by content2bean in order to make addMapping work, do not remove!
96      public List<HostURIMapping> getMappings() {
97          return null;
98      }
99  
100     /**
101      * Adds a mapping (used by content2bean).
102      *
103      * @param mapping object.
104      */
105     public void addMapping(HostURIMapping mapping) {
106         if (mapping.getHost() != null && mapping.getToURI() != null) {
107             synchronized (hosts) {
108                 hosts.add(mapping);
109             }
110         }
111     }
112 
113     // required by content2bean in order to make addHost work, do not remove!
114     // @Deprecated since 4.5.18, content2bean mechanism will recognize getMappings() method to call the addMapping method.
115     @Deprecated
116     public List<String> getHosts() {
117         return null;
118     }
119 
120 
121     /**
122      * @param mapping in the form host=path
123      * @Deprecated since 4.5.18, Use {@link #addMapping(HostURIMapping))} instead.
124      * Adds a host mapping (used by content2bean).
125      */
126     @Deprecated
127     public void addHost(String mapping) {
128         String[] hostToPath = StringUtils.split(mapping, "=");
129         if (hostToPath != null && hostToPath.length == 2) {
130             synchronized (hosts) {
131                 hosts.add(new HostURIMapping(hostToPath[0], hostToPath[1]));
132             }
133         }
134     }
135 
136     @Override
137     public MappingResult mapURI(String uri) {
138 
139         MappingResult result = super.mapURI(uri);
140 
141         if (result != null) {
142             String destination = toURI;
143             String hostMapping = this.tryToMapHost();
144             if (hostMapping != null) {
145                 destination = hostMapping;
146             }
147             result.setToURI(destination);
148             return result;
149         }
150 
151         return null;
152     }
153 
154     /**
155      * Choose the mapping host that matches the request host, with the least number of additional characters.
156      *
157      * @return The URI to map to.
158      */
159     protected String tryToMapHost() {
160         final int NO_MATCHED_MAPPINGS = -1;
161         int bestMatchValue = NO_MATCHED_MAPPINGS;
162         String toURI = null;
163 
164         if (hosts != null && !hosts.isEmpty()) {
165             String requestHost = ((WebContext) MgnlContext.getInstance()).getRequest().getServerName();
166 
167             Iterator<HostURIMapping> hostIt = hosts.iterator();
168 
169             while (hostIt.hasNext()) {
170                 HostURIMapping hk = hostIt.next();
171                 if (requestHost.endsWith(hk.getHost())) {
172                     int matchValue = (requestHost.length() - hk.getHost().length());
173                     if (bestMatchValue == NO_MATCHED_MAPPINGS || matchValue < bestMatchValue) {
174                         bestMatchValue = matchValue;
175                         toURI = hk.getToURI();
176                     }
177                 }
178             }
179         }
180         return toURI;
181     }
182 
183     @Override
184     public String toString() {
185         return "[" + super.toString() + "[hosts:" + hosts.toString() + "]]";
186     }
187 
188     @Override
189     public boolean isValid() {
190         if (this.getClass().equals(HostBasedVirtualURIMapping.class)) {
191             return StringUtils.isNotEmpty(fromURI) && StringUtils.isNotEmpty(toURI);
192         }
193 
194         return true;
195     }
196 
197     /**
198      * HostURIMapping object to receive "mapping" nodes in configuration.
199      */
200     public static class HostURIMapping {
201 
202         // Empty constructor required for content2bean.
203         public HostURIMapping() {
204         }
205 
206         public HostURIMapping(String host, String toURI) {
207             this.host = host;
208             this.toURI = toURI;
209         }
210 
211         private String host;
212 
213         private String toURI;
214 
215         public String getHost() {
216             return this.host;
217         }
218 
219         public void setHost(String host) {
220             this.host = host;
221         }
222 
223         public String getToURI() {
224             return this.toURI;
225         }
226 
227         public void setToURI(String toURI) {
228             this.toURI = toURI;
229         }
230 
231         @Override
232         public String toString() {
233             return getHost() + "=" + getToURI();
234 
235         }
236     }
237 
238 }