001: /*
002: * $Id: PrependContextPathHandler.java 461655 2006-07-30 12:37:49Z jdonnerstag $
003: * $Revision: 461655 $ $Date: 2006-07-30 14:37:49 +0200 (Sun, 30 Jul 2006) $
004: *
005: * ==============================================================================
006: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
007: * use this file except in compliance with the License. You may obtain a copy of
008: * the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations under
016: * the License.
017: */
018: package wicket.markup.parser.filter;
019:
020: import java.text.ParseException;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024:
025: import wicket.Application;
026: import wicket.markup.ComponentTag;
027: import wicket.markup.MarkupElement;
028: import wicket.markup.parser.AbstractMarkupFilter;
029:
030: /**
031: * This is a markup inline filter which by default is added to the list of
032: * markup filters. It can be added by means of subclassing
033: * Application.newMarkupParser() like
034: *
035: * <pre>
036: * public class MyApplication extends Application
037: * {
038: * ...
039: * public IMarkupFilter[] getAdditionalMarkupHandler()
040: * {
041: * return new IMarkupFilter[] { new new PrependContextPathHandler() };
042: * }
043: * </pre>
044: *
045: * The purpose of the filter is to prepend the web apps context path to all href
046: * and src attributes found in the markup which contain a relative URL like
047: * "myDir/myPage.gif". It is applied to all non wicket component tags (attributes).
048: *
049: * @author Juergen Donnerstag
050: */
051: public final class PrependContextPathHandler extends
052: AbstractMarkupFilter {
053: /** Logging */
054: private static final Log log = LogFactory
055: .getLog(PrependContextPathHandler.class);
056:
057: /** List of attribute names considered */
058: private static final String attributeNames[] = new String[] {
059: "href", "src" };
060:
061: private final Application application;
062:
063: /**
064: * This constructor will get the context path from the application settings.
065: * When it is not set the context path will be automatically resolved.
066: * This should work in most cases, and support the following clustering
067: * scheme
068: *
069: * <pre>
070: * node1.mydomain.com[/appcontext]
071: * node2.mydomain.com[/appcontext]
072: * node3.mydomain.com[/appcontext]
073: * </pre>
074: *
075: * If it is set then you can map to other context like in clusters
076: *
077: * <pre>
078: * node1.mydomain.com/mycontext1/
079: * node2.mydomain.com/mycontext2/
080: * node3.mydomain.com/mycontext3/
081: * mydomain.com/mycontext (load balancer)
082: * </pre>
083: *
084: * or as a virtual server (app server and webserver)
085: *
086: * <pre>
087: * appserver.com/context mapped to webserver/ (context path should be '/')
088: * </pre>
089: *
090: * @param application The application object
091: *
092: */
093: public PrependContextPathHandler(final Application application) {
094: this .application = application;
095: }
096:
097: /**
098: * Get the next MarkupElement from the parent MarkupFilter and handle it if
099: * the specific filter criteria are met. Depending on the filter, it may
100: * return the MarkupElement unchanged, modified or it remove by asking the
101: * parent handler for the next tag.
102: *
103: * @see wicket.markup.parser.IMarkupFilter#nextTag()
104: * @return Return the next eligible MarkupElement
105: */
106: public MarkupElement nextTag() throws ParseException {
107: // Get the next tag. If null, no more tags are available
108: final ComponentTag tag = (ComponentTag) getParent().nextTag();
109: if (tag == null || tag.getId() != null) {
110: return tag;
111: }
112:
113: // Don't touch any wicket:id component
114: if (tag.getId() != null) {
115: return tag;
116: }
117:
118: // this call should always get the default of the application or the overriden one.
119: String contextPath = application.getApplicationSettings()
120: .getContextPath();
121: if (contextPath == null) {
122: contextPath = "";
123: } else if (contextPath.endsWith("/") == false) {
124: contextPath += "/";
125: }
126:
127: if (contextPath.length() > 0) {
128: // Modify all relevant attributes
129: for (int i = 0; i < attributeNames.length; i++) {
130: String attrName = attributeNames[i];
131: String attrValue = tag.getAttributes().getString(
132: attrName);
133: if ((attrValue != null)
134: && (attrValue.startsWith("/") == false)
135: && (attrValue.indexOf(":") < 0)
136: && !(attrValue.startsWith("#"))) {
137: String url = contextPath + attrValue;
138: tag.getAttributes().put(attrName, url);
139: tag.setModified(true);
140: }
141: }
142: }
143:
144: return tag;
145: }
146: }
|