001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.framework.basic;
011:
012: import org.mmbase.framework.*;
013: import java.util.*;
014: import javax.servlet.http.HttpServletRequest;
015: import org.mmbase.util.functions.*;
016: import org.mmbase.util.logging.Logger;
017: import org.mmbase.util.logging.Logging;
018:
019: /**
020: * The UrlConverter which deals in urls and filters links that start with '/mmbase/'.
021: *
022: *
023: * @author Michiel Meeuwissen
024: * @version $Id: MMBaseUrlConverter.java,v 1.4 2008/02/22 14:05:57 michiel Exp $
025: * @since MMBase-1.9
026: */
027: public class MMBaseUrlConverter implements UrlConverter {
028: private static final Logger log = Logging
029: .getLoggerInstance(MMBaseUrlConverter.class);
030:
031: /**
032: * MMBaseUrlConverter points to a jsp which renders 1 block. This parameter indicates of which component.
033: */
034: public static final Parameter<String> COMPONENT = new Parameter<String>(
035: "component", String.class);
036:
037: /**
038: * MMBaseUrlConverter points to a jsp which renders 1 block. This parameter indicates its name.
039: */
040: public static final Parameter<String> BLOCK = new Parameter<String>(
041: "block", String.class);
042:
043: /**
044: * MMBaseUrlConverter wants a 'category'.
045: */
046: public static final Parameter<String> CATEGORY = new Parameter<String>(
047: "category", String.class);
048:
049: private final BasicFramework framework;
050:
051: protected String dir = "/mmbase/";
052:
053: public MMBaseUrlConverter(BasicFramework fw) {
054: framework = fw;
055: }
056:
057: public void setDir(String d) {
058: dir = d;
059: }
060:
061: public Parameter[] getParameterDefinition() {
062: return new Parameter[] { CATEGORY, COMPONENT, BLOCK };
063: }
064:
065: protected String getUrl(String path,
066: Map<String, Object> parameters,
067: Parameters frameworkParameters, boolean escapeAmps,
068: boolean action) {
069: if (log.isDebugEnabled()) {
070: log.debug("path '" + path + "' parameters: " + parameters
071: + " framework parameters " + frameworkParameters);
072: }
073: HttpServletRequest request = frameworkParameters
074: .get(Parameter.REQUEST);
075: State state = State.getState(request);
076:
077: String category = frameworkParameters.get(CATEGORY);
078: if (category == null && state.isRendering()) {
079: category = state.getFrameworkParameters().get(CATEGORY);
080: }
081:
082: // MMBase urls always shows only one block
083: Component component = ComponentRepository.getInstance()
084: .getComponent(frameworkParameters.get(COMPONENT));
085: if (component == null) {
086: // if no explicit component specified, suppose current component, if there is one:
087: if (state.isRendering()) {
088: component = state.getBlock().getComponent();
089: } else {
090: log
091: .debug("No rendering state object found, so no current component.");
092: if (category != null) {
093: log.debug("Found category " + category);
094: return dir + category;
095: } else {
096: return null;
097: }
098: }
099: }
100:
101: assert component != null;
102:
103: boolean filteredMode = FrameworkFilter.getPath(request)
104: .startsWith(dir);
105:
106: if (state.isRendering()
107: && (!filteredMode || state.getDepth() > 0)) {
108: log
109: .debug("we are rendering a sub-component, deal with that as if no mmbaseurlconverter. "
110: + filteredMode);
111: return null;
112: }
113:
114: Block block;
115: { // determin the block:
116: String blockParam = frameworkParameters.get(BLOCK);
117: if (blockParam != null) {
118: if (log.isDebugEnabled()) {
119: log.debug("found block " + blockParam
120: + " trying it on " + component);
121: }
122:
123: if (path != null && !"".equals(path))
124: throw new IllegalArgumentException(
125: "Cannot use both 'path' argument and 'block' parameter");
126: block = component.getBlock(blockParam);
127: if (block == null)
128: throw new IllegalArgumentException("No block '"
129: + blockParam + "' found in component '"
130: + component + "'");
131: } else {
132: block = component.getBlock(path);
133: if (block != null) {
134: if (!filteredMode) {
135: path = null; // used, determin path with block name
136: }
137: } else {
138: // no such block
139: if (path != null && !"".equals(path)) {
140: log.debug("No block '" + path + "' found");
141: return null;
142: }
143: }
144: if (block == null) {
145: if (state.isRendering()) {
146: // current block
147: block = state.getRenderer().getBlock();
148: } else {
149: // default block
150: block = component.getDefaultBlock();
151: }
152: }
153: }
154: }
155:
156: assert block != null;
157:
158: Map<String, Object> map = new TreeMap<String, Object>();
159: if (log.isDebugEnabled()) {
160: log.debug("Creating URL to component " + component
161: + " generating URL to " + block + " State " + state
162: + " category " + category);
163: }
164: boolean processUrl = Boolean.TRUE.equals(frameworkParameters
165: .get("process"));
166: if (processUrl) {
167: // get current components ids
168: if (state.isRendering()) {
169: map.put("action", state.getId());
170: } else {
171: map.put("action", state.getUpcomingId());
172: }
173: }
174:
175: if (!processUrl && state.isRendering()) {
176: // copy all current parameters of the request.
177: for (Object e : request.getParameterMap().entrySet()) {
178: Map.Entry<String, String[]> entry = (Map.Entry<String, String[]>) e;
179: String k = entry.getKey();
180: if (k.equals(BLOCK.getName()))
181: continue;
182: if (k.equals(COMPONENT.getName()))
183: continue;
184: if (k.equals(CATEGORY.getName()))
185: continue;
186: map.put(k, entry.getValue()[0]);
187: }
188: } else {
189: //log.debug("Now processing " + processor);
190: }
191:
192: if (!processUrl) {
193: Parameters blockParameters = block.createParameters();
194: for (Map.Entry<String, Object> entry : parameters
195: .entrySet()) {
196: blockParameters.set(entry.getKey(), entry.getValue());
197: }
198: map
199: .putAll(framework.prefix(state, blockParameters
200: .toMap()));
201: }
202:
203: // TODO, if no category specified somehow, then guess when, using the avaiable
204: // classifications for the specified block.
205:
206: if (category == null) {
207: Block.Type[] classification = block.getClassification();
208: }
209: //boolean subComponent = state.getDepth() > 0;
210:
211: String page;
212: if (state.isRendering() && state.getBlock().equals(block)) {
213: page = FrameworkFilter.getPath(request);
214: } else {
215: page = dir + (category == null ? "_" : category) + "/"
216: + component.getName() + "/" + block.getName();
217: }
218:
219: //path == null || subComponent ?
220:
221: String sb = BasicUrlConverter.getUrl(page, map, request,
222: escapeAmps);
223: return sb;
224: }
225:
226: public String getUrl(String path, Map<String, Object> parameters,
227: Parameters frameworkParameters, boolean escapeAmps) {
228: return getUrl(path, parameters, frameworkParameters,
229: escapeAmps, false);
230: }
231:
232: public String getProcessUrl(String path,
233: Map<String, Object> parameters,
234: Parameters frameworkParameters, boolean escapeAmps) {
235: return getUrl(path, parameters, frameworkParameters,
236: escapeAmps, true);
237: }
238:
239: public String getInternalUrl(String page,
240: Map<String, Object> params, Parameters frameworkParameters) {
241: HttpServletRequest request = frameworkParameters
242: .get(Parameter.REQUEST);
243: if (page == null)
244: throw new IllegalArgumentException();
245: if (page.startsWith(dir)) {
246: String sp = FrameworkFilter.getPath(request);
247: String[] path = sp.split("/");
248: if (log.isDebugEnabled()) {
249: log.debug("Going to filter " + Arrays.asList(path));
250: }
251: if (path.length >= 3) {
252: assert path[0].equals("");
253: assert path[1].equals(dir.split("/")[1]);
254: String category = path[2];
255: if (!category.equals("_")) {
256: boolean categoryOk = false;
257: for (Block.Type rootType : ComponentRepository
258: .getInstance().getBlockClassification(
259: "mmbase")[0].getSubTypes()) {
260: categoryOk = rootType.getName()
261: .equals(category);
262: if (categoryOk)
263: break;
264: }
265: if (!categoryOk) {
266: log
267: .debug("No such component clasification, ignoring this");
268: return null;
269: }
270: }
271:
272: StringBuilder url = new StringBuilder(
273: "/mmbase/admin/index.jsp?category=");
274: url.append(category);
275:
276: if (path.length == 3)
277: return url.toString();
278:
279: Component comp = ComponentRepository.getInstance()
280: .getComponent(path[3]);
281: if (comp == null) {
282: log.debug("No such component, ignoring this too");
283: return null;
284: }
285: url.append("&component=").append(comp.getName());
286:
287: if (path.length == 4)
288: return url.toString();
289:
290: Block block = comp.getBlock(path[4]);
291: if (log.isDebugEnabled()) {
292: log.debug("Will try to display " + block);
293: }
294: if (block == null) {
295: log.debug("No block " + path[4] + " in component "
296: + path[3]);
297: return null;
298:
299: }
300: url.append("&block=").append(block.getName());
301: if (log.isDebugEnabled()) {
302: log.debug("internal URL " + url);
303: }
304: return url.toString();
305: } else {
306: log.debug("path length " + path.length);
307: return null;
308: }
309: } else {
310: log.debug("Leaving unfiltered");
311: return null;
312: }
313: }
314:
315: public String toString() {
316: return dir;
317: }
318:
319: }
|