diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml index 1c8e079b01..1a04728ce1 100644 --- a/apps/showcase/pom.xml +++ b/apps/showcase/pom.xml @@ -68,12 +68,6 @@ struts2-json-plugin - - org.apache.tiles - tiles-jsp - runtime - - org.apache.struts struts2-convention-plugin diff --git a/bom/pom.xml b/bom/pom.xml index c4ffbaf5ea..6a97573828 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -24,8 +24,8 @@ org.apache.struts - struts-master - 14 + struts2-parent + 6.3.0-SNAPSHOT struts2-bom diff --git a/plugins/portlet-tiles/pom.xml b/plugins/portlet-tiles/pom.xml index 60631ebc6d..7caba14429 100644 --- a/plugins/portlet-tiles/pom.xml +++ b/plugins/portlet-tiles/pom.xml @@ -40,10 +40,6 @@ org.apache.struts struts2-portlet-plugin - - org.apache.tiles - tiles-request-portlet - javax.servlet.jsp jsp-api @@ -55,9 +51,9 @@ provided - org.apache.tiles - tiles-jsp - runtime + org.easymock + easymock + test diff --git a/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java b/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java index 82249ccc90..ef1f82f76d 100644 --- a/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java +++ b/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java @@ -22,9 +22,9 @@ import org.apache.struts2.portlet.PortletConstants; import org.apache.struts2.portlet.context.PortletActionContext; import org.apache.struts2.result.ServletDispatcherResult; -import org.apache.tiles.TilesContainer; -import org.apache.tiles.TilesException; -import org.apache.tiles.access.TilesAccess; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.TilesException; +import org.apache.tiles.api.access.TilesAccess; import org.apache.tiles.request.ApplicationContext; import org.apache.tiles.request.Request; import org.apache.tiles.request.portlet.RenderPortletRequest; diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/PortletRequest.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/PortletRequest.java new file mode 100644 index 0000000000..6946776e44 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/PortletRequest.java @@ -0,0 +1,344 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet; + +import org.apache.tiles.request.AbstractClientRequest; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.attribute.Addable; +import org.apache.tiles.request.collection.HeaderValuesMap; +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.portlet.delegate.RequestDelegate; +import org.apache.tiles.request.portlet.delegate.ResponseDelegate; +import org.apache.tiles.request.portlet.extractor.HeaderExtractor; +import org.apache.tiles.request.portlet.extractor.RequestScopeExtractor; +import org.apache.tiles.request.portlet.extractor.SessionScopeExtractor; + +import javax.portlet.PortletContext; +import javax.portlet.PortletException; +import javax.portlet.PortletRequestDispatcher; +import javax.portlet.PortletResponse; +import javax.portlet.PortletSession; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * Portlet-based TilesApplicationContext implementation. + */ +public class PortletRequest extends AbstractClientRequest { + + /** + * The native available scopes. + */ + private static final List SCOPES = Collections.unmodifiableList(Arrays.asList(REQUEST_SCOPE, "portletSession", "session", APPLICATION_SCOPE)); + + /** + *

The lazily instantiated Map of header name-value + * combinations (immutable).

+ */ + private Map header = null; + + + /** + *

The lazily instantiated Map of header name-value + * combinations (write-only).

+ */ + private Addable responseHeaders = null; + + + /** + *

The lazily instantiated Map of header name-values + * combinations (immutable).

+ */ + private Map headerValues = null; + + /** + * The PortletContext for this application. + */ + protected PortletContext context; + + /** + *

The PortletRequest for this request.

+ */ + protected javax.portlet.PortletRequest request; + + /** + * The delegate to get information about parameters. + */ + protected RequestDelegate requestDelegate; + + + /** + *

The lazily instantiated Map of request scope + * attributes.

+ */ + private Map requestScope = null; + + + /** + *

The PortletResponse for this request.

+ */ + protected PortletResponse response; + + /** + * The delegate to get information from a response (output stream, writer, etc.). + */ + protected ResponseDelegate responseDelegate; + + + /** + *

The lazily instantiated Map of session scope + * attributes.

+ */ + private Map sessionScope = null; + + /** + *

The lazily instantiated Map of portlet session scope + * attributes.

+ */ + private Map portletSessionScope = null; + + + /** + * Creates a new instance of PortletTilesRequestContext. + * + * @param applicationContext The Tiles application context. + * @param context The portlet context to use. + * @param request The request object to use. + * @param response The response object to use. + * @param requestDelegate The request delegate. + * @param responseDelegate The response delegate. + */ + public PortletRequest(ApplicationContext applicationContext, + PortletContext context, javax.portlet.PortletRequest request, + PortletResponse response, RequestDelegate requestDelegate, ResponseDelegate responseDelegate) { + super(applicationContext); + + // Save the specified Portlet API object references + this.context = context; + this.request = request; + this.response = response; + this.requestDelegate = requestDelegate; + this.responseDelegate = responseDelegate; + } + + /** + *

Return the {@link PortletRequest} for this context.

+ * + * @return The used portlet request. + */ + public javax.portlet.PortletRequest getRequest() { + return (this.request); + } + + /** + * Returns the portlet context. + * + * @return The portlet context. + */ + public PortletContext getPortletContext() { + return context; + } + + /** + * {@inheritDoc} + */ + public Map getHeader() { + if ((header == null) && (request != null)) { + header = new ReadOnlyEnumerationMap<>(new HeaderExtractor(request, null)); + } + return (header); + } + + /** + * {@inheritDoc} + */ + public Addable getResponseHeaders() { + if ((responseHeaders == null) && (request != null)) { + responseHeaders = new HeaderExtractor(null, response); + } + return (responseHeaders); + } + + /** + * {@inheritDoc} + */ + public Map getHeaderValues() { + if ((headerValues == null) && (request != null)) { + headerValues = new HeaderValuesMap(new HeaderExtractor(request, response)); + } + return (headerValues); + } + + /** + * {@inheritDoc} + */ + public Map getRequestScope() { + if ((requestScope == null) && (request != null)) { + requestScope = new ScopeMap(new RequestScopeExtractor(request)); + } + return (requestScope); + } + + /** + * {@inheritDoc} + */ + public Map getSessionScope() { + if ((sessionScope == null) && (request != null)) { + sessionScope = new ScopeMap(new SessionScopeExtractor(request, + PortletSession.APPLICATION_SCOPE)); + } + return (sessionScope); + } + + /** + * {@inheritDoc} + */ + public Map getPortletSessionScope() { + if ((portletSessionScope == null) && (request != null)) { + portletSessionScope = new ScopeMap(new SessionScopeExtractor( + request, PortletSession.APPLICATION_SCOPE)); + } + return (portletSessionScope); + } + + @Override + public List getAvailableScopes() { + return SCOPES; + } + + /** + * {@inheritDoc} + */ + public Locale getRequestLocale() { + return request.getLocale(); + } + + @Override + public Map getParam() { + return requestDelegate.getParam(); + } + + @Override + public Map getParamValues() { + return requestDelegate.getParamValues(); + } + + /** + * {@inheritDoc} + */ + public boolean isUserInRole(String role) { + return request.isUserInRole(role); + } + + @Override + public OutputStream getOutputStream() throws IOException { + return responseDelegate.getOutputStream(); + } + + @Override + public PrintWriter getPrintWriter() throws IOException { + return responseDelegate.getPrintWriter(); + } + + @Override + public Writer getWriter() throws IOException { + return responseDelegate.getWriter(); + } + + @Override + public boolean isResponseCommitted() { + return responseDelegate.isResponseCommitted(); + } + + @Override + public void setContentType(String contentType) { + responseDelegate.setContentType(contentType); + } + + /** + * {@inheritDoc} + */ + public void doForward(String path) throws IOException { + if (responseDelegate.isResponseCommitted()) { + doInclude(path); + return; + } + + try { + PortletRequestDispatcher rd = getPortletContext() + .getRequestDispatcher(path); + + if (rd == null) { + throw new IOException( + "No portlet request dispatcher returned for path '" + + path + "'"); + } + + rd.forward(request, response); + } catch (PortletException e) { + throw new IOException("PortletException while including path '" + + path + "'.", e); + } + } + + /** + * {@inheritDoc} + */ + public void doInclude(String path) throws IOException { + try { + PortletRequestDispatcher rd = getPortletContext() + .getRequestDispatcher(path); + + if (rd == null) { + throw new IOException( + "No portlet request dispatcher returned for path '" + + path + "'"); + } + + rd.include(request, response); + } catch (PortletException e) { + throw new IOException("PortletException while including path '" + + path + "'.", e); + } + } + + @Override + public Map getContext(String scope) { + if (REQUEST_SCOPE.equals(scope)) { + return getRequestScope(); + } else if ("session".equals(scope)) { + return getSessionScope(); + } else if ("portletSession".equals(scope)) { + return getPortletSessionScope(); + } else if (APPLICATION_SCOPE.equals(scope)) { + return getApplicationScope(); + } + throw new IllegalArgumentException(scope + " does not exist. Call getAvailableScopes() first to check."); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/RenderPortletRequest.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/RenderPortletRequest.java new file mode 100644 index 0000000000..ea22c38a2d --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/RenderPortletRequest.java @@ -0,0 +1,47 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.portlet.delegate.MimeResponseDelegate; +import org.apache.tiles.request.portlet.delegate.PortletRequestDelegate; + +import javax.portlet.PortletContext; +import javax.portlet.RenderRequest; +import javax.portlet.RenderResponse; + +/** + * Portlet request for a {@link RenderRequest}. + */ +public class RenderPortletRequest extends PortletRequest { + + /** + * Constructor. + * + * @param applicationContext The application context. + * @param context The portlet context. + * @param request The portlet request. + * @param response The portlet response. + */ + public RenderPortletRequest(ApplicationContext applicationContext, PortletContext context, RenderRequest request, RenderResponse response) { + super(applicationContext, context, request, response, new PortletRequestDelegate(request), new MimeResponseDelegate(response)); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegate.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegate.java new file mode 100644 index 0000000000..347873cf13 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegate.java @@ -0,0 +1,72 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.delegate; + +import javax.portlet.MimeResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; + +/** + * Response delegate in case of {@link MimeResponse}. + */ +public class MimeResponseDelegate implements ResponseDelegate { + + /** + * The response. + */ + private final MimeResponse response; + + /** + * Constructor. + * + * @param response The response. + */ + public MimeResponseDelegate(MimeResponse response) { + this.response = response; + } + + /** {@inheritDoc} */ + public OutputStream getOutputStream() throws IOException { + return response.getPortletOutputStream(); + } + + /** {@inheritDoc} */ + public PrintWriter getPrintWriter() throws IOException { + return response.getWriter(); + } + + /** {@inheritDoc} */ + public Writer getWriter() throws IOException { + return response.getWriter(); + } + + /** {@inheritDoc} */ + public boolean isResponseCommitted() { + return response.isCommitted(); + } + + /** {@inheritDoc} */ + public void setContentType(String contentType) { + response.setContentType(contentType); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegate.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegate.java new file mode 100644 index 0000000000..e5683d5a01 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegate.java @@ -0,0 +1,79 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.delegate; + +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.apache.tiles.request.portlet.extractor.ParameterExtractor; + +import javax.portlet.PortletRequest; +import java.util.Map; + +/** + * Request delegate in case of simple Portlet request. + */ +public class PortletRequestDelegate implements RequestDelegate { + + /** + * The request. + */ + private final PortletRequest request; + + /** + *

The lazily instantiated Map of request + * parameter name-value.

+ */ + private Map param = null; + + /** + *

The lazily instantiated Map of request + * parameter name-values.

+ */ + private Map paramValues = null; + + /** + * Constructor. + * + * @param request The request. + */ + public PortletRequestDelegate(PortletRequest request) { + this.request = request; + } + + /** + * {@inheritDoc} + */ + public Map getParam() { + if ((param == null) && (request != null)) { + param = new ReadOnlyEnumerationMap<>(new ParameterExtractor(request)); + } + return (param); + } + + /** + * {@inheritDoc} + */ + public Map getParamValues() { + if ((paramValues == null) && (request != null)) { + paramValues = request.getParameterMap(); + } + return (paramValues); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/RequestDelegate.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/RequestDelegate.java new file mode 100644 index 0000000000..03846cc72d --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/RequestDelegate.java @@ -0,0 +1,43 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.delegate; + +import java.util.Map; + +/** + * Exposes the parameters of a portlet request, if available. + */ +public interface RequestDelegate { + + /** + * The parameters, as single values. + * + * @return The parameters. + */ + Map getParam(); + + /** + * The parameters, with values as array of strings. + * + * @return The parameters. + */ + Map getParamValues(); +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/ResponseDelegate.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/ResponseDelegate.java new file mode 100644 index 0000000000..92f46cef63 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/ResponseDelegate.java @@ -0,0 +1,70 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.delegate; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; + +/** + * Exposes features of a response, if they are available. + */ +public interface ResponseDelegate { + + /** + * Returns the output stream. + * + * @return The output stream. + * @throws IOException If the underlying response causes a problem. + */ + OutputStream getOutputStream() throws IOException; + + /** + * Returns the print writer. + * + * @return The print writer. + * @throws IOException If the underlying response causes a problem. + */ + PrintWriter getPrintWriter() throws IOException; + + /** + * Returns the writer. + * + * @return The writer. + * @throws IOException If the underlying response causes a problem. + */ + Writer getWriter() throws IOException; + + /** + * Sets the content type of the response. + * + * @param contentType The content type. + */ + void setContentType(String contentType); + + /** + * Checks if the response is committed. + * + * @return true if the response is committed. + */ + boolean isResponseCommitted(); +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/package-info.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/package-info.java new file mode 100644 index 0000000000..5080dc3e0e --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Delegations to map all the different types of request and responses. + */ +package org.apache.tiles.request.portlet.delegate; diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractor.java new file mode 100644 index 0000000000..590046cff1 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractor.java @@ -0,0 +1,66 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.portlet.PortletContext; +import java.util.Enumeration; + +/** + * Extracts attributes from portlet application scope. + */ +public class ApplicationScopeExtractor implements AttributeExtractor { + + /** + * The portlet context. + */ + private final PortletContext context; + + /** + * Constructor. + * + * @param context The portlet context. + */ + public ApplicationScopeExtractor(PortletContext context) { + this.context = context; + } + + @Override + public void setValue(String name, Object value) { + context.setAttribute(name, value); + } + + @Override + public void removeValue(String name) { + context.removeAttribute(name); + } + + @Override + public Enumeration getKeys() { + return context.getAttributeNames(); + } + + @Override + public Object getValue(String key) { + return context.getAttribute(key); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/HeaderExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/HeaderExtractor.java new file mode 100644 index 0000000000..0c94fa90f0 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/HeaderExtractor.java @@ -0,0 +1,74 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; + +import javax.portlet.PortletRequest; +import javax.portlet.PortletResponse; +import java.util.Enumeration; + +/** + * Extracts and puts headers in portlet requests and responses. + */ +public class HeaderExtractor implements EnumeratedValuesExtractor { + + /** + * The request. + */ + private final PortletRequest request; + + /** + * The response. + */ + private final PortletResponse response; + + /** + * Constructor. + * + * @param request The request. + * @param response The response. + */ + public HeaderExtractor(PortletRequest request, PortletResponse response) { + this.request = request; + this.response = response; + } + + @Override + public Enumeration getKeys() { + return request.getPropertyNames(); + } + + @Override + public String getValue(String key) { + return request.getProperty(key); + } + + @Override + public Enumeration getValues(String key) { + return request.getProperties(key); + } + + @Override + public void setValue(String key, String value) { + response.setProperty(key, value); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractor.java new file mode 100644 index 0000000000..f27fdf4f11 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractor.java @@ -0,0 +1,57 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.HasKeys; + +import javax.portlet.PortletContext; +import java.util.Enumeration; + +/** + * Extracts init parameters from a portlet context. + */ +public class InitParameterExtractor implements HasKeys { + + /** + * The portlet context. + */ + private final PortletContext context; + + /** + * Constructor. + * + * @param context The portlet context. + */ + public InitParameterExtractor(PortletContext context) { + this.context = context; + } + + @Override + public Enumeration getKeys() { + return context.getInitParameterNames(); + } + + @Override + public String getValue(String key) { + return context.getInitParameter(key); + } + +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ParameterExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ParameterExtractor.java new file mode 100644 index 0000000000..e412a84c69 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ParameterExtractor.java @@ -0,0 +1,56 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.HasKeys; + +import javax.portlet.PortletRequest; +import java.util.Enumeration; + +/** + * Extracts parameters from a portlet request. + */ +public class ParameterExtractor implements HasKeys { + + /** + * The portlet request. + */ + private final PortletRequest request; + + /** + * Constructor. + * + * @param request The portlet request. + */ + public ParameterExtractor(PortletRequest request) { + this.request = request; + } + + @Override + public Enumeration getKeys() { + return request.getParameterNames(); + } + + @Override + public String getValue(String key) { + return request.getParameter(key); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractor.java new file mode 100644 index 0000000000..edc72bc9e3 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractor.java @@ -0,0 +1,66 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.portlet.PortletRequest; +import java.util.Enumeration; + +/** + * Extracts attributes from request scope of a portlet request. + */ +public class RequestScopeExtractor implements AttributeExtractor { + + /** + * The portlet request. + */ + private final PortletRequest request; + + /** + * Constructor. + * + * @param request The portlet request. + */ + public RequestScopeExtractor(PortletRequest request) { + this.request = request; + } + + @Override + public void setValue(String name, Object value) { + request.setAttribute(name, value); + } + + @Override + public void removeValue(String name) { + request.removeAttribute(name); + } + + @Override + public Enumeration getKeys() { + return request.getAttributeNames(); + } + + @Override + public Object getValue(String key) { + return request.getAttribute(key); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractor.java new file mode 100644 index 0000000000..9801454fa3 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractor.java @@ -0,0 +1,88 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.portlet.PortletRequest; +import javax.portlet.PortletSession; +import java.util.Enumeration; + +/** + * Extracts attributes from the session scope of a portlet request. + */ +public class SessionScopeExtractor implements AttributeExtractor { + + /** + * The portlet request. + */ + private final PortletRequest request; + + /** + * The subscope (application or portlet). + */ + private final int scope; + + /** + * Constructor. + * + * @param request The request. + * @param scope The subscope (application or portlet). + */ + public SessionScopeExtractor(PortletRequest request, int scope) { + this.request = request; + if (scope != PortletSession.APPLICATION_SCOPE && scope != PortletSession.PORTLET_SCOPE) { + throw new IllegalArgumentException("The scope must be either APPLICATION_SCOPE or PORTLET_SCOPE"); + } + this.scope = scope; + } + + @Override + public void setValue(String name, Object value) { + request.getPortletSession().setAttribute(name, value, scope); + } + + @Override + public void removeValue(String name) { + PortletSession session = request.getPortletSession(false); + if (session != null) { + session.removeAttribute(name, scope); + } + } + + @Override + public Enumeration getKeys() { + PortletSession session = request.getPortletSession(false); + if (session != null) { + return session.getAttributeNames(scope); + } + return null; + } + + @Override + public Object getValue(String key) { + PortletSession session = request.getPortletSession(false); + if (session != null) { + return session.getAttribute(key, scope); + } + return null; + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java new file mode 100644 index 0000000000..a14f53a7bc --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java @@ -0,0 +1,53 @@ +/* + * $Id$ + * + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.HasAddableKeys; + +import javax.portlet.PortletRequest; +import javax.portlet.StateAwareResponse; + +/** + * Extracts parameters from a request and allows putting render parameters in a state aware response. + */ +public class StateAwareParameterExtractor extends ParameterExtractor implements HasAddableKeys { + + /** + * The portlet response. + */ + private final StateAwareResponse response; + + /** + * Constructor. + * + * @param request The portlet request. + * @param response The portlet response. + */ + public StateAwareParameterExtractor(PortletRequest request, StateAwareResponse response) { + super(request); + this.response = response; + } + + @Override + public void setValue(String key, String value) { + response.setRenderParameter(key, value); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/package-info.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/package-info.java new file mode 100644 index 0000000000..a37ccbb9ef --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Extractors to get scopes from Portlet requests. + */ +package org.apache.tiles.request.portlet.extractor; diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/package-info.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/package-info.java new file mode 100644 index 0000000000..b9eb0d1687 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Support of Tiles requests to portlets. + */ +package org.apache.tiles.request.portlet; diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java new file mode 100644 index 0000000000..53a6bf8560 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java @@ -0,0 +1,424 @@ +/* + * 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.apache.tiles.request.portlet; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.collection.HeaderValuesMap; +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.portlet.delegate.RequestDelegate; +import org.apache.tiles.request.portlet.delegate.ResponseDelegate; +import org.apache.tiles.request.portlet.extractor.HeaderExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletContext; +import javax.portlet.PortletException; +import javax.portlet.PortletRequestDispatcher; +import javax.portlet.PortletResponse; +import javax.servlet.ServletOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Locale; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link PortletRequest}. + */ +public class PortletRequestTest { + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * The portlet context. + */ + private PortletContext portletContext; + + /** + * The request. + */ + private javax.portlet.PortletRequest request; + + /** + * The response. + */ + private PortletResponse response; + + /** + * The request to test. + */ + private PortletRequest req; + + /** + * The request delegate. + */ + private RequestDelegate requestDelegate; + + /** + * The response delegate. + */ + private ResponseDelegate responseDelegate; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + applicationContext = createMock(ApplicationContext.class); + portletContext = createMock(PortletContext.class); + request = createMock(javax.portlet.PortletRequest.class); + response = createMock(PortletResponse.class); + requestDelegate = createMock(RequestDelegate.class); + responseDelegate = createMock(ResponseDelegate.class); + req = new PortletRequest(applicationContext, portletContext, request, + response, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#doForward(String)}. + * + * @throws IOException If something goes wrong. + * @throws PortletException If something goes wrong. + */ + @Test + public void testDoForward() throws PortletException, IOException { + PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class); + + expect(responseDelegate.isResponseCommitted()).andReturn(false); + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd); + rd.forward(request, response); + + replay(applicationContext, portletContext, request, response, rd); + req.doForward("/my/path"); + verify(applicationContext, portletContext, request, response, rd); + } + + /** + * Test method for {@link PortletRequest#doForward(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testDoForwardNoDispatcher() throws IOException { + expect(responseDelegate.isResponseCommitted()).andReturn(false); + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(null); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + try { + req.doForward("/my/path"); + } finally { + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + } + + /** + * Test method for {@link PortletRequest#doForward(String)}. + * + * @throws IOException If something goes wrong. + * @throws PortletException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testDoForwardPortletException() throws PortletException, IOException { + PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class); + + expect(responseDelegate.isResponseCommitted()).andReturn(false); + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd); + rd.forward(request, response); + expectLastCall().andThrow(new PortletException()); + + replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + try { + req.doForward("/my/path"); + } finally { + verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + } + } + + /** + * Test method for {@link PortletRequest#doForward(String)}. + * + * @throws IOException If something goes wrong. + * @throws PortletException If something goes wrong. + */ + @Test + public void testDoForwardInclude() throws PortletException, IOException { + PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class); + + expect(responseDelegate.isResponseCommitted()).andReturn(true); + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd); + rd.include(request, response); + + replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + req.doForward("/my/path"); + verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#doInclude(String)}. + * + * @throws IOException If something goes wrong. + * @throws PortletException If something goes wrong. + */ + @Test + public void testDoInclude() throws IOException, PortletException { + PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class); + + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd); + rd.include(request, response); + + replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + req.doInclude("/my/path"); + verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#doInclude(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testDoIncludeNoDispatcher() throws IOException { + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(null); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + try { + req.doInclude("/my/path"); + } finally { + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + } + + /** + * Test method for {@link PortletRequest#doInclude(String)}. + * + * @throws IOException If something goes wrong. + * @throws PortletException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testDoIncludePortletException() throws IOException, PortletException { + PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class); + + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd); + rd.include(request, response); + expectLastCall().andThrow(new PortletException()); + + replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + try { + req.doInclude("/my/path"); + } finally { + verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + } + } + + /** + * Test method for {@link PortletRequest#getHeader()}. + */ + @Test + public void testGetHeader() { + assertTrue(req.getHeader() instanceof ReadOnlyEnumerationMap); + } + + /** + * Test method for {@link PortletRequest#getResponseHeaders()}. + */ + @Test + public void testGetResponseHeaders() { + assertTrue(req.getResponseHeaders() instanceof HeaderExtractor); + } + + /** + * Test method for {@link PortletRequest#getHeaderValues()}. + */ + @Test + public void testGetHeaderValues() { + assertTrue(req.getHeaderValues() instanceof HeaderValuesMap); + } + + /** + * Test method for {@link PortletRequest#getParam()}. + */ + @Test + public void testGetParam() { + Map map = createMock(Map.class); + + expect(requestDelegate.getParam()).andReturn(map); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + assertEquals(map, req.getParam()); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getParamValues()}. + */ + @Test + public void testGetParamValues() { + Map paramMap = createMock(Map.class); + + expect(requestDelegate.getParamValues()).andReturn(paramMap); + + replay(applicationContext, request, response, paramMap, portletContext, requestDelegate, responseDelegate); + assertEquals(paramMap, req.getParamValues()); + verify(applicationContext, request, response, paramMap, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getRequestScope()}. + */ + @Test + public void testGetRequestScope() { + assertTrue(req.getRequestScope() instanceof ScopeMap); + } + + /** + * Test method for {@link PortletRequest#getSessionScope()}. + */ + @Test + public void testGetSessionScope() { + assertTrue(req.getSessionScope() instanceof ScopeMap); + } + + /** + * Test method for {@link PortletRequest#getPortletSessionScope()}. + */ + @Test + public void testGetPortletSessionScope() { + assertTrue(req.getPortletSessionScope() instanceof ScopeMap); + } + + /** + * Test method for {@link PortletRequest#getOutputStream()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetOutputStream() throws IOException { + ServletOutputStream os = createMock(ServletOutputStream.class); + + expect(responseDelegate.getOutputStream()).andReturn(os); + + replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + assertEquals(req.getOutputStream(), os); + verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getWriter()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetWriter() throws IOException { + PrintWriter os = createMock(PrintWriter.class); + + expect(responseDelegate.getWriter()).andReturn(os); + + replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + assertEquals(req.getWriter(), os); + verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getPrintWriter()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetPrintWriter() throws IOException { + PrintWriter os = createMock(PrintWriter.class); + + expect(responseDelegate.getPrintWriter()).andReturn(os); + + replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + assertEquals(req.getPrintWriter(), os); + verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#isResponseCommitted()}. + */ + @Test + public void testIsResponseCommitted() { + expect(responseDelegate.isResponseCommitted()).andReturn(true); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + assertTrue(req.isResponseCommitted()); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#setContentType(String)}. + */ + @Test + public void testSetContentType() { + responseDelegate.setContentType("text/html"); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + req.setContentType("text/html"); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getRequestLocale()}. + */ + @Test + public void testGetRequestLocale() { + Locale locale = Locale.ITALY; + + expect(request.getLocale()).andReturn(locale); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + assertEquals(locale, req.getRequestLocale()); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getRequest()}. + */ + @Test + public void testGetRequest() { + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + assertEquals(request, req.getRequest()); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#isUserInRole(String)}. + */ + @Test + public void testIsUserInRole() { + expect(request.isUserInRole("myrole")).andReturn(true); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + assertTrue(req.isUserInRole("myrole")); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java new file mode 100644 index 0000000000..5bba700fb9 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java @@ -0,0 +1,69 @@ +/* + * 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.apache.tiles.request.portlet; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.portlet.delegate.MimeResponseDelegate; +import org.apache.tiles.request.portlet.delegate.PortletRequestDelegate; +import org.junit.Test; + +import javax.portlet.PortletContext; +import javax.portlet.RenderRequest; +import javax.portlet.RenderResponse; +import java.lang.reflect.Field; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link RenderPortletRequest}. + */ +public class RenderPortletRequestTest { + + /** + * Test method for + * {@link RenderPortletRequest#RenderPortletRequest(ApplicationContext, PortletContext, + * RenderRequest, RenderResponse)}. + * + * @throws NoSuchFieldException If something goes wrong. + * @throws SecurityException If something goes wrong. + * @throws IllegalAccessException If something goes wrong. + * @throws IllegalArgumentException If something goes wrong. + */ + @Test + public void testRenderPortletRequest() throws NoSuchFieldException, IllegalAccessException { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + PortletContext portletContext = createMock(PortletContext.class); + RenderRequest request = createMock(RenderRequest.class); + RenderResponse response = createMock(RenderResponse.class); + + replay(applicationContext, portletContext, request, response); + RenderPortletRequest req = new RenderPortletRequest(applicationContext, + portletContext, request, response); + Class clazz = req.getClass(); + Field field = clazz.getSuperclass().getDeclaredField("requestDelegate"); + assertTrue(field.get(req) instanceof PortletRequestDelegate); + field = clazz.getSuperclass().getDeclaredField("responseDelegate"); + assertTrue(field.get(req) instanceof MimeResponseDelegate); + verify(applicationContext, portletContext, request, response); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java new file mode 100644 index 0000000000..25d6534566 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java @@ -0,0 +1,132 @@ +/* + * 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.apache.tiles.request.portlet.delegate; + +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.MimeResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link MimeResponseDelegate}. + */ +public class MimeResponseDelegateTest { + + /** + * The response. + */ + private MimeResponse response; + + /** + * The delegate to test. + */ + private MimeResponseDelegate delegate; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + response = createMock(MimeResponse.class); + delegate = new MimeResponseDelegate(response); + } + + /** + * Test method for {@link MimeResponseDelegate#getOutputStream()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetOutputStream() throws IOException { + OutputStream os = createMock(OutputStream.class); + + expect(response.getPortletOutputStream()).andReturn(os); + + replay(response, os); + assertEquals(os, delegate.getOutputStream()); + verify(response, os); + } + + /** + * Test method for {@link MimeResponseDelegate#getPrintWriter()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetPrintWriter() throws IOException { + PrintWriter os = createMock(PrintWriter.class); + + expect(response.getWriter()).andReturn(os); + + replay(response, os); + assertEquals(os, delegate.getPrintWriter()); + verify(response, os); + } + + /** + * Test method for {@link MimeResponseDelegate#getWriter()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetWriter() throws IOException { + PrintWriter os = createMock(PrintWriter.class); + + expect(response.getWriter()).andReturn(os); + + replay(response, os); + assertEquals(os, delegate.getWriter()); + verify(response, os); + } + + /** + * Test method for {@link MimeResponseDelegate#isResponseCommitted()}. + */ + @Test + public void testIsResponseCommitted() { + expect(response.isCommitted()).andReturn(true); + + replay(response); + assertTrue(delegate.isResponseCommitted()); + verify(response); + } + + /** + * Test method for {@link MimeResponseDelegate#setContentType(String)}. + */ + @Test + public void testSetContentType() { + response.setContentType("text/html"); + + replay(response); + delegate.setContentType("text/html"); + verify(response); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java new file mode 100644 index 0000000000..ce6d4e8494 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java @@ -0,0 +1,83 @@ +/* + * 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.apache.tiles.request.portlet.delegate; + +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link PortletRequestDelegate}. + */ +public class PortletRequestDelegateTest { + + /** + * The request. + */ + private PortletRequest request; + + /** + * The delegate to test. + */ + private PortletRequestDelegate delegate; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + request = createMock(PortletRequest.class); + delegate = new PortletRequestDelegate(request); + } + + /** + * Test method for {@link PortletRequestDelegate#getParam()}. + */ + @Test + public void testGetParam() { + replay(request); + assertTrue(delegate.getParam() instanceof ReadOnlyEnumerationMap); + verify(request); + } + + /** + * Test method for {@link PortletRequestDelegate#getParamValues()}. + */ + @Test + public void testGetParamValues() { + Map params = createMock(Map.class); + + expect(request.getParameterMap()).andReturn(params); + + replay(request, params); + assertEquals(params, delegate.getParamValues()); + verify(request, params); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java new file mode 100644 index 0000000000..5ede84f691 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java @@ -0,0 +1,106 @@ +/* + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.ApplicationScopeExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletContext; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link ApplicationScopeExtractor}. + */ +public class ApplicationScopeExtractorTest { + + /** + * The portlet context. + */ + private PortletContext context; + + /** + * The extractot to test. + */ + private ApplicationScopeExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + context = createMock(PortletContext.class); + extractor = new ApplicationScopeExtractor(context); + } + + /** + * Test method for {@link ApplicationScopeExtractor#setValue(String, Object)}. + */ + @Test + public void testSetValue() { + context.setAttribute("attribute", "value"); + + replay(context); + extractor.setValue("attribute", "value"); + verify(context); + } + + /** + * Test method for {@link ApplicationScopeExtractor#removeValue(String)}. + */ + @Test + public void testRemoveValue() { + context.removeAttribute("attribute"); + + replay(context); + extractor.removeValue("attribute"); + verify(context); + } + + /** + * Test method for {@link ApplicationScopeExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + expect(context.getAttributeNames()).andReturn(keys); + + replay(context, keys); + assertEquals(keys, extractor.getKeys()); + verify(context, keys); + } + + /** + * Test method for {@link ApplicationScopeExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(context.getAttribute("attribute")).andReturn("value"); + + replay(context); + assertEquals("value", extractor.getValue("attribute")); + verify(context); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java new file mode 100644 index 0000000000..7f5054c024 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java @@ -0,0 +1,117 @@ +/* + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.HeaderExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import javax.portlet.PortletResponse; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link HeaderExtractor}. + */ +public class HeaderExtractorTest { + + /** + * The request. + */ + private PortletRequest request; + + /** + * The response. + */ + private PortletResponse response; + + /** + * The extractor to test. + */ + private HeaderExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + request = createMock(PortletRequest.class); + response = createMock(PortletResponse.class); + extractor = new HeaderExtractor(request, response); + } + + /** + * Test method for {@link HeaderExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + + expect(request.getPropertyNames()).andReturn(keys); + + replay(request, response, keys); + assertEquals(keys, extractor.getKeys()); + verify(request, response, keys); + } + + /** + * Test method for {@link HeaderExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(request.getProperty("name")).andReturn("value"); + + replay(request, response); + assertEquals("value", extractor.getValue("name")); + verify(request, response); + } + + /** + * Test method for {@link HeaderExtractor#getValues(String)}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetValues() { + Enumeration keys = createMock(Enumeration.class); + + expect(request.getProperties("name")).andReturn(keys); + + replay(request, response, keys); + assertEquals(keys, extractor.getValues("name")); + verify(request, response, keys); + } + + /** + * Test method for {@link HeaderExtractor#setValue(String, String)}. + */ + @Test + public void testSetValue() { + response.setProperty("name", "value"); + + replay(request, response); + extractor.setValue("name", "value"); + verify(request, response); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java new file mode 100644 index 0000000000..66a1f9ea79 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java @@ -0,0 +1,83 @@ +/* + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.InitParameterExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletContext; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link InitParameterExtractor}. + */ +public class InitParameterExtractorTest { + + /** + * The portlet context. + */ + private PortletContext context; + + /** + * The extractor to test. + */ + private InitParameterExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + context = createMock(PortletContext.class); + extractor = new InitParameterExtractor(context); + } + + /** + * Test method for {@link InitParameterExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + + expect(context.getInitParameterNames()).andReturn(keys); + + replay(context, keys); + assertEquals(keys, extractor.getKeys()); + verify(context, keys); + } + + /** + * Test method for {@link InitParameterExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(context.getInitParameter("name")).andReturn("value"); + + replay(context); + assertEquals("value", extractor.getValue("name")); + verify(context); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java new file mode 100644 index 0000000000..0e80053250 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java @@ -0,0 +1,83 @@ +/* + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.ParameterExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link ParameterExtractor}. + */ +public class ParameterExtractorTest { + + /** + * The request. + */ + private PortletRequest request; + + /** + * The extractor to test. + */ + private ParameterExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + request = createMock(PortletRequest.class); + extractor = new ParameterExtractor(request); + } + + /** + * Test method for {@link ParameterExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + + expect(request.getParameterNames()).andReturn(keys); + + replay(request, keys); + assertEquals(keys, extractor.getKeys()); + verify(request, keys); + } + + /** + * Test method for {@link ParameterExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(request.getParameter("name")).andReturn("value"); + + replay(request); + assertEquals("value", extractor.getValue("name")); + verify(request); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java new file mode 100644 index 0000000000..df76a515e8 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java @@ -0,0 +1,107 @@ +/* + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.RequestScopeExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link RequestScopeExtractor}. + */ +public class RequestScopeExtractorTest { + + /** + * The request to test. + */ + private PortletRequest request; + + /** + * The extractor to test. + */ + private RequestScopeExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + request = createMock(PortletRequest.class); + extractor = new RequestScopeExtractor(request); + } + + /** + * Test method for {@link RequestScopeExtractor#setValue(String, Object)}. + */ + @Test + public void testSetValue() { + request.setAttribute("name", "value"); + + replay(request); + extractor.setValue("name", "value"); + verify(request); + } + + /** + * Test method for {@link RequestScopeExtractor#removeValue(String)}. + */ + @Test + public void testRemoveValue() { + request.removeAttribute("name"); + + replay(request); + extractor.removeValue("name"); + verify(request); + } + + /** + * Test method for {@link RequestScopeExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + + expect(request.getAttributeNames()).andReturn(keys); + + replay(request, keys); + assertEquals(keys, extractor.getKeys()); + verify(request, keys); + } + + /** + * Test method for {@link RequestScopeExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(request.getAttribute("name")).andReturn("value"); + + replay(request); + assertEquals("value", extractor.getValue("name")); + verify(request); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java new file mode 100644 index 0000000000..09010ff0c7 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java @@ -0,0 +1,154 @@ +/* + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.SessionScopeExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import javax.portlet.PortletSession; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link SessionScopeExtractor}. + */ +public class SessionScopeExtractorTest { + + /** + * The request. + */ + private PortletRequest request; + + /** + * The session. + */ + private PortletSession session; + + /** + * The scope to test. + */ + private SessionScopeExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + request = createMock(PortletRequest.class); + session = createMock(PortletSession.class); + extractor = new SessionScopeExtractor(request, PortletSession.PORTLET_SCOPE); + } + + + /** + * Tests {@link SessionScopeExtractor#SessionScopeExtractor(PortletRequest, int)}. + */ + @Test(expected = IllegalArgumentException.class) + public void testIllegalScope() { + replay(request, session); + new SessionScopeExtractor(request, 0); + verify(request, session); + } + + /** + * Test method for {@link SessionScopeExtractor#setValue(String, Object)}. + */ + @Test + public void testSetValue() { + expect(request.getPortletSession()).andReturn(session); + session.setAttribute("name", "value", PortletSession.PORTLET_SCOPE); + + replay(request, session); + extractor.setValue("name", "value"); + verify(request, session); + } + + /** + * Test method for {@link SessionScopeExtractor#removeValue(String)}. + */ + @Test + public void testRemoveValue() { + expect(request.getPortletSession(false)).andReturn(session); + session.removeAttribute("name", PortletSession.PORTLET_SCOPE); + + replay(request, session); + extractor.removeValue("name"); + verify(request, session); + } + + /** + * Test method for {@link SessionScopeExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + + expect(request.getPortletSession(false)).andReturn(session); + expect(session.getAttributeNames(PortletSession.PORTLET_SCOPE)).andReturn(keys); + + replay(request, session, keys); + assertEquals(keys, extractor.getKeys()); + verify(request, session, keys); + } + + /** + * Test method for {@link SessionScopeExtractor#getKeys()}. + */ + @Test + public void testGetKeysNoSession() { + expect(request.getPortletSession(false)).andReturn(null); + + replay(request, session); + assertNull(extractor.getKeys()); + verify(request, session); + } + + /** + * Test method for {@link SessionScopeExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(request.getPortletSession(false)).andReturn(session); + expect(session.getAttribute("name", PortletSession.PORTLET_SCOPE)).andReturn("value"); + + replay(request, session); + assertEquals("value", extractor.getValue("name")); + verify(request, session); + } + + /** + * Test method for {@link SessionScopeExtractor#getValue(String)}. + */ + @Test + public void testGetValueNoSession() { + expect(request.getPortletSession(false)).andReturn(null); + + replay(request, session); + assertNull(extractor.getValue("name")); + verify(request, session); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java new file mode 100644 index 0000000000..5157b6fe66 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java @@ -0,0 +1,50 @@ +/* + * 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.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.StateAwareParameterExtractor; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import javax.portlet.StateAwareResponse; + +import static org.easymock.EasyMock.*; + +/** + * Tests {@link StateAwareParameterExtractor}. + */ +public class StateAwareParameterExtractorTest { + + /** + * Test method for {@link StateAwareParameterExtractor#setValue(String, String)}. + */ + @Test + public void testSetValue() { + PortletRequest request = createMock(PortletRequest.class); + StateAwareResponse response = createMock(StateAwareResponse.class); + + response.setRenderParameter("name", "value"); + + replay(request, response); + StateAwareParameterExtractor extractor = new StateAwareParameterExtractor(request, response); + extractor.setValue("name", "value"); + verify(request, response); + } + +} diff --git a/plugins/tiles/pom.xml b/plugins/tiles/pom.xml index 0c0488dc01..9716e71980 100644 --- a/plugins/tiles/pom.xml +++ b/plugins/tiles/pom.xml @@ -31,59 +31,87 @@ jar Struts 2 Tiles Plugin + + + + build-autotags + + true + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + compile + + java + + + + + org.apache.struts2.tiles.BuildAutotags + + + ${project.build.directory} + + + + + + + + - org.apache.tiles - tiles-api - - - org.apache.tiles - tiles-core - - - org.apache.tiles - tiles-servlet - - - org.apache.tiles - tiles-request-api + commons-digester + commons-digester - org.apache.tiles - tiles-request-jsp + org.glassfish + javax.el + true - org.apache.tiles - tiles-request-servlet + javax.servlet.jsp + jsp-api + provided - org.apache.tiles - tiles-jsp + org.apache.velocity + velocity-engine-core + true - org.apache.tiles - tiles-freemarker + org.apache.velocity.tools + velocity-tools-view + true - org.apache.tiles - tiles-ognl + org.apache.velocity.tools + velocity-tools-view-jsp + true - org.apache.tiles - tiles-el + com.thoughtworks.xstream + xstream + true - org.glassfish - javax.el - true + org.easymock + easymock + test - javax.servlet.jsp - jsp-api - provided + org.apache.logging.log4j + log4j-jcl + test - UTF-8 + UTF-8 diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/BuildAutotags.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/BuildAutotags.java new file mode 100644 index 0000000000..4e90bb7ba3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/BuildAutotags.java @@ -0,0 +1,229 @@ +/* + * 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.apache.struts2.tiles; + +import java.io.File; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.tiles.autotag.freemarker.FMTemplateGeneratorFactory; +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.tiles.autotag.jsp.JspTemplateGeneratorFactory; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.tiles.autotag.velocity.VelocityTemplateGeneratorFactory; +import org.apache.velocity.app.VelocityEngine; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.xml.DomDriver; + +/** + * Helper class for building/generating the classes and resources used in the + * plugin. + */ +public class BuildAutotags { + + public BuildAutotags() { + } + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + + BuildAutotags me = new BuildAutotags(); + + // Jsp classes + me.buildJsp(args[0]); + + // Freemarker classes + me.buildFreemarker(args[0]); + + // Velocity classes + me.buildVelocity(args[0]); + + } + + /** + * Build JSP tag classes and .tld file. + * + * To build, change template-suite.xml as required and then run this program. + * Copy the classes and .tld from the target autotag folder into the packageName + * location, .tld to src/main/resources/META-INF/tld/tiles-jsp.tld + * + * @param outputDir the output dir + */ + public void buildJsp(String outputDir) { + + // Default values + String taglibURI = "http://tiles.apache.org/tags-tiles"; + String packageName = "org.apache.tiles.web.jsp.taglib"; + String requestClass = "org.apache.tiles.request.Request"; + String runtime = "org.apache.tiles.request.jsp.autotag.JspAutotagRuntime"; + // outputDir = "/target" + + Map parameters = new HashMap(); + parameters.put("taglibURI", taglibURI); + + try { + + TemplateSuite suite; + + InputStream stream = getClass().getResourceAsStream("/META-INF/template-suite.xml"); + + try { + XStream xstream = new XStream(new DomDriver()); + xstream.allowTypes(new Class[] { org.apache.tiles.autotag.model.TemplateClass.class, + org.apache.tiles.autotag.model.TemplateSuite.class, + org.apache.tiles.autotag.model.TemplateParameter.class }); + suite = (TemplateSuite) xstream.fromXML(stream); + } finally { + stream.close(); + } + + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + + File classesOutputDirectory = new File(outputDir + "/generated-sources/autotag/classes"); + File resourcesOutputDirectory = new File(outputDir + "/generated-sources/autotag"); + + TemplateGenerator generator = new JspTemplateGeneratorFactory(classesOutputDirectory, + resourcesOutputDirectory, new VelocityEngine(props), TemplateGeneratorBuilder.createNewInstance()) + .createTemplateGenerator(); + + generator.generate(packageName, suite, parameters, runtime, requestClass); + + } catch (Exception e) { + // ignored + } + + } + + /** + * Builds the Freemarker classes. + * + * To build, change template-suite.xml as required and then run this program. + * Copy the classes from the target autotag folder into the packageName + * location. + * + * @param outputDir the output dir + */ + public void buildFreemarker(String outputDir) { + + // Default values + String packageName = "org.apache.tiles.freemarker.template"; + String requestClass = "org.apache.tiles.request.Request"; + String runtime = "org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime"; + // outputDir = "/target" + + try { + + TemplateSuite suite; + + InputStream stream = getClass().getResourceAsStream("/META-INF/template-suite.xml"); + + try { + XStream xstream = new XStream(new DomDriver()); + xstream.allowTypes(new Class[] { org.apache.tiles.autotag.model.TemplateClass.class, + org.apache.tiles.autotag.model.TemplateSuite.class, + org.apache.tiles.autotag.model.TemplateParameter.class }); + suite = (TemplateSuite) xstream.fromXML(stream); + } finally { + stream.close(); + } + + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + + File classesOutputDirectory = new File(outputDir + "/generated-sources/autotag/classes"); + + TemplateGenerator generator = new FMTemplateGeneratorFactory(classesOutputDirectory, + new VelocityEngine(props), TemplateGeneratorBuilder.createNewInstance()).createTemplateGenerator(); + + generator.generate(packageName, suite, null, runtime, requestClass); + + } catch (Exception e) { + // ignored + } + + } + + /** + * Builds the velocity classes and velocity.properties. + * + * To build, change template-suite.xml as required and then run this program. + * Copy the classes from the target autotag folder into the packageName + * location, and velocity.properties to + * src/main/resources/META-INF/velocity.properties + * + * @param outputDir the output dir + */ + public void buildVelocity(String outputDir) { + + // Default values + String packageName = "org.apache.tiles.velocity.template"; + String requestClass = "org.apache.tiles.request.Request"; + String runtime = "org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime"; + // outputDir = "/target" + + try { + + TemplateSuite suite; + + InputStream stream = getClass().getResourceAsStream("/META-INF/template-suite.xml"); + + try { + XStream xstream = new XStream(new DomDriver()); + xstream.allowTypes(new Class[] { org.apache.tiles.autotag.model.TemplateClass.class, + org.apache.tiles.autotag.model.TemplateSuite.class, + org.apache.tiles.autotag.model.TemplateParameter.class }); + suite = (TemplateSuite) xstream.fromXML(stream); + } finally { + stream.close(); + } + + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + + File classesOutputDirectory = new File(outputDir + "/generated-sources/autotag/classes"); + File resourcesOutputDirectory = new File(outputDir + "/generated-sources/autotag"); + + TemplateGenerator generator = new VelocityTemplateGeneratorFactory(classesOutputDirectory, + resourcesOutputDirectory, new VelocityEngine(props), TemplateGeneratorBuilder.createNewInstance()) + .createTemplateGenerator(); + + generator.generate(packageName, suite, null, runtime, requestClass); + + } catch (Exception e) { + // ignored + } + + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/I18NAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/I18NAttributeEvaluator.java index 04673f294b..e566f57476 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/I18NAttributeEvaluator.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/I18NAttributeEvaluator.java @@ -25,7 +25,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.ServletActionContext; -import org.apache.tiles.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.core.evaluator.AbstractAttributeEvaluator; import org.apache.tiles.request.Request; import org.apache.tiles.request.servlet.ServletUtil; diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java index b0cdb95baa..7b3e7624f9 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java @@ -25,8 +25,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.ServletActionContext; -import org.apache.tiles.evaluator.AbstractAttributeEvaluator; -import org.apache.tiles.evaluator.EvaluationException; +import org.apache.tiles.core.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.core.evaluator.EvaluationException; import org.apache.tiles.request.Request; import org.apache.tiles.request.servlet.ServletUtil; diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsFreeMarkerAttributeRenderer.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsFreeMarkerAttributeRenderer.java index cb6e0d403f..e39fed4c6f 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsFreeMarkerAttributeRenderer.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsFreeMarkerAttributeRenderer.java @@ -33,9 +33,9 @@ import org.apache.struts2.views.freemarker.FreemarkerResult; import org.apache.struts2.views.freemarker.StrutsBeanWrapper; import org.apache.tiles.freemarker.template.TilesFMModelRepository; -import org.apache.tiles.impl.InvalidTemplateException; import org.apache.tiles.request.Request; import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.core.impl.InvalidTemplateException; import org.apache.tiles.request.servlet.ServletUtil; import javax.servlet.ServletContext; @@ -44,7 +44,7 @@ public class StrutsFreeMarkerAttributeRenderer implements Renderer { - private static Logger LOG = LogManager.getLogger(StrutsFreeMarkerAttributeRenderer.class); + private static final Logger LOG = LogManager.getLogger(StrutsFreeMarkerAttributeRenderer.class); @Override public void render(String path, Request request) throws IOException { @@ -75,7 +75,7 @@ public void render(String path, Request request) throws IOException { } /** - * Depending how Tiles definition was defined, request can an instance of JspRequest (for JSPs) + * Depending on how Tiles definition was defined, request can an instance of JspRequest (for JSPs) * or a ServletRequest (FreeMarker) */ protected ActionContext readActionContext(Request request) { diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsPreparerFactory.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsPreparerFactory.java index e279adcb40..8630a061f6 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsPreparerFactory.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsPreparerFactory.java @@ -23,8 +23,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.message.ParameterizedMessage; -import org.apache.tiles.preparer.ViewPreparer; -import org.apache.tiles.preparer.factory.BasicPreparerFactory; +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.core.prepare.factory.BasicPreparerFactory; /** * This is a basic ViewPreparer factory that uses {@link ObjectFactory} to create the ViewPreparer diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java index e36b75d16c..8842578afc 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java @@ -25,10 +25,10 @@ import org.apache.struts2.tiles.annotation.TilesDefinitions; import org.apache.struts2.tiles.annotation.TilesPutAttribute; import org.apache.struts2.tiles.annotation.TilesPutListAttribute; -import org.apache.tiles.Attribute; -import org.apache.tiles.Definition; -import org.apache.tiles.Expression; -import org.apache.tiles.ListAttribute; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.ListAttribute; /** * Processes tiles annotations to create {@link Definition}s and @@ -123,7 +123,7 @@ protected Attribute buildTemplateAttribute(TilesDefinition tilesDef) { String templateType = getValueOrNull(tilesDef.templateType()); if (templateType != null) { attribute.setRenderer(templateType); - } else if (getValueOrNull(tilesDef.extend()) != null && templateType == null) { + } else if (getValueOrNull(tilesDef.extend()) != null) { attribute.setRenderer(null); } return attribute; diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java index 41b93a38fc..205476467d 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java @@ -24,25 +24,31 @@ import ognl.PropertyAccessor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.tiles.TilesContainer; -import org.apache.tiles.definition.DefinitionsFactory; -import org.apache.tiles.definition.pattern.DefinitionPatternMatcherFactory; -import org.apache.tiles.definition.pattern.PatternDefinitionResolver; -import org.apache.tiles.definition.pattern.PrefixedPatternDefinitionResolver; -import org.apache.tiles.definition.pattern.regexp.RegexpDefinitionPatternMatcherFactory; -import org.apache.tiles.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.BasicRendererFactory; +import org.apache.tiles.request.render.ChainedDelegateRenderer; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcherFactory; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PrefixedPatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.regexp.RegexpDefinitionPatternMatcherFactory; +import org.apache.tiles.core.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.BasicAttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.impl.DirectAttributeEvaluator; +import org.apache.tiles.core.factory.BasicTilesContainerFactory; +import org.apache.tiles.core.factory.TilesContainerFactoryException; +import org.apache.tiles.core.impl.mgmt.CachingTilesContainer; +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.core.prepare.factory.PreparerFactory; import org.apache.tiles.el.ELAttributeEvaluator; import org.apache.tiles.el.JspExpressionFactoryFactory; import org.apache.tiles.el.ScopeELResolver; import org.apache.tiles.el.TilesContextBeanELResolver; import org.apache.tiles.el.TilesContextELResolver; -import org.apache.tiles.evaluator.AttributeEvaluatorFactory; -import org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory; -import org.apache.tiles.evaluator.impl.DirectAttributeEvaluator; -import org.apache.tiles.factory.BasicTilesContainerFactory; -import org.apache.tiles.factory.TilesContainerFactoryException; -import org.apache.tiles.impl.mgmt.CachingTilesContainer; -import org.apache.tiles.locale.LocaleResolver; import org.apache.tiles.ognl.AnyScopePropertyAccessor; import org.apache.tiles.ognl.DelegatePropertyAccessor; import org.apache.tiles.ognl.NestedObjectDelegatePropertyAccessor; @@ -51,12 +57,6 @@ import org.apache.tiles.ognl.ScopePropertyAccessor; import org.apache.tiles.ognl.TilesApplicationContextNestedObjectExtractor; import org.apache.tiles.ognl.TilesContextPropertyAccessorDelegateFactory; -import org.apache.tiles.preparer.factory.PreparerFactory; -import org.apache.tiles.request.ApplicationContext; -import org.apache.tiles.request.ApplicationResource; -import org.apache.tiles.request.Request; -import org.apache.tiles.request.render.BasicRendererFactory; -import org.apache.tiles.request.render.ChainedDelegateRenderer; import org.apache.tiles.request.render.Renderer; import javax.el.ArrayELResolver; @@ -81,7 +81,7 @@ * - S2 ro access Struts' ValueStack * - OGNL * - EL - * + *

* If you need additional features create your own listener and factory, * you can base on code from Tiles' CompleteAutoloadTilesContainerFactory */ @@ -270,4 +270,4 @@ protected OGNLAttributeEvaluator createOGNLEvaluator() { } } -} \ No newline at end of file +} diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesInitializer.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesInitializer.java index 5170003a40..cb471a1ab5 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesInitializer.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesInitializer.java @@ -20,11 +20,11 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.tiles.definition.DefinitionsFactory; -import org.apache.tiles.factory.AbstractTilesContainerFactory; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.factory.AbstractTilesContainerFactory; +import org.apache.tiles.core.startup.AbstractTilesInitializer; import org.apache.tiles.request.ApplicationContext; import org.apache.tiles.request.servlet.ServletApplicationContext; -import org.apache.tiles.startup.AbstractTilesInitializer; import javax.servlet.ServletContext; diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesListener.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesListener.java index 38e5065522..5ebe36237e 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesListener.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesListener.java @@ -20,7 +20,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.tiles.startup.TilesInitializer; +import org.apache.tiles.core.startup.TilesInitializer; import org.apache.tiles.web.startup.AbstractTilesListener; /** @@ -37,4 +37,4 @@ protected TilesInitializer createTilesInitializer() { LOG.info("Starting Struts Tiles 3 integration ..."); return new StrutsTilesInitializer(); } -} \ No newline at end of file +} diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesLocaleResolver.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesLocaleResolver.java index 3e6524fa4b..0d3d3ec33e 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesLocaleResolver.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesLocaleResolver.java @@ -24,7 +24,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.ServletActionContext; -import org.apache.tiles.locale.LocaleResolver; +import org.apache.tiles.core.locale.LocaleResolver; import org.apache.tiles.request.Request; import org.apache.tiles.request.servlet.ServletUtil; @@ -33,7 +33,7 @@ public class StrutsTilesLocaleResolver implements LocaleResolver { - private static Logger LOG = LogManager.getLogger(StrutsTilesLocaleResolver.class); + private static final Logger LOG = LogManager.getLogger(StrutsTilesLocaleResolver.class); @Override public Locale resolveLocale(Request request) { diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java index 6a890d4a95..7af6069bba 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java @@ -24,7 +24,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tiles.request.ApplicationResource; -import org.apache.tiles.request.locale.URLApplicationResource; import org.apache.tiles.request.servlet.ServletApplicationContext; import javax.servlet.ServletContext; diff --git a/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java b/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java index a1e1c69d75..3ca20e4c19 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java @@ -29,58 +29,41 @@ import org.apache.struts2.result.ServletDispatcherResult; import org.apache.struts2.tiles.StrutsTilesAnnotationProcessor; import org.apache.struts2.tiles.annotation.TilesDefinition; -import org.apache.tiles.Definition; -import org.apache.tiles.TilesContainer; -import org.apache.tiles.TilesException; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.TilesException; import com.opensymphony.xwork2.ActionInvocation; -import org.apache.tiles.access.TilesAccess; -import org.apache.tiles.mgmt.MutableTilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.api.mgmt.MutableTilesContainer; import org.apache.tiles.request.ApplicationContext; import org.apache.tiles.request.Request; import org.apache.tiles.request.servlet.ServletRequest; import org.apache.tiles.request.servlet.ServletUtil; /** - * - * Renders a view using struts-tiles. - * - * - * - * In your web.xml file, you need to add a TilesListener. - * + * Renders a view using struts-tiles. In your web.xml file, you need to add a TilesListener. + *

* <listener> * <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class> * </listener> - * - * - * + *

* In struts.xml, use type="tiles" on your <result>. - * + *

* <action name="editUser" class="userAction" method="edit"> * <result name="success" type="tiles">userForm</result> * <result name="input" type="tiles">userList</result> * </action> - * - * - * - * - * + *

* Making this result type the default for the current package. - * + *

* <result-types> * <result-type name="tiles" * class="org.apache.struts2.views.tiles.TilesResult" default="true" /> * </result-types> - * - * - * - * + *

* You have to configure tiles itself. Therefore you can add tiles.xml either * to resources or WEB-INF. You may also use annotations like {@link TilesDefinition}. - * - * - * */ public class TilesResult extends ServletDispatcherResult { @@ -114,8 +97,7 @@ public void doExecute(String location, ActionInvocation invocation) throws Excep if (StringUtils.isEmpty(location)) { LOG.trace("location not set -> action must have one @TilesDefinition"); tilesDefinition = annotationProcessor.findAnnotation(action, null); - String tileName = StringUtils.isNotEmpty(tilesDefinition.name()) ? tilesDefinition.name() : actionName; - location = tileName; + location = StringUtils.isNotEmpty(tilesDefinition.name()) ? tilesDefinition.name() : actionName; LOG.debug("using new location name '{}' and @TilesDefinition '{}'", location, tilesDefinition); } setLocation(location); diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/Attribute.java b/plugins/tiles/src/main/java/org/apache/tiles/api/Attribute.java new file mode 100644 index 0000000000..65be6537ab --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/Attribute.java @@ -0,0 +1,366 @@ +/* + * 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.apache.tiles.api; + +import com.opensymphony.xwork2.util.TextParseUtil; +import org.apache.tiles.request.Request; + +import java.util.Iterator; +import java.util.Objects; +import java.util.Set; + +/** + * Common implementation of attribute definition. + */ +public class Attribute { + + /** + * The name of the template renderer. + */ + private static final String TEMPLATE_RENDERER = "template"; + + /** + * The roles that can render this attribute. + * + * @since 2.0.6 + */ + private Set roles = null; + + /** + * The value of the attribute. + */ + private Object value = null; + + /** + * The expression to evaluate. Ignored if {@link #value} is not null. + * + * @since 2.2.0 + */ + private Expression expressionObject = null; + + /** + * The renderer name of the attribute. Default names are string, + * template, definition, object. + */ + private String renderer = null; + + /** + * Constructor. + */ + public Attribute() { + } + + /** + * Constructor. + * + * @param value Object to store. + */ + public Attribute(Object value) { + this.value = value; + } + + /** + * Copy constructor. + * + * @param attribute The attribute to copy from. + */ + public Attribute(Attribute attribute) { + this.roles = attribute.roles; + this.value = attribute.getValue(); + if (attribute.expressionObject != null) { + this.expressionObject = new Expression(attribute.expressionObject); + } else { + this.expressionObject = null; + } + this.renderer = attribute.renderer; + } + + /** + * Constructor. + * + * @param value Object to store. + * @param role Asociated role. + */ + public Attribute(Object value, String role) { + this.value = value; + setRole(role); + } + + /** + * Constructor. + * + * @param value Object to store. If specified, the expression + * parameter will be ignored. + * @param expression The expression to be evaluated. Ignored if the + * value is not null. + * @param role Associated role. + * @param rendererName The renderer name. + * @since 2.2.0 + */ + public Attribute(Object value, Expression expression, String role, String rendererName) { + this.value = value; + this.expressionObject = expression; + this.renderer = rendererName; + setRole(role); + } + + /** + * Creates a template attribute, starting from the name of the template. + * + * @param template The template that will be rendered. + * @return The template attribute. + * @since 2.1.2 + */ + public static Attribute createTemplateAttribute(String template) { + Attribute attribute = new Attribute(); + attribute.setValue(template); + attribute.setRenderer(TEMPLATE_RENDERER); + return attribute; + } + + /** + * Creates a template attribute, starting from the name of the template. + * + * @param template The template that will be rendered. + * @param templateExpression The template expression that will be evaluated + * to a template. + * @param templateType The type, or renderer, of the template. If null, the + * default template will be used. + * @param role The comma-separated roles for which the template is + * authorized to be rendered. + * @return The template attribute. + * @since 2.2.2 + */ + public static Attribute createTemplateAttribute(String template, + String templateExpression, String templateType, String role) { + Attribute templateAttribute = createTemplateAttribute(template); + templateAttribute.setRole(role); + if (templateType != null) { + templateAttribute.setRenderer(templateType); + } + templateAttribute + .setExpressionObject(Expression + .createExpressionFromDescribedExpression(templateExpression)); + return templateAttribute; + } + + /** + * Get role. + * + * @return the name of the required role(s) + */ + public String getRole() { + String retValue = null; + + if (roles != null && !roles.isEmpty()) { + StringBuilder builder = new StringBuilder(); + Iterator roleIt = roles.iterator(); + if (roleIt.hasNext()) { + builder.append(roleIt.next()); + while (roleIt.hasNext()) { + builder.append(","); + builder.append(roleIt.next()); + } + retValue = builder.toString(); + } + } + + return retValue; + } + + /** + * Returns the roles that can render this attribute. + * + * @return The enabled roles. + * @since 2.0.6 + */ + public Set getRoles() { + return roles; + } + + /** + * Set role. + * + * @param role Associated role. + */ + public void setRole(String role) { + if (role != null && role.trim().length() > 0) { + roles = TextParseUtil.commaDelimitedStringToSet(role); + } else { + roles = null; + } + } + + /** + * Sets the roles that can render this attribute. + * + * @param roles The enabled roles. + * @since 2.0.6 + */ + public void setRoles(Set roles) { + this.roles = roles; + } + + /** + * Get value. + * + * @return the value + */ + public Object getValue() { + return value; + } + + /** + * Set value. + * + * @param value New value. + */ + public void setValue(Object value) { + this.value = value; + } + + /** + * Returns The expression to evaluate. Ignored if {@link #value} is not + * null. + * + * @return The expression to be evaluated. + * @since 2.2.0 + */ + public Expression getExpressionObject() { + return expressionObject; + } + + /** + * Sets The expression to evaluate. Ignored if {@link #value} is not + * null. + * + * @param expressionObject The expression to be evaluated. + * @since 2.2.0 + */ + public void setExpressionObject(Expression expressionObject) { + this.expressionObject = expressionObject; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return Objects.toString(value); + } + + /** + * Returns the renderer name to use. + * + * @return The renderer name. + * @since 2.1.0 + */ + public String getRenderer() { + return renderer; + } + + /** + * Sets the renderer name to use. + * + * @param rendererName The renderer. + * @since 2.1.0 + */ + public void setRenderer(String rendererName) { + this.renderer = rendererName; + } + + /** + * Inherits an attribute, i.e. overwrites null properties with the ones + * provided by the attribute. + * + * @param attribute The attribute to inherit. + * @since 2.1.2 + */ + public void inherit(Attribute attribute) { + if (value == null) { + value = attribute.getValue(); + } + Expression targetExpressionObject = attribute.getExpressionObject(); + if (targetExpressionObject != null + && (expressionObject == null || expressionObject + .getExpression() == null)) { + expressionObject = new Expression(targetExpressionObject); + } + if (roles == null || roles.isEmpty()) { + roles = attribute.getRoles(); + } + if (renderer == null) { + renderer = attribute.getRenderer(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null && value == null) { + return true; + } + if (!(obj instanceof Attribute)) { + return false; + } + Attribute attribute = (Attribute) obj; + return Objects.equals(value, attribute.value) + && Objects.equals(renderer, attribute.renderer) + && Objects.equals(roles, attribute.roles) + && Objects.equals(expressionObject, attribute.expressionObject); + } + + /** + * Checks if the current user can use this attribute. + * + * @param request The request context. + * @return true if the current user can see this attribute. + * @since 3.0.0 + */ + public boolean isPermitted(Request request) { + if (roles == null || roles.isEmpty()) { + return true; + } + + boolean retValue = false; + + for (Iterator roleIt = roles.iterator(); roleIt.hasNext() + && !retValue; ) { + retValue = request.isUserInRole(roleIt.next()); + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(value) + Objects.hashCode(renderer) + + Objects.hashCode(roles) + Objects.hashCode(expressionObject); + } + + public Attribute copy() { + return new Attribute(this); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/AttributeContext.java b/plugins/tiles/src/main/java/org/apache/tiles/api/AttributeContext.java new file mode 100644 index 0000000000..554bd9ec09 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/AttributeContext.java @@ -0,0 +1,161 @@ +/* + * 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.apache.tiles.api; + +import java.util.Map; +import java.util.Set; + +/** + * Encapsulation of the current state of execution. + * + * @since Tiles 2.0 + */ +public interface AttributeContext { + + /** + * Returns the attribute that will be used to render a template. + * + * @return The template attribute. + * @since 2.1.2 + */ + Attribute getTemplateAttribute(); + + /** + * Sets the template attribute, that will be used to render the template + * page. + * + * @param templateAttribute The template attribute. + * @since 2.1.2 + */ + void setTemplateAttribute(Attribute templateAttribute); + + /** + * Get associated preparer instance. + * + * @return The preparer name. + * @since 2.1.0 + */ + String getPreparer(); + + /** + * Set associated preparer instance. + * + * @param url The preparer name. + * @since 2.1.0 + */ + void setPreparer(String url); + + /** + * Add all attributes to the context. + * + * @param newAttributes the attributes to be added. + */ + void addAll(Map newAttributes); + + /** + * Copies the cascaded attributes to this attribute context. + * + * @param parent The parent context to be used. + * @since 2.1.0 + */ + void inheritCascadedAttributes(AttributeContext parent); + + /** + * Copies all missing attributes from the parent attribute + * context to this one. + * + * @param parent The attribute context to copy attributes from. + * @since 2.1.0 + */ + void inherit(AttributeContext parent); + + /** + * Retrieve the named attribute, either cascaded or not. + * + * @param name key name for the attribute. + * @return Attribute associated with the given name. + */ + Attribute getAttribute(String name); + + /** + * Retrieve the attribute that has been defined in this context (i.e. not + * cascaded). + * + * @param name key name for the attribute. + * @return Attribute The local attribute associated with the given name, if + * present, or null otherwise. + * @since 2.1.0 + */ + Attribute getLocalAttribute(String name); + + /** + * Retrieve the attribute that has been cascaded at upper levels. + * + * @param name key name for the attribute. + * @return Attribute The cascaded attribute associated with the given name, + * if present, or null otherwise. + * @since 2.1.0 + */ + Attribute getCascadedAttribute(String name); + + /** + * Returns the names of the local attributes, i.e. the one that have not + * been cascaded. + * + * @return The local attribute names. + * @since 2.1.0 + */ + Set getLocalAttributeNames(); + + /** + * Returns the names of the cascaded attributes. + * + * @return The cascaded attribute names. + * @since 2.1.0 + */ + Set getCascadedAttributeNames(); + + /** + * Add the specified attribute. The attribute value will be available only + * in the current context, i.e. it is like calling + * {@link AttributeContext#putAttribute(String, Attribute, boolean)} with + * cascade = false. + * + * @param name name of the attribute + * @param value value of the attribute + */ + void putAttribute(String name, Attribute value); + + /** + * Add the specified attribute. + * + * @param name name of the attribute + * @param value value of the attribute + * @param cascade If true, the attribute value will be + * available in all nested contexts. If false, it will be + * available only in the current context. + * @since 2.1.0 + */ + void putAttribute(String name, Attribute value, boolean cascade); + + /** + * Clear the attributes. + */ + void clear(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/BasicAttributeContext.java b/plugins/tiles/src/main/java/org/apache/tiles/api/BasicAttributeContext.java new file mode 100644 index 0000000000..cd12ea8607 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/BasicAttributeContext.java @@ -0,0 +1,462 @@ +/* + * 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.apache.tiles.api; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * Basic implementation for AttributeContext. + * + * @since 2.1.0 + */ +public class BasicAttributeContext implements AttributeContext, Serializable { + + /** + * The template attribute, to render a template. + * + * @since 2.1.2 + */ + protected Attribute templateAttribute; + + /** + * Associated ViewPreparer URL or classname, if defined. + * + * @since 2.1.0 + */ + protected String preparer = null; + + /** + * Template attributes. + * + * @since 2.1.0 + */ + protected Map attributes = null; + + /** + * Cascaded template attributes. + * + * @since 2.1.0 + */ + protected Map cascadedAttributes = null; + + /** + * Constructor. + * + * @since 2.1.0 + */ + public BasicAttributeContext() { + } + + /** + * Constructor. + * Create a context and set specified attributes. + * + * @param attributes Attributes to initialize context. + * @since 2.1.0 + */ + public BasicAttributeContext(Map attributes) { + if (attributes != null) { + this.attributes = deepCopyAttributeMap(attributes); + } + } + + /** + * Copy constructor. + * + * @param context The constructor to copy. + * @since 2.1.0 + */ + public BasicAttributeContext(AttributeContext context) { + if (context instanceof BasicAttributeContext) { + copyBasicAttributeContext((BasicAttributeContext) context); + } else { + Attribute parentTemplateAttribute = context.getTemplateAttribute(); + if (parentTemplateAttribute != null) { + this.templateAttribute = new Attribute(parentTemplateAttribute); + } + this.preparer = context.getPreparer(); + this.attributes = new HashMap<>(); + Set parentAttributeNames = context.getLocalAttributeNames(); + if (parentAttributeNames != null) { + for (String name : parentAttributeNames) { + attributes.put(name, new Attribute(context.getLocalAttribute(name))); + } + } + inheritCascadedAttributes(context); + } + } + + /** + * Copy constructor. + * + * @param context The constructor to copy. + * @since 2.1.0 + */ + public BasicAttributeContext(BasicAttributeContext context) { + copyBasicAttributeContext(context); + } + + /** + * {@inheritDoc} + */ + public Attribute getTemplateAttribute() { + return templateAttribute; + } + + /** + * {@inheritDoc} + */ + public void setTemplateAttribute(Attribute templateAttribute) { + this.templateAttribute = templateAttribute; + } + + /** + * {@inheritDoc} + */ + public String getPreparer() { + return preparer; + } + + /** + * {@inheritDoc} + */ + public void setPreparer(String url) { + this.preparer = url; + } + + /** + * {@inheritDoc} + */ + public void inheritCascadedAttributes(AttributeContext context) { + if (context instanceof BasicAttributeContext) { + if (((BasicAttributeContext) context).cascadedAttributes != null && !((BasicAttributeContext) context).cascadedAttributes.isEmpty()) { + cascadedAttributes = deepCopyAttributeMap(((BasicAttributeContext) context).cascadedAttributes); + } + } else { + this.cascadedAttributes = new HashMap<>(); + Set parentAttributeNames = context.getCascadedAttributeNames(); + if (parentAttributeNames != null) { + for (String name : parentAttributeNames) { + cascadedAttributes.put(name, new Attribute(context + .getCascadedAttribute(name))); + } + } + } + } + + /** + * {@inheritDoc} + */ + public void inherit(AttributeContext parent) { + if (parent instanceof BasicAttributeContext) { + inherit((BasicAttributeContext) parent); + } else { + // Inheriting template, roles and preparer. + Attribute parentTemplateAttribute = parent.getTemplateAttribute(); + inheritParentTemplateAttribute(parentTemplateAttribute); + if (preparer == null) { + preparer = parent.getPreparer(); + } + + // Inheriting attributes. + Set names = parent.getCascadedAttributeNames(); + if (names != null && !names.isEmpty()) { + for (String name : names) { + Attribute attribute = parent.getCascadedAttribute(name); + Attribute destAttribute = getCascadedAttribute(name); + if (destAttribute == null) { + putAttribute(name, attribute, true); + } else if (attribute instanceof ListAttribute + && destAttribute instanceof ListAttribute + && ((ListAttribute) destAttribute).isInherit()) { + ((ListAttribute) destAttribute).inherit((ListAttribute) attribute); + } + } + } + names = parent.getLocalAttributeNames(); + if (names != null && !names.isEmpty()) { + for (String name : names) { + Attribute attribute = parent.getLocalAttribute(name); + Attribute destAttribute = getLocalAttribute(name); + if (destAttribute == null) { + putAttribute(name, attribute, false); + } else if (attribute instanceof ListAttribute + && destAttribute instanceof ListAttribute + && ((ListAttribute) destAttribute).isInherit()) { + ((ListAttribute) destAttribute).inherit((ListAttribute) attribute); + } + } + } + } + } + + /** + * Inherits the attribute context, inheriting, i.e. copying if not present, + * the attributes. + * + * @param parent The attribute context to inherit. + * @since 2.1.0 + */ + public void inherit(BasicAttributeContext parent) { + // Set template, roles and preparer if not set. + inheritParentTemplateAttribute(parent.getTemplateAttribute()); + if (preparer == null) { + preparer = parent.preparer; + } + + // Sets attributes. + cascadedAttributes = addMissingAttributes(parent.cascadedAttributes, + cascadedAttributes); + attributes = addMissingAttributes(parent.attributes, attributes); + } + + /** + * Add all attributes to this context. + * Copies all the mappings from the specified attribute map to this context. + * New attribute mappings will replace any mappings that this context had for any of the keys + * currently in the specified attribute map. + * + * @param newAttributes Attributes to add. + * @since 2.1.0 + */ + public void addAll(Map newAttributes) { + if (newAttributes == null) { + return; + } + + if (attributes == null) { + attributes = new HashMap<>(newAttributes); + return; + } + + attributes.putAll(newAttributes); + } + + /** + * {@inheritDoc} + */ + public Attribute getAttribute(String name) { + Attribute retValue = null; + if (attributes != null) { + retValue = attributes.get(name); + } + + if (retValue == null && cascadedAttributes != null) { + retValue = cascadedAttributes.get(name); + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + public Attribute getLocalAttribute(String name) { + if (attributes == null) { + return null; + } + + return attributes.get(name); + } + + /** + * {@inheritDoc} + */ + public Attribute getCascadedAttribute(String name) { + if (cascadedAttributes == null) { + return null; + } + + return cascadedAttributes.get(name); + } + + /** + * {@inheritDoc} + */ + public Set getLocalAttributeNames() { + if (attributes != null && !attributes.isEmpty()) { + return attributes.keySet(); + } + return null; + } + + /** + * {@inheritDoc} + */ + public Set getCascadedAttributeNames() { + if (cascadedAttributes != null && !cascadedAttributes.isEmpty()) { + return cascadedAttributes.keySet(); + } + return null; + } + + /** + * {@inheritDoc} + */ + public void putAttribute(String name, Attribute value) { + if (attributes == null) { + attributes = new HashMap<>(); + } + + attributes.put(name, value); + } + + /** + * {@inheritDoc} + */ + public void putAttribute(String name, Attribute value, boolean cascade) { + Map mapToUse; + if (cascade) { + if (cascadedAttributes == null) { + cascadedAttributes = new HashMap<>(); + } + mapToUse = cascadedAttributes; + } else { + if (attributes == null) { + attributes = new HashMap<>(); + } + mapToUse = attributes; + } + mapToUse.put(name, value); + } + + /** + * {@inheritDoc} + */ + public void clear() { + templateAttribute = null; + preparer = null; + attributes.clear(); + cascadedAttributes.clear(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof BasicAttributeContext)) { + return false; + } + BasicAttributeContext bac = (BasicAttributeContext) obj; + return Objects.equals(templateAttribute, bac.templateAttribute) + && Objects.equals(preparer, bac.preparer) + && Objects.equals(attributes, bac.attributes) + && Objects.equals(cascadedAttributes, bac.cascadedAttributes); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(templateAttribute) + Objects.hashCode(preparer) + + Objects.hashCode(attributes) + + Objects.hashCode(cascadedAttributes); + } + + /** + * Inherits the parent template attribute. + * + * @param parentTemplateAttribute The parent template attribute. + */ + private void inheritParentTemplateAttribute( + Attribute parentTemplateAttribute) { + if (parentTemplateAttribute != null) { + if (templateAttribute == null) { + templateAttribute = new Attribute(parentTemplateAttribute); + } else { + templateAttribute.inherit(parentTemplateAttribute); + } + } + } + + /** + * Copies a BasicAttributeContext in an easier way. + * + * @param context The context to copy. + */ + private void copyBasicAttributeContext(BasicAttributeContext context) { + Attribute parentTemplateAttribute = context.getTemplateAttribute(); + if (parentTemplateAttribute != null) { + this.templateAttribute = new Attribute(parentTemplateAttribute); + } + preparer = context.preparer; + if (context.attributes != null && !context.attributes.isEmpty()) { + attributes = deepCopyAttributeMap(context.attributes); + } + if (context.cascadedAttributes != null && !context.cascadedAttributes.isEmpty()) { + cascadedAttributes = deepCopyAttributeMap(context.cascadedAttributes); + } + } + + /** + * Adds missing attributes to the destination map. + * + * @param source The source attribute map. + * @param destination The destination attribute map. + * @return The destination attribute map if not null, a new one otherwise. + */ + private Map addMissingAttributes(Map source, Map destination) { + if (source != null && !source.isEmpty()) { + if (destination == null) { + destination = new HashMap<>(); + } + for (Map.Entry entry : source.entrySet()) { + String key = entry.getKey(); + Attribute destAttribute = destination.get(key); + if (destAttribute == null) { + destination.put(key, entry.getValue()); + } else if (destAttribute instanceof ListAttribute + && entry.getValue() instanceof ListAttribute + && ((ListAttribute) destAttribute).isInherit()) { + ((ListAttribute) destAttribute) + .inherit((ListAttribute) entry.getValue()); + } + } + } + + return destination; + } + + /** + * Deep copies the attribute map, by creating clones (using copy + * constructors) of the attributes. + * + * @param attributes The attribute map to copy. + * @return The copied map. + */ + private Map deepCopyAttributeMap(Map attributes) { + Map retValue = new HashMap<>(attributes.size()); + for (Map.Entry entry : attributes.entrySet()) { + Attribute toCopy = entry.getValue(); + if (toCopy != null) { + retValue.put(entry.getKey(), toCopy.copy()); + } + } + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/Definition.java b/plugins/tiles/src/main/java/org/apache/tiles/api/Definition.java new file mode 100644 index 0000000000..54ac5e035c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/Definition.java @@ -0,0 +1,165 @@ +/* + * 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.apache.tiles.api; + +import java.util.Map; +import java.util.Objects; + +/** + * A definition, i.e. a template with (completely or not) filled attributes. + * Attributes of a template can be defined with the help of this class.
+ * It can be used as a data transfer object used for registering new + * definitions with the Container. + * + * @since Tiles 2.0 + */ +public class Definition extends BasicAttributeContext { + /** + * Extends attribute value. + */ + protected String inherit; + /** + * Definition name. + */ + protected String name = null; + + /** + * Constructor. + */ + public Definition() { + } + + /** + * Copy Constructor. + * Create a new definition initialized with parent definition. + * Do a shallow copy : attributes are shared between copies, but not the Map + * containing attributes. + * + * @param definition The definition to copy. + */ + public Definition(Definition definition) { + super(definition); + this.name = definition.name; + this.inherit = definition.inherit; + } + + /** + * Constructor. + * + * @param name The name of the definition. + * @param templateAttribute The template attribute of the definition. + * @param attributes The attribute map of the definition. + * @since 2.1.2 + */ + public Definition(String name, Attribute templateAttribute, + Map attributes) { + super(attributes); + this.name = name; + this.templateAttribute = templateAttribute; + } + + /** + * Access method for the name property. + * + * @return the current value of the name property + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param aName the new value of the name property + */ + public void setName(String aName) { + name = aName; + } + + /** + * Set extends. + * + * @param name Name of the extended definition. + */ + public void setExtends(String name) { + inherit = name; + } + + /** + * Get extends. + * + * @return Name of the extended definition. + */ + public String getExtends() { + return inherit; + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof Definition)) { + return false; + } + Definition def = (Definition) obj; + return Objects.equals(name, def.name) && Objects.equals(inherit, def.inherit) && super.equals(def); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(name) + Objects.hashCode(inherit) + super.hashCode(); + } + + /** + * Get extends flag. + * + * @return true if this definition extends another. + */ + public boolean isExtending() { + return inherit != null; + } + + /** + * Returns a description of the attributes. + * + * @return A string representation of the content of this definition. + */ + @Override + public String toString() { + return "{name=" + + name + + ", template=" + + (templateAttribute != null ? templateAttribute.getValue() : "") + + ", role=" + + (templateAttribute != null ? templateAttribute.getRoles() : "") + + ", preparerInstance=" + + preparer + + ", attributes=" + + attributes + + "}"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/Expression.java b/plugins/tiles/src/main/java/org/apache/tiles/api/Expression.java new file mode 100644 index 0000000000..38d152ccbd --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/Expression.java @@ -0,0 +1,165 @@ +/* + * 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.apache.tiles.api; + +import java.util.Objects; + +/** + * It is an expression, along with the expression language (e.g. EL, MVEL, OGNL) + * it is expressed with. + * + * @since 2.2.0 + */ +public class Expression { + + /** + * The expression itself. + */ + private final String expression; + + /** + * The language of the expression. + */ + private final String language; + + /** + * Constructor. + * + * @param expression The expression itself. + * @param language The language of the expression. + * @since 2.2.0 + */ + public Expression(String expression, String language) { + this.expression = expression; + this.language = language; + } + + /** + * Constructor, using the default (i.e. null) language. + * + * @param expression The expression itself. + * @since 2.2.0 + */ + public Expression(String expression) { + this(expression, null); + } + + /** + * Copy constructor. + * + * @param toCopy The expression to copy. + * @since 2.2.0 + */ + public Expression(Expression toCopy) { + this.expression = toCopy.expression; + this.language = toCopy.language; + } + + /** + * Creates an Expression object from a string in the form + * LANGUAGE:EXPRESSION. + * + * @param describedExpression The expression in the form + * LANGUAGE:EXPRESSION. The LANGUAGE part should be expressed + * only with letters and numbers. + * @return The created object, or null if the expression is null. + * @since 2.2.0 + */ + public static Expression createExpressionFromDescribedExpression(String describedExpression) { + if (describedExpression != null) { + String language = null; + String expression = describedExpression; + if (describedExpression.matches("[a-zA-Z0-9]+:.+")) { + language = describedExpression.substring(0, describedExpression.indexOf(':')); + expression = describedExpression.substring(describedExpression.indexOf(':') + 1); + } + return new Expression(expression, language); + } + + return null; + } + + /** + * Creates an Expression object from the expression and its language. + * + * @param expression The expression itself. + * @param language The language of the expression. + * @return The created object, or null if the expression is null. + * @since 2.2.0 + */ + public static Expression createExpression(String expression, String language) { + if (expression != null) { + return new Expression(expression, language); + } + + return null; + } + + /** + * Returns the expression string. + * + * @return The expression itself. + * @since 2.2.0 + */ + public String getExpression() { + return expression; + } + + /** + * Returns the language in which the expression is expressed. + * + * @return The expression language. + * @since 2.2.0 + */ + public String getLanguage() { + return language; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof Expression)) { + return false; + } + Expression exp = (Expression) obj; + return Objects.equals(expression, exp.expression) && Objects.equals(language, exp.language); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(expression) + Objects.hashCode(language); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return (language == null ? "DEFAULT" : language) + ":" + expression; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/ListAttribute.java b/plugins/tiles/src/main/java/org/apache/tiles/api/ListAttribute.java new file mode 100644 index 0000000000..67b3294437 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/ListAttribute.java @@ -0,0 +1,169 @@ +/* + * 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.apache.tiles.api; + +import java.util.ArrayList; +import java.util.List; + +/** + * An attribute as a List. + * This attribute associates a name with a list. The list can be found by the + * property name. + * Elements in list are retrieved using List methods. + * This class is used to read configuration files. + * + * @since 2.1.0 + */ +public class ListAttribute extends Attribute { + + /** + * If true, the attribute will put the elements of the attribute with the + * same name of the parent definition before the ones specified here. By + * default, it is 'false'. + */ + private boolean inherit = false; + + /** + * Constructor. + * + * @since 2.1.0 + */ + public ListAttribute() { + setValue(new ArrayList()); + } + + /** + * Copy constructor. + * + * @param toCopy The list attribute to copy. + * @since 2.1.3 + */ + public ListAttribute(ListAttribute toCopy) { + super(toCopy); + List attributesToCopy = toCopy.getValue(); + if (attributesToCopy != null) { + List attributes = new ArrayList<>(attributesToCopy.size()); + for (Attribute attribute : attributesToCopy) { + if (attribute != null) { + attributes.add(attribute.copy()); + } else { + attributes.add(null); + } + } + setValue(attributes); + } + this.inherit = toCopy.inherit; + } + + /** + * Sets the list of the attributes that are elements of this attribute. + * + * @param attributes The attributes. + * @since 3.0.0 + */ + public void setValue(List attributes) { + super.setValue(attributes); + } + + /** + * Returns the list of the attributes that are elements of this attribute. + * + * @return The attributes. + * @since 3.0.0 + */ + @SuppressWarnings("unchecked") + @Override + public List getValue() { + return (List) super.getValue(); + } + + /** + * Add an element in list. + * We use a property to avoid rewriting a new class. + * + * @param element XmlAttribute to add. + * @since 2.1.0 + */ + public void add(Attribute element) { + getValue().add(element); + } + + /** + * If true, the attribute will put the elements of the attribute with the + * same name of the parent definition before the ones specified here. By + * default, it is 'false' + * + * @param inherit The "inherit" value. + * @since 2.1.0 + */ + public void setInherit(boolean inherit) { + this.inherit = inherit; + } + + /** + * If true, the attribute will put the elements of the attribute with the + * same name of the parent definition before the ones specified here. By + * default, it is 'false' + * + * @return inherit The "inherit" value. + * @since 2.1.0 + */ + public boolean isInherit() { + return inherit; + } + + /** + * Inherits elements present in a "parent" list attribute. The elements will + * be put before the ones already present. + * + * @param parent The parent list attribute. + * @since 2.1.0 + */ + public void inherit(ListAttribute parent) { + List tempList = new ArrayList<>(); + tempList.addAll(parent.getValue()); + tempList.addAll(getValue()); + setValue(tempList); + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof ListAttribute)) { + return false; + } + ListAttribute attribute = (ListAttribute) obj; + return super.equals(attribute) && this.inherit == attribute.inherit; + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + return super.hashCode() + Boolean.valueOf(inherit).hashCode(); + } + + /** {@inheritDoc} */ + @Override + public ListAttribute copy() { + return new ListAttribute(this); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/NoSuchContainerException.java b/plugins/tiles/src/main/java/org/apache/tiles/api/NoSuchContainerException.java new file mode 100644 index 0000000000..6d6d193071 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/NoSuchContainerException.java @@ -0,0 +1,38 @@ +/* + * 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.apache.tiles.api; + +/** + * Indicates that a keyed container has not been found. + * + * @since 2.1.0 + */ +public class NoSuchContainerException extends TilesException { + + /** + * Constructor. + * + * @param message The detail message. + * @since 2.1.0 + */ + public NoSuchContainerException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainer.java b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainer.java new file mode 100644 index 0000000000..00afe9dace --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainer.java @@ -0,0 +1,137 @@ +/* + * 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.apache.tiles.api; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +import java.io.IOException; + +/** + * An encapsulation of the Tiles framework. This interface is + * used to expose tiles features to frameworks which leverage + * it as a plugin. It can alternately be used by web applications + * which would like a programmatic interface. + * + * @since 2.0 + */ +public interface TilesContainer { + + /** + * Retrieve the container's context. + * + * @return current application context + */ + ApplicationContext getApplicationContext(); + + /** + * Retrieve the attribute context of the current request. + * @param request The request. + * @return map of the attributes in the current attribute context. + */ + AttributeContext getAttributeContext(Request request); + + /** + * Starts a new context, where attribute values are stored independently of others.
+ * When the use of the contexts is finished, call{@link TilesContainer#endContext(Request)} + * + * @param request The request. + * @return The newly created context. + */ + AttributeContext startContext(Request request); + + /** + * Ends a context, where attribute values are stored independently of others.
+ * It must be called after a {@link TilesContainer#startContext(Request)} call. + * + * @param request The request. + */ + void endContext(Request request); + + /** + * Renders the current context, as it is. + * @param request The request. + * + * @since 2.1.0 + */ + void renderContext(Request request); + + /** + * Executes a preparer. + * + * @param preparer The name of the preparer to execute. + * @param request The request. + */ + void prepare(String preparer, Request request); + + /** + * Render the given tiles request. + * + * @param definition the current definition. + * @param request The request. + */ + void render(String definition, Request request); + + /** + * Renders the specified definition. + * @param definition The definition to render. + * @param request The request context. + */ + void render(Definition definition, Request request); + + /** + * Render the given Attribute. + * + * @param attribute The attribute to render. + * @param request The request. + * @throws IOException If something goes wrong during writing to the output. + * @since 2.1.2 + */ + void render(Attribute attribute, Request request) + throws IOException; + + /** + * Evaluates the given attribute. + * + * @param attribute The attribute to evaluate. + * @param request The request. + * @return The evaluated object. + * @since 2.1.0 + */ + Object evaluate(Attribute attribute, Request request); + + /** + * Returns a definition specifying its name. + * + * @param definitionName The name of the definition to find. + * @param request The request context. + * @return The definition, if found. + */ + Definition getDefinition(String definitionName, + Request request); + + /** + * Determine whether the definition exists. + * + * @param definition the name of the definition. + * @param request The request. + * @return true if the definition is found. + */ + boolean isValidDefinition(String definition, Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainerWrapper.java b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainerWrapper.java new file mode 100644 index 0000000000..e8707e34fb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainerWrapper.java @@ -0,0 +1,107 @@ +/* + * 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.apache.tiles.api; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +import java.io.IOException; + +/** + * Wraps a Tiles container to allow easy decoration. + */ +public class TilesContainerWrapper implements TilesContainer { + + /** + * The container to wrap. + */ + protected TilesContainer container; + + /** + * Constructor. + * + * @param container The container to wrap. + */ + public TilesContainerWrapper(TilesContainer container) { + this.container = container; + if (container == null) { + throw new NullPointerException("The wrapped container must be not null"); + } + } + + @Override + public void endContext(Request request) { + container.endContext(request); + } + + @Override + public Object evaluate(Attribute attribute, Request request) { + return container.evaluate(attribute, request); + } + + @Override + public ApplicationContext getApplicationContext() { + return container.getApplicationContext(); + } + + @Override + public AttributeContext getAttributeContext(Request request) { + return container.getAttributeContext(request); + } + + @Override + public Definition getDefinition(String definitionName, Request request) { + return container.getDefinition(definitionName, request); + } + + @Override + public boolean isValidDefinition(String definition, Request request) { + return container.isValidDefinition(definition, request); + } + + @Override + public void prepare(String preparer, Request request) { + container.prepare(preparer, request); + } + + @Override + public void render(String definition, Request request) { + container.render(definition, request); + } + + @Override + public void render(Definition definition, Request request) { + container.render(definition, request); + } + + @Override + public void render(Attribute attribute, Request request) throws IOException { + container.render(attribute, request); + } + + @Override + public void renderContext(Request request) { + container.renderContext(request); + } + + @Override + public AttributeContext startContext(Request request) { + return container.startContext(request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/TilesException.java b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesException.java new file mode 100644 index 0000000000..520c244198 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesException.java @@ -0,0 +1,66 @@ +/* + * 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.apache.tiles.api; + +/** + * Root class for all Tiles-exceptions. + */ +public class TilesException extends RuntimeException { + + /** + * Constructor. + */ + public TilesException() { + } + + /** + * Constructor. + * + * @param message The error or warning message. + */ + public TilesException(String message) { + super(message); + } + + /** + * Create a new TilesException wrapping an existing exception. + *

+ *

The existing exception will be embedded in the new + * one, and its message will become the default message for + * the TilesException.

+ * + * @param e The cause to be wrapped. + */ + public TilesException(Throwable e) { + super(e); + } + + /** + * Create a new TilesException from an existing exception. + *

+ *

The existing exception will be embedded in the new + * one, but the new exception will have its own message.

+ * + * @param message The detail message. + * @param e The cause to be wrapped. + */ + public TilesException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/access/TilesAccess.java b/plugins/tiles/src/main/java/org/apache/tiles/api/access/TilesAccess.java new file mode 100644 index 0000000000..81cf488649 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/access/TilesAccess.java @@ -0,0 +1,158 @@ +/* + * 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.apache.tiles.api.access; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.NoSuchContainerException; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +import java.util.Map; + +/** + * Provides static access to the Tiles container. + */ +public final class TilesAccess { + + private static final Logger LOG = LogManager.getLogger(TilesAccess.class); + + /** + * Name of the attribute used to store the current used container. + */ + public static final String CURRENT_CONTAINER_ATTRIBUTE_NAME = + "org.apache.tiles.servlet.context.ServletTilesRequestContext.CURRENT_CONTAINER_KEY"; + + /** + * Constructor, private to avoid instantiation. + */ + private TilesAccess() { + } + + /** + * The name of the attribute to use when getting and setting the container + * object in a context. + */ + public static final String CONTAINER_ATTRIBUTE = + "org.apache.tiles.CONTAINER"; + + /** + * Configures the container to be used in the application. + * + * @param context The Tiles application context object to use. + * @param container The container object to set. + * @param key The key under which the container will be stored. + * @since 2.1.2 + */ + public static void setContainer(ApplicationContext context, TilesContainer container, String key) { + if (key == null) { + key = CONTAINER_ATTRIBUTE; + } + + if (container == null) { + LOG.info("Removing TilesContext for context: {}", context.getClass().getName()); + context.getApplicationScope().remove(key); + } else { + LOG.info("Publishing TilesContext for context: {}", context.getClass().getName()); + context.getApplicationScope().put(key, container); + } + } + + /** + * Returns default the container to be used in the application. + * + * @param context The Tiles application context object to use. + * @return The default container object. + * @since 3.0.0 + */ + public static TilesContainer getContainer(ApplicationContext context) { + return getContainer(context, CONTAINER_ATTRIBUTE); + } + + /** + * Returns the container to be used in the application registered under a specific key. + * + * @param context The Tiles application context object to use. + * @param key The key under which the container will be stored. + * @return The container object. + * @since 3.0.0 + */ + public static TilesContainer getContainer(ApplicationContext context, + String key) { + if (key == null) { + key = CONTAINER_ATTRIBUTE; + } + + return (TilesContainer) context.getApplicationScope().get(key); + } + + /** + * Sets the current container to use in web pages. + * + * @param request The request to use. + * @param key The key under which the container is stored. + * @since 2.1.0 + */ + public static void setCurrentContainer(Request request, + String key) { + ApplicationContext applicationContext = request.getApplicationContext(); + TilesContainer container = getContainer(applicationContext, key); + if (container != null) { + request.getContext("request").put(CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + } else { + throw new NoSuchContainerException("The container with the key '" + + key + "' cannot be found"); + } + } + + /** + * Sets the current container to use in web pages. + * + * @param request The request to use. + * @param container The container to use as the current container. + * @since 2.1.0 + */ + public static void setCurrentContainer(Request request, TilesContainer container) { + if (container != null) { + request.getContext("request").put(CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + } else { + throw new NullPointerException("The container cannot be null"); + } + } + + /** + * Returns the current container that has been set, or the default one. + * + * @param request The request to use. + * @return The current Tiles container to use in web pages. + * @since 2.1.0 + */ + public static TilesContainer getCurrentContainer(Request request) { + ApplicationContext context = request.getApplicationContext(); + Map requestScope = request.getContext("request"); + TilesContainer container = (TilesContainer) requestScope.get(CURRENT_CONTAINER_ATTRIBUTE_NAME); + if (container == null) { + container = getContainer(context); + requestScope.put(CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + } + + return container; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/access/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/api/access/package-info.java new file mode 100644 index 0000000000..f6090a5747 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/access/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +/** + * Tiles access package. Utility classes to access Tiles funcionality from an application. + */ +package org.apache.tiles.api.access; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/MutableTilesContainer.java b/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/MutableTilesContainer.java new file mode 100644 index 0000000000..5348f239c2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/MutableTilesContainer.java @@ -0,0 +1,39 @@ +/* + * 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.apache.tiles.api.mgmt; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; + +/** + * Defines a mutable version of the TilesContainer. + * + * @since Tiles 2.0 + */ +public interface MutableTilesContainer extends TilesContainer { + + /** + * Register a new definition with the container. + * + * @param definition The definition to register. + * @param request TODO + */ + void register(Definition definition, Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/package-info.java new file mode 100644 index 0000000000..8a22e1cb54 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ +/** + * Classes and interfaces to be used when it is needed to create Tiles definitions + * during the execution of the application. + */ +package org.apache.tiles.api.mgmt; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/api/package-info.java new file mode 100644 index 0000000000..f19af6deff --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/package-info.java @@ -0,0 +1,385 @@ +/* + * 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. + */ +/** + * The Tiles taglib and framework allows building web pages by assembling reusable + pieces of pages, called Tiles. A Tiles is usually a simple JSP page. + +
+

Introduction

+ +

The Tiles framework allows building pages by assembling reusable Tiles. + As an example, the page in the next figure can be build by assembling a + header, a footer, a menu and a body.

+ +

doc-files/image001

+ +

Each Tiles (header, menu, body, ...) is a JSP page and can itself be build + by assembling other Tiles.

+ +

Using Tiles can be compared as using Java methods: You need to define the Tiles (the method body), and then you + can "call" this body anywhere you want, passing it some parameters. In Tiles, parameters are called + "attributes" in order to avoid confusion with the request parameters.

+ +

The Tiles body can be a simple JSP page, a Struts action or any URI pointing + to a resource inside the current web site.

+ +

Inserting the body, or calling it, is done with the tag <tiles:insert + ...> anywhere in a JSP page. Insertion can also be done by specifying + a definition name as the path of a Struts forward or as input, + forward or include attributes of a Struts action.

+ +

Tiles bodies are used to create layouts, reusable parts, ... Tiles insertions + are used to insert Tiles. The same Tiles can be reused several times in + the same site, or even in the same page.

+ +

Insertion of a Tiles body can be associated to a logical name in what Tiles calls a "definition". A + definition contains a logical name, a page used as body and some attribute values. The definition declaration + doesn't insert the associated Tiles body. It just associates it with the name. A definition name can be used + anywhere insertion of a Tiles body can occur. The associated Tiles body is then inserted with associated + attributes.

+ +

The definition declarations can be done in JSP pages or in one or more + centralized files. A definition can extend another one, overload some attributes, + add new attributes ... This allows the declaration of a "master" definition + declaring the common layout, header, menu and footer. All other definitions + extend this master layout thereby making it possible to change the entire + site look & feel simply by changing the master definition.

+
+
+

Simple Examples

+ +
+

Insert a JSP page

+
<tiles:insert page="/layouts/commonLayout.jsp" flush="true" />
+ 
+

This example inserts the specified page in place of the tag. The page attribute is any valid URL pointing to + a resource inside the current site.

+
+
+ + +

Insert a Tiles passing some attributes

+
+ <tiles:insert page="/layouts/classicLayout.jsp" flush=&quot;true">
+ <tiles:put name="title"  value="Page Title" />
+ <tiles:put name="header" value="/common/header.jsp" />
+ <tiles:put name="footer" value="/common/footer.jsp" />
+ <tiles:put name="menu"   value="/common/menu.jsp" />
+ <tiles:put name="body"   value="/tiles/mainBody.jsp" />
+ </tiles:insert>
+ 
+

This example inserts the specified page, passing it the attributes. Attributes + are stored in a Tiles context which is passed to the inserted pag and + can then be accesssed by their names.

+
+
+

Retrieve an attribute value as String

+
+ <tiles:getAsString name="title" />
+ 
+

This example retrieves the value of the attribute "title" and prints it as a String in the current + output stream. The method toString() is applied on the attribute value, allowing to pass any kind of object + as value.

+
+
+

Insert Tiles referenced by an attribute

+
+ <tiles:insert attribute='menu' />
+ 
+

This inserts the Tiles referenced by the attribute "menu" value. The + specified attribute value is first retrieved from current Tiles's context, + and then the value is used as a page target to insert.

+
+
+

Classic Layout

+ +

This example is a layout assembling a page in the classic header-footer-menu-body + fashion.

+
+ <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
+ <HTML>
+ <HEAD>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/layouts/stylesheet.css"
+ type="text/css"/>
+ <title><tiles:getAsString name="title"/></title>
+ </HEAD>
+ <body>
+ <table border="0" width="100%" cellspacing="5">
+ <tr>
+ <td colspan="2"><tiles:insert attribute="header" /></td>
+ </tr>
+ <tr>
+ <td width="140" valign="top">
+ <tiles:insert attribute='menu' />
+ </td>
+ <td valign="top"  align="left">
+ <tiles:insert attribute='body' />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <tiles:insert attribute="footer" />
+ </td>
+ </tr>
+ </table>
+ </body>
+ </html>
+ 
+

The layout is declared in a JSP page (ex: /layouts/classicLayout.jsp). + It can be used in conjunction with the tag described in "Insert + a page passing some attributes".

+
+
+
+

Definitions

+ +

A definition associates a logical name with the URL of a Tiles to be inserted + and some attribute values. A definition doesn't insert the Tiles. This is + done later using the definition name. A definition name can be inserted + as often as you want in your site, making it easy to reuse a Tiles.

+ +

A definition can extend another definition and overload some attributes + or add new ones. This makes easy factorization of definitions differing + by some attributes. For example, you can define a master definition declaring + the main header, menu, footer, and a default title. Then let each of your + page definitions extend this master definition and overload the title and + the body.

+ +

Definitions can be declared in a JSP page, or in one or more centralized + files. To enable the definitions from centralized files, you need to initialize + the "definitions factory&&quot; which will parse the definitions from the files + and provide them to the Tiles framework.

+ +
+

Enabling Definition Factory

+ +

To enable Tiles definitions described in one or more files, you need to write these files and to initialize the + definition factory.

+ +

Initialization is different depending on the Struts version you use, + or if you do not use Struts at all.

+ +
+

Struts1.1

+ +

Use the Tiles plug-in to enable Tiles definitions. This plug-in creates + the definition factory and passese it a configuration object populated + with parameters. Parameters can be specified in the web.xml file or + as plug-in parameters. The plug-in first reads parameters from web.xml, + and then overloads them with the ones found in the plug-in. All parameters + are optional and can be omitted. The plug-in should be declared in each + struts-config file:

+
+ <plug-in className=&&quot;org.apache.struts.tiles.TilesPlugin&&quot; >
+ <set-property property=&&quot;definitions-config&&quot;
+ value=&&quot;/WEB-INF/tiles-defs.xml,
+ /WEB-INF/tiles-tests-defs.xml,/WEB-INF/tiles-tutorial-defs.xml,
+ /WEB-INF/tiles-examples-defs.xml&&quot; />
+ <set-property property=&&quot;moduleAware&&quot; value=&&quot;true&&quot; />
+ <set-property
+ property=&&quot;org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE&&quot;
+ value=&&quot;true&&quot; />
+ </plug-in>
+ 
+
    +
  • definitions-config: (optional) +
      +
    • Specify configuration file names. There can be several comma separated file names (default: ?? ) +
    • +
    +
  • +
  • org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE: (optional) +
      +
    • Specify if XML parser should validate the Tiles configuration + file +
        +
      • true : validate. DTD should be specified in file header (default)
      • +
      • false : no validation
      • + +
      +
    • +
    +
  • + +
  • moduleAware: (optional) +
      +
    • Specify if the Tiles definition factory is module aware. If true (default), + there will be one factory for each Struts module. + If false, there will be one common factory for all module. In this later case, + it is still needed to declare one plugin per module. The factory will be + initialized with parameters found in the first initialized plugin (generally the + one associated with the default module). +
        +
      • true : Tiles framework is module aware
      • +
      • false :Tiles framework has one single factoy shared among modules (default)
      • +
      +
    • +
    +
  • + +
  • tilesUtilImplClassname: (optional - for advanced user) +
      +
    • Specify The classname of the TilesUtil implementation to use. The specified class should + be a subclass of TilesUtilStrutsImpl. This option disable the moduleAware option. +
      Specifying &&"TilesUtilStrutsImpl&&" is equivalent to moduleAware = + false. +
      Specifying &&"TilesUtilStrutsModuleImpl&&" is equivalent to moduleAware + = true. + This option is taken into account only once, when it is first encountered. To avoid problems, + it is advice to specify the same values in all TilesPlugin declaration. +
    • +
    +
  • + +
+

The TilesPlugin class creates one definition factory for each struts module. +

+ +

+ If the flag moduleAware is false, only one shared factory is created for all modules. + In this later case, the factory is initialized with parameters found in the first plugin. + The plugins should be declared in all modules, and the moduleAware flag should be + the same for the entire application.

+ +

+ Paths found in Tiles definitions are relative to the main context.

+ +

You don't need to specify a TilesRequestProcessor, this is automatically + done by the plug-in. If, however, you want to specify your own RequestProcessor, + it should extend the TilesRequestProcessor. The plug-in checks this + constraint.

+
+
+

Struts1.0.x

+ +

You need to use a special servlet extending the Struts servlet. This is specified in the web.xml file of your + application:

+
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.tiles.web.startup.TilesServlet</servlet-class>
+ <!-- Tiles Servlet parameter
+ Specify configuration file names. There can be several comma
+ separated file names
+ -->
+ <init-param>
+ <param-name>definitions-config</param-name>
+ <param-value>/WEB-INF/tiles-defs.xml</param-value>
+ </init-param>
+ <!-- Tiles Servlet parameter
+ Specify if XML parser should validate the Tiles configuration file(s).
+ true : validate. DTD should be specified in file header.
+ false : no validation
+ -->
+ <init-param>
+ <param-name>org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ ...
+ </servlet>
+ 
+
+
+

Without Struts

+ +

Tiles can be used without Struts. To initialize the definition factory, you can use the provided servlet. Declare + it in the web.xml file of your application:

+
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.struts.tiles.TilesServlet</servlet-class>
+
+
+ <init-param>
+ <param-name>definitions-config</param-name>
+ <param-value>/WEB-INF/tiles-defs.xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ ...
+ 
+

The parameters are the same as for Struts1.1 or 1.0.

+
+
+
+

Definition File Syntax

+ +

The definition file syntax can be found in the + tiles-config_2_0.dtd file. +

+ +

Following is a simple example:

+
+ <!DOCTYPE tiles-definitions PUBLIC
+ &&quot;-//Apache Software Foundation//DTD Tiles Configuration//EN&&quot;
+ &&quot;http://tiles.apache.org/dtds/tiles-config_2_0.dtd&&quot;>
+
+ <!-- Definitions for Tiles documentation   -->
+ <tiles-definitions>
+
+ <!-- ========================================================== -->
+ <!-- Master definition                                          -->
+ <!-- ========================================================== -->
+ <!-- Main page layout used as a root for other page definitions -->
+
+ <definition name=&&quot;site.mainLayout&&quot;
+   template=&&quot;/layouts/classicLayout.jsp&&quot;>
+ <put name=&&quot;title&&quot;  value=&&quot;Tiles Blank Site&&quot; />
+ <put name=&&quot;header&&quot; value=&&quot;/tiles/common/header.jsp&&quot; />
+ <put name=&&quot;menu&&quot;   value=&&quot;site.menu.bar&&quot; />
+ <put name=&&quot;footer&&quot; value=&&quot;/tiles/common/footer.jsp&&quot; />
+ <put name=&&quot;body&&quot;   value=&&quot;/tiles/body.jsp&&quot; />
+ </definition>
+
+ <!-- ========================================================== -->
+ <!-- Index page definition                                      -->
+ <!-- ========================================================== -->
+ <!-- This definition inherits from the main definition.
+ It overloads the page title and the body used.
+ Use the same mechanism to define new pages sharing common
+ properties (here header, menu, footer, layout)
+ -->
+
+ <definition name=&&quot;site.index.page&&quot;
+   extends=&&quot;site.mainLayout&&quot; >
+ <put name=&&quot;title&&quot;  value=&&quot;Tiles Blank Site Index&&quot; />
+ <put name=&&quot;body&&quot;   value=&&quot;/tiles/body.jsp&&quot; />
+ </definition>
+
+ </tiles-definition>
+ 
+
+
+

Debugging

+ +

To debug a page made of Tiles, you can use following advices:

+
    +
  • Check each Tiles separatly. Try to access nested Tiles directly to test + if thes work properly. +
  • +
  • Enable Tiles logging. See the commons-logging package help.
  • +
+
+
+ + */ +package org.apache.tiles.api; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/PreparerException.java b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/PreparerException.java new file mode 100644 index 0000000000..87ba1f1f33 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/PreparerException.java @@ -0,0 +1,67 @@ +/* + * 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.apache.tiles.api.preparer; + +import org.apache.tiles.api.TilesException; + +/** + *

+ * Thrown when an exception occurs while processing + * a prepare request. + *

+ * + * @since Tiles 2.0 + */ +public class PreparerException extends TilesException { + + /** + * Constructor. + */ + public PreparerException() { + super(); + } + + /** + * Constructor. + * + * @param e The cause exception. + */ + public PreparerException(Throwable e) { + super(e); + } + + /** + * Constructor. + * + * @param message The message to include. + */ + public PreparerException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param message The message to include. + * @param e The cause exception. + */ + public PreparerException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/ViewPreparer.java b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/ViewPreparer.java new file mode 100644 index 0000000000..9abf720a6f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/ViewPreparer.java @@ -0,0 +1,54 @@ +/* + * 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.apache.tiles.api.preparer; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.request.Request; + +/** + *

+ * Executed prior to rendering a view. + *

+ * + *

+ * A view preparer is typically used to provide last minute + * translations of the data within the attribute context. + * A preparer is not intended to replace the controller within an + * MVC architecture. + *

+ * + * See + *
    + *
  • <insert>
  • + *
  • <definition>
  • + *
> + */ +public interface ViewPreparer { + + /** + * Method associated to a tile and called immediately before the tile + * is included. + * + * @param tilesContext Current tiles application context. + * @param attributeContext Current tile context. + * @throws PreparerException If something goes wrong during execution. + */ + void execute(Request tilesContext, + AttributeContext attributeContext); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/package-info.java new file mode 100644 index 0000000000..a8fcab1fdd --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/package-info.java @@ -0,0 +1,26 @@ +/* + * 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. + */ +/** + * "View preparers" are objects that allows the "preparation" of a Tiles artifact + * (definition, template or attribute) before it is rendered.
+ * It is useful, for example, when a view item should be built and stored in a + * particular context (e.g. a menu) and then rendered. + */ +package org.apache.tiles.api.preparer; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/AutotagRuntimeException.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/AutotagRuntimeException.java new file mode 100644 index 0000000000..188dae2695 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/AutotagRuntimeException.java @@ -0,0 +1,60 @@ +/* + * 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.apache.tiles.autotag.core; + +/** + * Generic exception for Autotag. + */ +public class AutotagRuntimeException extends RuntimeException { + + /** + * Constructor. + */ + public AutotagRuntimeException() { + } + + /** + * Constructor. + * + * @param message The message of the exception. + */ + public AutotagRuntimeException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param cause The cause. + */ + public AutotagRuntimeException(Throwable cause) { + super(cause); + } + + /** + * Constructor. + * + * @param message The message of the exception. + * @param cause The cause. + */ + public AutotagRuntimeException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AbstractModelBody.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AbstractModelBody.java new file mode 100644 index 0000000000..b1a937e734 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AbstractModelBody.java @@ -0,0 +1,80 @@ +/* + * 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.apache.tiles.autotag.core.runtime; + +import org.apache.tiles.autotag.core.runtime.util.NullWriter; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.regex.Pattern; + +/** + * Base class for the abstraction of the body. + */ +public abstract class AbstractModelBody implements ModelBody { + + // precompiled the pattern to avoid compiling on every method call + private static final Pattern PATTERN = Pattern.compile("^\\s*$"); + + /** + * The default writer to use. + */ + private final Writer defaultWriter; + + /** + * Constructor. + * + * @param defaultWriter The default writer to use. + */ + public AbstractModelBody(Writer defaultWriter) { + this.defaultWriter = defaultWriter; + } + + @Override + public void evaluate() throws IOException { + evaluate(defaultWriter); + } + + @Override + public String evaluateAsString() throws IOException { + StringWriter writer = new StringWriter(); + try { + evaluate(writer); + } finally { + writer.close(); + } + String body = writer.toString(); + if (body != null) { + body = PATTERN.matcher(body).replaceAll(""); + if (body.length() == 0) { + body = null; + } + } + return body; + } + + @Override + public void evaluateWithoutWriting() throws IOException { + try (NullWriter writer = new NullWriter()) { + evaluate(writer); + } + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AutotagRuntime.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AutotagRuntime.java new file mode 100644 index 0000000000..f95e39d77c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AutotagRuntime.java @@ -0,0 +1,49 @@ +/* + * 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.apache.tiles.autotag.core.runtime; + +/** + * Builder interface for creating requests. + * The implementations are expected to provide a default constructor, + * and to implement another interface that can be used to provide the + * parameters needed to build the actual request object. + */ +public interface AutotagRuntime { + /** + * Creates a new Request instance. + * + * @return The Request. + */ + R createRequest(); + + /** + * Creates a new ModelBody instance to match the request. + * + * @return The ModelBody. + */ + ModelBody createModelBody(); + + /** + * Extracts a parameter from the tag. + * @param name The name of the parameter. + * @param defaultValue The default value if none is specified. + * @return The value of the parameter. + */ + T getParameter(String name, Class type, T defaultValue); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/ModelBody.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/ModelBody.java new file mode 100644 index 0000000000..0f97ec0d04 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/ModelBody.java @@ -0,0 +1,58 @@ +/* + * 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.apache.tiles.autotag.core.runtime; + +import java.io.IOException; +import java.io.Writer; + +/** + * Abstracts a tag/directive body. + */ +public interface ModelBody { + + /** + * Evaluates a body and returns it as a string. + * + * @return The body, as a string. + * @throws IOException If something goes wrong. + */ + String evaluateAsString() throws IOException; + + /** + * Evaluates a body, but discards result. + * + * @throws IOException If something goes wrong. + */ + void evaluateWithoutWriting() throws IOException; + + /** + * Evaluates the body and writes in the default writer. + * + * @throws IOException If something goes wrong. + */ + void evaluate() throws IOException; + + /** + * Evaluates the body and writes the result in the writer. + * + * @param writer The writer to write the result into. + * @throws IOException If something goes wrong. + */ + void evaluate(Writer writer) throws IOException; +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/Parameter.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/Parameter.java new file mode 100644 index 0000000000..8833eddeb1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/Parameter.java @@ -0,0 +1,52 @@ +/* + * 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.apache.tiles.autotag.core.runtime.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Specifies behaviour for a parameter of the "execute" method of a template class. + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.PARAMETER) +public @interface Parameter { + + /** + * Indicates to use the parameter name itself for the exported name. + */ + String SAME_NAME = "USE THE SAME NAME"; + + /** + * Returns the name of the exported property name. + */ + String name() default SAME_NAME; + + /** + * Indicates that this parameter is required. + */ + boolean required() default false; + + /** + * Indicates the default value, as it will be written in Java code. + */ + String defaultValue() default "null"; +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/package-info.java new file mode 100644 index 0000000000..2b68de79df --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Annotations to be used in template classes. + */ +package org.apache.tiles.autotag.core.runtime.annotation; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/package-info.java new file mode 100644 index 0000000000..8d7b724833 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Runtime part for all Autotag generated code. + */ +package org.apache.tiles.autotag.core.runtime; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/NullWriter.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/NullWriter.java new file mode 100644 index 0000000000..4905e6c634 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/NullWriter.java @@ -0,0 +1,46 @@ +/* + * 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.apache.tiles.autotag.core.runtime.util; + +import java.io.Writer; + +/** + * A writer that does not write anything. + */ +public class NullWriter extends Writer { + + /** {@inheritDoc} */ + @Override + public void close() { + // Does nothing + } + + /** {@inheritDoc} */ + @Override + public void flush() { + // Does nothing + } + + /** {@inheritDoc} */ + @Override + public void write(char[] cbuf, int off, int len) { + // Does nothing + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/package-info.java new file mode 100644 index 0000000000..76efc98f13 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Utilities for Autotag core runtime. + */ +package org.apache.tiles.autotag.core.runtime.util; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelGenerator.java new file mode 100644 index 0000000000..8c3520e91b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelGenerator.java @@ -0,0 +1,63 @@ +/* + * 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.apache.tiles.autotag.freemarker; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateClassGenerator; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates a single Freemarker directive model, given a template class. + */ +public class FMModelGenerator extends AbstractTemplateClassGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public FMModelGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return packageName.replaceAll("\\.", "/"); + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return clazz.getTagClassPrefix() + "FMModel.java"; + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return "/org/apache/tiles/autotag/freemarker/fmModel.vm"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGenerator.java new file mode 100644 index 0000000000..6c045a5358 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGenerator.java @@ -0,0 +1,61 @@ +/* + * 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.apache.tiles.autotag.freemarker; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateSuiteGenerator; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates the model repository, given the template suite. + */ +public class FMModelRepositoryGenerator extends AbstractTemplateSuiteGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public FMModelRepositoryGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "/org/apache/tiles/autotag/freemarker/repository.vm"; + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, Map parameters) { + String name = suite.getName(); + return name.substring(0, 1).toUpperCase() + name.substring(1) + "FMModelRepository.java"; + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return packageName.replaceAll("\\.", "/"); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactory.java new file mode 100644 index 0000000000..b13b7a37c6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactory.java @@ -0,0 +1,69 @@ +/* + * 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.apache.tiles.autotag.freemarker; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.tiles.autotag.generate.TemplateGeneratorFactory; +import org.apache.velocity.app.VelocityEngine; + +/** + * Creates a template generator that generates code for Freemarker. + */ +public class FMTemplateGeneratorFactory implements TemplateGeneratorFactory { + + /** + * Location of the file. + */ + private File classesOutputDirectory; + + /** + * The Velocity engine. + */ + private VelocityEngine velocityEngine; + + /** + * The template generator builder. + */ + private TemplateGeneratorBuilder templateGeneratorBuilder; + + /** + * Constructor. + * + * @param classesOutputDirectory Directory where code will be placed. + * @param velocityEngine The Velocity engine. + * @param templateGeneratorBuilder The template generator builder. + */ + public FMTemplateGeneratorFactory(File classesOutputDirectory, VelocityEngine velocityEngine, + TemplateGeneratorBuilder templateGeneratorBuilder) { + this.classesOutputDirectory = classesOutputDirectory; + this.velocityEngine = velocityEngine; + this.templateGeneratorBuilder = templateGeneratorBuilder; + } + + @Override + public TemplateGenerator createTemplateGenerator() { + return templateGeneratorBuilder.setClassesOutputDirectory(classesOutputDirectory) + .addClassesTemplateSuiteGenerator(new FMModelRepositoryGenerator(velocityEngine)) + .addClassesTemplateClassGenerator(new FMModelGenerator(velocityEngine)).build(); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/package-info.java new file mode 100644 index 0000000000..f891ee3474 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1044819 2010-12-12 13:29:34Z apetrelli $ + * + * 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. + */ +/** + * Autotag support for Freemarker. + */ +package org.apache.tiles.autotag.freemarker; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGenerator.java new file mode 100644 index 0000000000..009d6d1a55 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGenerator.java @@ -0,0 +1,143 @@ +/* + * 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.apache.tiles.autotag.generate; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.Map; + +import org.apache.tiles.autotag.core.AutotagRuntimeException; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.tiles.autotag.tool.StringTool; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.exception.ResourceNotFoundException; + +/** + * A base template class generator. + */ +public abstract class AbstractTemplateClassGenerator implements + TemplateClassGenerator { + + /** + * The Velocity engine to use. + */ + private VelocityEngine velocityEngine; + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public AbstractTemplateClassGenerator(VelocityEngine velocityEngine) { + this.velocityEngine = velocityEngine; + } + + @Override + public void generate(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + File dir = new File(directory, getDirectoryName(directory, packageName, + suite, clazz, parameters, runtimeClass, requestClass)); + dir.mkdirs(); + File file = new File(dir, getFilename(dir, packageName, suite, clazz, parameters, runtimeClass, requestClass)); + VelocityContext context = new VelocityContext(); + context.put("packageName", packageName); + context.put("suite", suite); + context.put("clazz", clazz); + context.put("stringTool", new StringTool()); + context.put("parameters", parameters); + context.put("runtimeClass", runtimeClass); + context.put("requestClass", requestClass); + try { + file.createNewFile(); + Template template = velocityEngine.getTemplate(getTemplatePath(dir, + packageName, suite, clazz, parameters, runtimeClass, requestClass)); + Writer writer = new FileWriter(file); + try { + template.merge(context, writer); + } finally { + writer.close(); + } + } catch (ResourceNotFoundException e) { + throw new AutotagRuntimeException("Cannot find template resource", + e); + } catch (ParseErrorException e) { + throw new AutotagRuntimeException( + "The template resource is not parseable", e); + } catch (IOException e) { + throw new AutotagRuntimeException( + "I/O Exception when generating file", e); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new AutotagRuntimeException( + "Another generic exception while parsing the template resource", + e); + } + } + + /** + * Calculates and returns the template path. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param clazz The template class. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getTemplatePath(File directory, + String packageName, TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass); + + /** + * Calculates and returns the filename of the generated file. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param clazz The template class. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getFilename(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, String runtimeClass, + String requestClass); + + /** + * Calculates and returns the directory where the file will be written.. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param clazz The template class. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getDirectoryName(File directory, + String packageName, TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass); + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGenerator.java new file mode 100644 index 0000000000..16e3234b67 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGenerator.java @@ -0,0 +1,128 @@ +/* + * 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.apache.tiles.autotag.generate; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.Map; + +import org.apache.tiles.autotag.core.AutotagRuntimeException; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.tiles.autotag.tool.StringTool; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.exception.ResourceNotFoundException; + +/** + * A base template suite generator. + */ +public abstract class AbstractTemplateSuiteGenerator implements TemplateSuiteGenerator { + + /** + * The velocity engine. + */ + private VelocityEngine velocityEngine; + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public AbstractTemplateSuiteGenerator(VelocityEngine velocityEngine) { + this.velocityEngine = velocityEngine; + } + + @Override + public void generate(File directory, String packageName, TemplateSuite suite, Map parameters) { + File dir = new File(directory, getDirectoryName(directory, packageName, suite, parameters)); + dir.mkdirs(); + File file = new File(dir, getFilename(dir, packageName, suite, parameters)); + VelocityContext context = new VelocityContext(); + context.put("packageName", packageName); + context.put("suite", suite); + context.put("stringTool", new StringTool()); + context.put("parameters", parameters); + try { + file.createNewFile(); + Template template = velocityEngine.getTemplate(getTemplatePath(dir, + packageName, suite, parameters)); + Writer writer = new FileWriter(file); + try { + template.merge(context, writer); + } finally { + writer.close(); + } + } catch (ResourceNotFoundException e) { + throw new AutotagRuntimeException("Cannot find template resource", e); + } catch (ParseErrorException e) { + throw new AutotagRuntimeException("The template resource is not parseable", e); + } catch (IOException e) { + throw new AutotagRuntimeException( + "I/O Exception when generating file", e); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new AutotagRuntimeException( + "Another generic exception while parsing the template resource", + e); + } + } + + /** + * Calculates and returns the template path. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getTemplatePath(File directory, + String packageName, TemplateSuite suite, + Map parameters); + + /** + * Calculates and returns the filename of the generated file. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getFilename(File directory, String packageName, + TemplateSuite suite, Map parameters); + + /** + * Calculates and returns the directory where the file will be written.. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getDirectoryName(File directory, + String packageName, TemplateSuite suite, + Map parameters); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java new file mode 100644 index 0000000000..e9b27b060c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java @@ -0,0 +1,187 @@ +/* + * 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.apache.tiles.autotag.generate; + +import java.io.File; +import java.util.List; +import java.util.Map; + +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; + +/** + * The basic template generator. Use {@link TemplateGeneratorBuilder} to + * create instances of this class. + */ +class BasicTemplateGenerator implements TemplateGenerator { + + /** + * The template suite generators. + */ + private List templateSuiteGenerators; + + /** + * The template class generators. + */ + private List templateClassGenerators; + + /** + * Indicates that this generator generates resources. + */ + private boolean generatingResources = false; + + /** + * Indicates that this generator generates classes. + */ + private boolean generatingClasses = false; + + /** + * Constructor. + * + * @param templateSuiteGenerators The template suite generators. + * @param templateClassGenerators The template class generators. + * @param generatingClasses Indicates that this generator generates classes. + * @param generatingResources Indicates that this generator generates resources. + */ + BasicTemplateGenerator( + List templateSuiteGenerators, + List templateClassGenerators, + boolean generatingClasses, boolean generatingResources) { + this.templateSuiteGenerators = templateSuiteGenerators; + this.templateClassGenerators = templateClassGenerators; + this.generatingClasses = generatingClasses; + this.generatingResources = generatingResources; + } + + + + @Override + public void generate(String packageName, TemplateSuite suite, Map parameters, + String runtimeClass, String requestClass) { + for (TSGeneratorDirectoryPair pair : templateSuiteGenerators) { + pair.getGenerator().generate(pair.getDirectory(), packageName, suite, parameters); + } + for (TemplateClass templateClass : suite.getTemplateClasses()) { + for (TCGeneratorDirectoryPair pair : templateClassGenerators) { + pair.getGenerator().generate(pair.getDirectory(), packageName, + suite, templateClass, parameters, runtimeClass, requestClass); + } + } + } + + /** + * A pair of a template suite generator and a directory. + */ + static class TSGeneratorDirectoryPair { + /** + * The directory where files are generated. + */ + private File directory; + + /** + * The generator. + */ + private TemplateSuiteGenerator generator; + + /** + * Constructor. + * + * @param directory The directory where files are generated. + * @param generator The generator. + */ + public TSGeneratorDirectoryPair(File directory, + TemplateSuiteGenerator generator) { + this.directory = directory; + this.generator = generator; + } + + /** + * Returns the directory where files are generated. + * + * @return The directory where files are generated. + */ + public File getDirectory() { + return directory; + } + + /** + * Returns the generator. + * + * @return The generator. + */ + public TemplateSuiteGenerator getGenerator() { + return generator; + } + } + + /** + * A pair of a template class generator and a directory. + */ + static class TCGeneratorDirectoryPair { + /** + * The directory where files are generated. + */ + private File directory; + + /** + * The generator. + */ + private TemplateClassGenerator generator; + + /** + * Constructor. + * + * @param directory The directory where files are generated. + * @param generator The generator. + */ + public TCGeneratorDirectoryPair(File directory, + TemplateClassGenerator generator) { + this.directory = directory; + this.generator = generator; + } + + /** + * Returns the directory where files are generated. + * + * @return The directory where files are generated. + */ + public File getDirectory() { + return directory; + } + + /** + * Returns the generator. + * + * @return The generator. + */ + public TemplateClassGenerator getGenerator() { + return generator; + } + } + + @Override + public boolean isGeneratingResources() { + return generatingResources; + } + + @Override + public boolean isGeneratingClasses() { + return generatingClasses; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateClassGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateClassGenerator.java new file mode 100644 index 0000000000..3d958beef3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateClassGenerator.java @@ -0,0 +1,45 @@ +/* + * 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.apache.tiles.autotag.generate; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; + +/** + * Generates code from a parsed class. + */ +public interface TemplateClassGenerator { + + /** + * Generates the code. + * + * @param directory The base directory where the code will be put. + * @param packageName The package name. + * @param suite The template suite. + * @param clazz The template class. + * @param parameters Configuration parameters. + * @param runtimeClass The RequestBuilder implementation. + */ + void generate(File directory, String packageName, TemplateSuite suite, + TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGenerator.java new file mode 100644 index 0000000000..9e462ff2d7 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGenerator.java @@ -0,0 +1,56 @@ +/* + * 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.apache.tiles.autotag.generate; + + +import java.util.Map; + +import org.apache.tiles.autotag.model.TemplateSuite; + +/** + * Generates all the code for a template suite. + */ +public interface TemplateGenerator { + + /** + * Generates the code. + * + * @param packageName The package name. + * @param suite The template suite. + * @param parameters Configuration parameters. + * @param runtimeClass The RequestBuilder implementation. + * @param requestClass The request class to use. + */ + void generate(String packageName, TemplateSuite suite, Map parameters, + String runtimeClass, String requestClass); + + /** + * Indicates that this generator generates resources. + * + * @return true if the generator generates resources. + */ + boolean isGeneratingResources(); + + /** + * Indicates that this generator generates classes. + * + * @return true if the generator generates classes. + */ + boolean isGeneratingClasses(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilder.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilder.java new file mode 100644 index 0000000000..943175da68 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilder.java @@ -0,0 +1,180 @@ +/* + * 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.apache.tiles.autotag.generate; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tiles.autotag.generate.BasicTemplateGenerator.TCGeneratorDirectoryPair; +import org.apache.tiles.autotag.generate.BasicTemplateGenerator.TSGeneratorDirectoryPair; + +/** + * Builds a TemplateGenerator. + */ +public class TemplateGeneratorBuilder { + + /** + * The template suite generators. + */ + private List templateSuiteGenerators; + + /** + * The template class generators. + */ + private List templateClassGenerators; + + /** + * Indicates that this generator generates resources. + */ + private boolean generatingResources = false; + + /** + * Indicates that this generator generates classes. + */ + private boolean generatingClasses = false; + + /** + * The classes output directory. + */ + private File classesOutputDirectory; + + /** + * The resources output directory. + */ + private File resourcesOutputDirectory; + + /** + * Constructor. + */ + private TemplateGeneratorBuilder() { + templateSuiteGenerators = new ArrayList(); + templateClassGenerators = new ArrayList(); + } + + /** + * Creates a new instance of the builder. + * + * @return A new instance of the builder. + */ + public static TemplateGeneratorBuilder createNewInstance() { + return new TemplateGeneratorBuilder(); + } + + /** + * Sets the classes output directory. + * + * @param classesOutputDirectory The classes output directory. + * @return This instance. + */ + public TemplateGeneratorBuilder setClassesOutputDirectory(File classesOutputDirectory) { + this.classesOutputDirectory = classesOutputDirectory; + return this; + } + + /** + * Sets the resources output directory. + * + * @param resourcesOutputDirectory The resources output directory. + * @return This instance. + */ + public TemplateGeneratorBuilder setResourcesOutputDirectory(File resourcesOutputDirectory) { + this.resourcesOutputDirectory = resourcesOutputDirectory; + return this; + } + + /** + * Adds a new template suite generator to generate classes. + * + * @param generator The generator to add. + * @return This instance. + */ + public TemplateGeneratorBuilder addClassesTemplateSuiteGenerator(TemplateSuiteGenerator generator) { + if (classesOutputDirectory == null) { + throw new NullPointerException( + "Classes output directory not specified, call 'setClassesOutputDirectory' first"); + } + templateSuiteGenerators.add(new TSGeneratorDirectoryPair( + classesOutputDirectory, generator)); + generatingClasses = true; + return this; + } + + /** + * Adds a new template class generator to generate classes. + * + * @param generator The generator to add. + * @return This instance. + */ + public TemplateGeneratorBuilder addClassesTemplateClassGenerator(TemplateClassGenerator generator) { + if (classesOutputDirectory == null) { + throw new NullPointerException( + "Classes output directory not specified, call 'setClassesOutputDirectory' first"); + } + templateClassGenerators.add(new TCGeneratorDirectoryPair( + classesOutputDirectory, generator)); + generatingClasses = true; + return this; + } + + /** + * Adds a new template suite generator to generate resources. + * + * @param generator The generator to add. + * @return This instance. + */ + public TemplateGeneratorBuilder addResourcesTemplateSuiteGenerator(TemplateSuiteGenerator generator) { + if (resourcesOutputDirectory == null) { + throw new NullPointerException( + "Resources output directory not specified, call 'setClassesOutputDirectory' first"); + } + templateSuiteGenerators.add(new TSGeneratorDirectoryPair( + resourcesOutputDirectory, generator)); + generatingResources = true; + return this; + } + + /** + * Adds a new template class generator to generate resources. + * + * @param generator The generator to add. + * @return This instance. + */ + public TemplateGeneratorBuilder addResourcesTemplateClassGenerator(TemplateClassGenerator generator) { + if (resourcesOutputDirectory == null) { + throw new NullPointerException( + "Resources output directory not specified, call 'setClassesOutputDirectory' first"); + } + templateClassGenerators.add(new TCGeneratorDirectoryPair( + resourcesOutputDirectory, generator)); + generatingResources = true; + return this; + } + + /** + * Builds and returns a new template generator. + * + * @return The new template generator. + */ + public TemplateGenerator build() { + return new BasicTemplateGenerator(templateSuiteGenerators, + templateClassGenerators, generatingClasses, generatingResources); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorFactory.java new file mode 100644 index 0000000000..11fbf693fc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorFactory.java @@ -0,0 +1,32 @@ +/* + * 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.apache.tiles.autotag.generate; + +/** + * Creates a new template generator. + */ +public interface TemplateGeneratorFactory { + + /** + * Creates a template generator. + * + * @return The newly created template generator. + */ + TemplateGenerator createTemplateGenerator(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateSuiteGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateSuiteGenerator.java new file mode 100644 index 0000000000..f8986779d4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateSuiteGenerator.java @@ -0,0 +1,40 @@ +/* + * 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.apache.tiles.autotag.generate; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.model.TemplateSuite; + +/** + * Generates code from a template suite. + */ +public interface TemplateSuiteGenerator { + + /** + * Generates the code. + * + * @param directory The base directory where the code will be put. + * @param packageName The package name. + * @param suite The template suite. + * @param parameters Configuration parameters. + */ + void generate(File directory, String packageName, TemplateSuite suite, Map parameters); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/package-info.java new file mode 100644 index 0000000000..2fbdf2ae09 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * The Autotag generation classes. + */ +package org.apache.tiles.autotag.generate; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactory.java new file mode 100644 index 0000000000..90c7ce32ec --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactory.java @@ -0,0 +1,79 @@ +/* + * 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.apache.tiles.autotag.jsp; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.tiles.autotag.generate.TemplateGeneratorFactory; +import org.apache.velocity.app.VelocityEngine; + +/** + * Creates a template generator to build JSP code around template models. + */ +public class JspTemplateGeneratorFactory implements TemplateGeneratorFactory { + + /** + * Location of the file. + */ + private File classesOutputDirectory; + + /** + * Location of the file. + */ + private File resourcesOutputDirectory; + + /** + * The Velocity engine. + */ + private VelocityEngine velocityEngine; + + /** + * The template generator builder. + */ + private TemplateGeneratorBuilder templateGeneratorBuilder; + + /** + * Constructor. + * + * @param classesOutputDirectory The directory where classes will be + * generated. + * @param resourcesOutputDirectory The directory where the TLD file will be + * generated. + * @param velocityEngine The Velocity engine. + * @param templateGeneratorBuilder The template generator builder. + */ + public JspTemplateGeneratorFactory(File classesOutputDirectory, File resourcesOutputDirectory, + VelocityEngine velocityEngine, TemplateGeneratorBuilder templateGeneratorBuilder) { + this.classesOutputDirectory = classesOutputDirectory; + this.resourcesOutputDirectory = resourcesOutputDirectory; + this.velocityEngine = velocityEngine; + this.templateGeneratorBuilder = templateGeneratorBuilder; + } + + @Override + public TemplateGenerator createTemplateGenerator() { + return templateGeneratorBuilder.setClassesOutputDirectory(classesOutputDirectory) + .setResourcesOutputDirectory(resourcesOutputDirectory) + .addResourcesTemplateSuiteGenerator(new TLDGenerator(velocityEngine)) + .addClassesTemplateClassGenerator(new TagClassGenerator(velocityEngine)).build(); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TLDGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TLDGenerator.java new file mode 100644 index 0000000000..28d947d6eb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TLDGenerator.java @@ -0,0 +1,60 @@ +/* + * 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.apache.tiles.autotag.jsp; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateSuiteGenerator; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates the TLD file, using a template suite. + */ +public class TLDGenerator extends AbstractTemplateSuiteGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public TLDGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "/org/apache/tiles/autotag/jsp/tld.vm"; + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return suite.getName() + "-jsp.tld"; + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "META-INF/tld/"; + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TagClassGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TagClassGenerator.java new file mode 100644 index 0000000000..c0ee919de5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TagClassGenerator.java @@ -0,0 +1,63 @@ +/* + * 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.apache.tiles.autotag.jsp; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateClassGenerator; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates a tag class using a template class. + */ +public class TagClassGenerator extends AbstractTemplateClassGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public TagClassGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return packageName.replaceAll("\\.", "/"); + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return clazz.getTagClassPrefix() + "Tag.java"; + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return "/org/apache/tiles/autotag/jsp/bodyTag.vm"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/package-info.java new file mode 100644 index 0000000000..f142dabfac --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Autotag support for JavaServer Pages. + */ +package org.apache.tiles.autotag.jsp; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateClass.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateClass.java new file mode 100644 index 0000000000..0aeb990cea --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateClass.java @@ -0,0 +1,191 @@ +/* + * 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.apache.tiles.autotag.model; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * It represents a parsed template class. + */ +public class TemplateClass { + + /** + * The class name. + */ + private String name; + + /** + * The name of the tag. + */ + private String tagName; + + /** + * The prefix of the tag class. + */ + private String tagClassPrefix; + + /** + * Documentation about this tag. + */ + private String documentation; + + /** + * The method that executes the template class. + */ + private TemplateMethod executeMethod; + + /** + * Constructor. + * + * @param name The name of the template class. + */ + public TemplateClass(String name) { + this(name, null, null, null); + } + + /** + * Constructor. + * + * @param name The name of the template class. + * @param tagName The name of the tag. + * @param tagClassPrefix The tag class prefix. + * @param executeMethod The method that executes the template class. + */ + public TemplateClass(String name, String tagName, String tagClassPrefix, + TemplateMethod executeMethod) { + this.name = name; + this.tagName = tagName; + this.tagClassPrefix = tagClassPrefix; + this.executeMethod = executeMethod; + } + + /** + * The name of the parsed class. + * + * @return The name of the class. + */ + public String getName() { + return name; + } + + /** + * Returns the name of the class, without the package part. + * + * @return The simple class name. + */ + public String getSimpleName() { + int pos = name.lastIndexOf('.'); + if (pos >= 0) { + return name.substring(pos + 1); + } + return name; + } + + /** + * Returns the tag name. + * + * @return The tag name. + */ + public String getTagName() { + return tagName; + } + + /** + * Returns the tag class prefix. + * + * @return The tag class prefix. + */ + public String getTagClassPrefix() { + return tagClassPrefix; + } + + /** + * Returns the documentation for this class. + * + * @return The documentation. + */ + public String getDocumentation() { + return documentation; + } + + /** + * Sets the documentation for this class. + * + * @param documentation The documentation. + */ + public void setDocumentation(String documentation) { + this.documentation = documentation; + } + + /** + * Returns the method that execute this class. + * + * @return The execute method. + */ + public TemplateMethod getExecuteMethod() { + return executeMethod; + } + + /** + * Returns the collection of regular parameters (no request, no body) + * of the execute method. + * + * @return The regular parameters. + */ + public Collection getParameters() { + Map params = new LinkedHashMap(); + fillRegularParameters(params, executeMethod); + return params.values(); + } + + /** + * Indicates that this class needs a tag body. + * + * @return true if tag body is needed. + */ + public boolean hasBody() { + return executeMethod.hasBody(); + } + + @Override + public String toString() { + return "TemplateClass [name=" + name + ", tagName=" + tagName + + ", tagClassPrefix=" + tagClassPrefix + ", documentation=" + + documentation + ", executeMethod=" + executeMethod + "]"; + } + + /** + * Creates regular parameters map. + * + * @param params The map to fill. + * @param method The method to analyze. + */ + private void fillRegularParameters(Map params, + TemplateMethod method) { + if (method != null) { + for (TemplateParameter param : method.getParameters()) { + if (!param.isRequest() && !param.isBody()) { + params.put(param.getName(), param); + } + } + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateMethod.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateMethod.java new file mode 100644 index 0000000000..2bccf2ddda --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateMethod.java @@ -0,0 +1,127 @@ +/* + * 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.apache.tiles.autotag.model; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * It represents a parsed method in a parsed template class. + */ +public class TemplateMethod { + + /** + * The name of the method. + */ + private String name; + + /** + * Documentation about the method. + */ + private String documentation; + + /** + * The map of parameters. + */ + private Map parameters; + + /** + * Constructor. + * + * @param name The name of the method. + * @param parameters The map of parameters. + */ + public TemplateMethod(String name, + Iterable parameters) { + this.name = name; + this.parameters = new LinkedHashMap(); + for (TemplateParameter parameter : parameters) { + this.parameters.put(parameter.getName(), parameter); + } + } + + /** + * Returns the name of the method. + * + * @return The name of the method. + */ + public String getName() { + return name; + } + + /** + * Returns the documentation for this method. + * + * @return The documentation. + */ + public String getDocumentation() { + return documentation; + } + + /** + * Sets the documentation for this method. + * + * @param documentation The documentation. + */ + public void setDocumentation(String documentation) { + this.documentation = documentation; + } + + /** + * Returns the parameters of this method. + * + * @return The parameters. + */ + public Collection getParameters() { + return parameters.values(); + } + + /** + * Returns a parameter given its name. + * + * @param name The name of the parameter. + * @return The parameter. + */ + public TemplateParameter getParameterByName(String name) { + return parameters.get(name); + } + + /** + * Indicates that this method needs a tag body. + * + * @return true if tag body is needed. + */ + public boolean hasBody() { + if (parameters.size() >= 2) { + for (TemplateParameter param : parameters.values()) { + if (param.isBody()) { + return true; + } + } + } + return false; + } + + @Override + public String toString() { + return "TemplateMethod [name=" + name + ", documentation=" + + documentation + ", parameters=" + parameters + "]"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateParameter.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateParameter.java new file mode 100644 index 0000000000..0540954c12 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateParameter.java @@ -0,0 +1,182 @@ +/* + * 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.apache.tiles.autotag.model; + +import org.apache.tiles.autotag.core.runtime.ModelBody; + +/** + * It represents a parameter in a method in a parsed template class. + */ +public class TemplateParameter { + + /** + * The name of the parameter. + */ + private String name; + + /** + * The exported name, i.e. the name of the parameter in created code. Usually + * helpful if this exported name is a reserved word. + */ + private String exportedName; + + /** + * The parameter documentation. + */ + private String documentation; + + /** + * The type of the parameter. + */ + private String type; + + /** + * The default value, as it will be written in Java code. + */ + private String defaultValue; + + /** + * Indicates that this parameter is required. + */ + private boolean required; + + /** + * Indicates that this parameter is the request. + */ + private boolean request; + + /** + * Constructor. + * + * @param name The name of the parameter. + * @param exportedName The exported name, i.e. the name of the parameter in created code. Usually + * helpful if this exported name is a reserved word. + * @param type The type of the parameter. + * @param defaultValue The default value, as it will be written in Java code. + * @param required Indicates that this parameter is required. + */ + public TemplateParameter(String name, String exportedName, String type, String defaultValue, boolean required, boolean request) { + this.name = name; + this.exportedName = exportedName; + this.type = type; + this.defaultValue = defaultValue; + this.required = required; + this.request = request; + } + + /** + * Returns the documentation for this parameter. + * + * @return The documentation. + */ + public String getDocumentation() { + return documentation; + } + + /** + * Sets the documentation for this parameter. + * + * @param documentation The documentation. + */ + public void setDocumentation(String documentation) { + this.documentation = documentation; + } + + /** + * Returns the name of the parameter. + * + * @return The name of the parameter. + */ + public String getName() { + return name; + } + + /** + * Returns the exported name, i.e. the name of the parameter in created code. Usually + * helpful if this exported name is a reserved word. + * + * @return The exported name. + */ + public String getExportedName() { + return exportedName; + } + + /** + * Returns the type of the parameter. + * + * @return The type. + */ + public String getType() { + return type; + } + + /** + * Returns the default value, as it will be written in Java code. + * + * @return The default value. + */ + public String getDefaultValue() { + return defaultValue; + } + + /** + * Indicates that this parameter is required. + * + * @return true if the parameter is required. + */ + public boolean isRequired() { + return required; + } + + /** + * Indicates that this parameter implements {@link ModelBody}. + * + * @return true if the parameter is a body. + */ + public boolean isBody() { + return ModelBody.class.getName().equals(type); + } + + /** + * Indicates that this parameter implements {@link Request}. + * + * @return true if the parameter is a request. + */ + public boolean isRequest() { + return request; + } + + /** + * Returns the suffix for getter and setter of the property generated by + * this parameter. + * + * @return The getter and setter suffix. + */ + public String getGetterSetterSuffix() { + return exportedName.substring(0, 1).toUpperCase() + exportedName.substring(1); + } + + @Override + public String toString() { + return "TemplateParameter [name=" + name + ", exportedName=" + + exportedName + ", documentation=" + documentation + ", type=" + + type + ", defaultValue=" + defaultValue + ", required=" + + required + ", request=" + request + "]"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateSuite.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateSuite.java new file mode 100644 index 0000000000..de14b466fd --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateSuite.java @@ -0,0 +1,125 @@ +/* + * 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.apache.tiles.autotag.model; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * It represents a suite of template classes. + */ +public class TemplateSuite { + + /** + * The name of the suite. + */ + private String name; + + /** + * The documentation of this suite. + */ + private String documentation; + + /** + * The map of template classes. + */ + private Map templateClasses; + + /** + * Constructor. + * + * @param name The name of the suite. + * @param documentation The documentation. + */ + public TemplateSuite(String name, String documentation) { + this(name, documentation, null); + } + + /** + * Constructor. + * + * @param name The name of the suite. + * @param documentation The documentation. + * @param classes The template classes. + */ + public TemplateSuite(String name, String documentation, + Iterable classes) { + this.name = name; + this.documentation = documentation; + templateClasses = new LinkedHashMap(); + if (classes != null) { + for (TemplateClass templateClass : classes) { + templateClasses.put(templateClass.getName(), templateClass); + } + } + } + + /** + * Returns the template suite name. + * + * @return The name. + */ + public String getName() { + return name; + } + + /** + * Returns the documentation. + * + * @return The documentation. + */ + public String getDocumentation() { + return documentation; + } + + /** + * Adds a new template class. + * + * @param clazz The template class. + */ + public void addTemplateClass(TemplateClass clazz) { + templateClasses.put(clazz.getName(), clazz); + } + + /** + * Returns the template classes. + * + * @return The template classes. + */ + public Collection getTemplateClasses() { + return templateClasses.values(); + } + + /** + * Returns a template class given its name. + * + * @param name The name of the class. + * @return The template class instance. + */ + public TemplateClass getTemplateClassByName(String name) { + return templateClasses.get(name); + } + + @Override + public String toString() { + return "TemplateSuite [name=" + name + ", documentation=" + + documentation + ", templateClasses=" + templateClasses + "]"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/package-info.java new file mode 100644 index 0000000000..7eddcd1f54 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Domain model classes representing a parsed template suite. + */ +package org.apache.tiles.autotag.model; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/StringTool.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/StringTool.java new file mode 100644 index 0000000000..2475298350 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/StringTool.java @@ -0,0 +1,138 @@ +/* + * 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.apache.tiles.autotag.tool; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tiles.autotag.core.AutotagRuntimeException; + +/** + * A Velocity tools to manipulate strings. + */ +public class StringTool { + + /** + * Maps a primitive type to its default value as a string. + */ + private Map type2default; + + /** + * Maps a primitive type to its boxed version. + */ + private Map primitive2wrapped; + + /** + * Constructor. + */ + public StringTool() { + type2default = new HashMap(); + type2default.put("byte", "0"); + type2default.put("short", "0"); + type2default.put("int", "0"); + type2default.put("long", "0L"); + type2default.put("float", "0.0f"); + type2default.put("double", "0.0d"); + type2default.put("char", "'\\u0000'"); + type2default.put("boolean", "false"); + + primitive2wrapped = new HashMap(); + primitive2wrapped.put("byte", Byte.class.getName()); + primitive2wrapped.put("short", Short.class.getName()); + primitive2wrapped.put("int", Integer.class.getName()); + primitive2wrapped.put("long", Long.class.getName()); + primitive2wrapped.put("float", Float.class.getName()); + primitive2wrapped.put("double", Double.class.getName()); + primitive2wrapped.put("char", Character.class.getName()); + primitive2wrapped.put("boolean", Boolean.class.getName()); + } + + /** + * Creates a list of strings, separating a string when a newline is encountered. + * + * @param toSplit The string to split. + * @return The list of splitted strings. + */ + public List splitOnNewlines(String toSplit) { + List retValue = new ArrayList(); + if (toSplit == null) { + return retValue; + } + Reader reader = new StringReader(toSplit); + BufferedReader bufReader = new BufferedReader(reader); + try { + String line; + while ((line = bufReader.readLine()) != null) { + retValue.add(line); + } + } catch (IOException e) { + throw new AutotagRuntimeException("Cannot read the string completely", e); + } + return retValue; + } + + /** + * Creates a string in which the first character is capitalized. + * + * @param string The string to use. + * @return The same string with the first character capitalized. + */ + public String capitalizeFirstLetter(String string) { + return string.substring(0, 1).toUpperCase() + string.substring(1); + } + + /** + * Returns the default value for a type. + * + * @param type The type. + * @param overriddenDefaultValue The default value, as specified by developers. + * @return The default value to use. + */ + public String getDefaultValue(String type, String overriddenDefaultValue) { + if (overriddenDefaultValue != null) { + return overriddenDefaultValue; + } + + String retValue = type2default.get(type); + if (retValue == null) { + retValue = "null"; + } + return retValue; + } + + /** + * Returns the class to be used to cast an Object. + * + * @param type The type to use, even a primitive type. + * @return The class to be used in casts. + */ + public String getClassToCast(String type) { + String retValue = primitive2wrapped.get(type); + if (retValue == null) { + retValue = type; + } + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/package-info.java new file mode 100644 index 0000000000..b58748ab06 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Velocity tools to be used in Velocity templates. + */ +package org.apache.tiles.autotag.tool; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGenerator.java new file mode 100644 index 0000000000..b59b70843e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGenerator.java @@ -0,0 +1,67 @@ +/* + * $Id: VelocityDirectiveGenerator.java 1349964 2012-06-13 17:18:51Z nlebas $ + * + * 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.apache.tiles.autotag.velocity; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateClassGenerator; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates a Velocity directive using a template class. + * + * @version $Rev: 1349964 $ $Date: 2012-06-13 13:18:51 -0400 (Wed, 13 Jun 2012) $ + */ +public class VelocityDirectiveGenerator extends AbstractTemplateClassGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public VelocityDirectiveGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return packageName.replaceAll("\\.", "/"); + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return clazz.getTagClassPrefix() + "Directive.java"; + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return "/org/apache/tiles/autotag/velocity/velocityDirective.vm"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGenerator.java new file mode 100644 index 0000000000..bf340c41f5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGenerator.java @@ -0,0 +1,64 @@ +/* + * $Id: VelocityPropertiesGenerator.java 1045345 2010-12-13 19:58:23Z apetrelli $ + * + * 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.apache.tiles.autotag.velocity; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateSuiteGenerator; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates a Velocity properties containing the list of generated user directives for future use. + * + * @version $Rev: 1045345 $ $Date: 2010-12-13 14:58:23 -0500 (Mon, 13 Dec 2010) $ + */ +public class VelocityPropertiesGenerator extends AbstractTemplateSuiteGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public VelocityPropertiesGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "/org/apache/tiles/autotag/velocity/velocityProperties.vm"; + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "velocity.properties"; + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "META-INF/"; + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactory.java new file mode 100644 index 0000000000..6ed64cf472 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactory.java @@ -0,0 +1,87 @@ +/* + * $Id: VelocityTemplateGeneratorFactory.java 1045345 2010-12-13 19:58:23Z apetrelli $ + * + * 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.apache.tiles.autotag.velocity; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.tiles.autotag.generate.TemplateGeneratorFactory; +import org.apache.velocity.app.VelocityEngine; + +/** + * Creates a template generator that generates code to build Velocity code + * around template classes. + * + * @version $Rev: 1045345 $ $Date: 2010-12-13 14:58:23 -0500 (Mon, 13 Dec 2010) $ + */ +public class VelocityTemplateGeneratorFactory implements + TemplateGeneratorFactory { + + /** + * Location of the file. + */ + private File classesOutputDirectory; + + /** + * Location of the file. + */ + private File resourcesOutputDirectory; + + /** + * The Velocity engine. + */ + private VelocityEngine velocityEngine; + + /** + * The template generator builder. + */ + private TemplateGeneratorBuilder templateGeneratorBuilder; + + /** + * Constructor. + * + * @param classesOutputDirectory The directory where classes will be generated. + * @param resourcesOutputDirectory The directory where velocity.properties will be written. + * @param velocityEngine The Velocity engine. + * @param templateGeneratorBuilder The template generator builder. + */ + public VelocityTemplateGeneratorFactory(File classesOutputDirectory, + File resourcesOutputDirectory, VelocityEngine velocityEngine, + TemplateGeneratorBuilder templateGeneratorBuilder) { + this.classesOutputDirectory = classesOutputDirectory; + this.resourcesOutputDirectory = resourcesOutputDirectory; + this.velocityEngine = velocityEngine; + this.templateGeneratorBuilder = templateGeneratorBuilder; + } + + @Override + public TemplateGenerator createTemplateGenerator() { + return templateGeneratorBuilder + .setClassesOutputDirectory(classesOutputDirectory) + .setResourcesOutputDirectory(resourcesOutputDirectory) + .addResourcesTemplateSuiteGenerator( + new VelocityPropertiesGenerator(velocityEngine)) + .addClassesTemplateClassGenerator( + new VelocityDirectiveGenerator(velocityEngine)).build(); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/package-info.java new file mode 100644 index 0000000000..15e00360fc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1045345 2010-12-13 19:58:23Z apetrelli $ + * + * 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. + */ +/** + * Autotag support for Velocity. + */ +package org.apache.tiles.autotag.velocity; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactory.java new file mode 100644 index 0000000000..8f0dcc7aa4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactory.java @@ -0,0 +1,75 @@ +/* + * 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.apache.tiles.core.definition; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.request.Request; + +/** + * Interface for creating a {@link Definition}s and managing their contents. + *

+ *

+ * DefinitionsFactory implementations are responsible for maintaining the data + * sources of Tiles configuration data and using the data to create Definitions + * sets. Implementations also know how to append locale-specific configuration + * data to an existing Definitions set. + *

+ */ +public interface DefinitionsFactory { + + /** + * Property name that specifies the implementation of the DefinitionsReader. + */ + String READER_IMPL_PROPERTY = + "org.apache.tiles.definition.DefinitionsReader"; + + /** + * Property name that specifies the implementation of + * {@link org.apache.tiles.core.locale.LocaleResolver}. + */ + String LOCALE_RESOLVER_IMPL_PROPERTY = + "org.apache.tiles.locale.LocaleResolver"; + + /** + * Constant representing the configuration parameter + * used to define the tiles definition resources. + * + * @since 2.1.0 + */ + String DEFINITIONS_CONFIG = "org.apache.tiles.definition.DefinitionsFactory.DEFINITIONS_CONFIG"; + + /** + * Constant representing the configuration parameter used to define the + * definition DAO to use. + */ + String DEFINITION_DAO_INIT_PARAM = + "org.apache.tiles.definition.DefinitionsFactory.DefinitionDAO"; + + /** + * Returns a Definition object that matches the given name and + * Tiles context. + * + * @param name The name of the Definition to return. + * @param tilesContext The Tiles context to use to resolve the definition. + * @return the Definition matching the given name or null if none + * is found. + */ + Definition getDefinition(String name, Request tilesContext); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactoryException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactoryException.java new file mode 100644 index 0000000000..3d07b20bb0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactoryException.java @@ -0,0 +1,72 @@ +/* + * 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.apache.tiles.core.definition; + +import org.apache.tiles.api.TilesException; + +/** + * Exception thrown when an error occurs while the impl tries to + * create a new instance mapper. + */ +public class DefinitionsFactoryException extends TilesException { + + /** + * Constructor. + */ + public DefinitionsFactoryException() { + super(); + } + + /** + * Constructor. + * + * @param message The error or warning message. + */ + public DefinitionsFactoryException(String message) { + super(message); + } + + + /** + * Create a new DefinitionsFactoryException wrapping an existing exception. + *

+ *

The existing exception will be embedded in the new + * one and its message will become the default message for + * the DefinitionsFactoryException.

+ * + * @param e The exception to be wrapped. + */ + public DefinitionsFactoryException(Throwable e) { + super(e); + } + + + /** + * Create a new DefinitionsFactoryException from an existing exception. + *

+ *

The existing exception will be embedded in the new + * one, but the new exception will have its own message.

+ * + * @param message The detail message. + * @param e The exception to be wrapped. + */ + public DefinitionsFactoryException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsReader.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsReader.java new file mode 100644 index 0000000000..39d61a52b9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsReader.java @@ -0,0 +1,52 @@ +/* + * 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.apache.tiles.core.definition; + +import org.apache.tiles.api.Definition; + +import java.util.Map; + +/** + * Interface for reading {@link Definition} from a source. + *

+ *

This interface provides a standard way to read + * {@link Definition} objects from a source. Implementations + * should define what the source is, whether it be a persistent store such as a + * configuration file or database, or something like a web service. The + * DefinitionsReader is responsible for reading from a single location. It does + * not perform any internationalization duties or inheritance of Definitions. + * It only reads from the source and returns a Map of objects read.

+ */ +public interface DefinitionsReader { + + /** + * Reads {@link Definition} objects from a source. + *

+ * Implementations should publish what type of source object is expected. + * + * @param source The source from which definitions will be read. + * @return a Map of Definition objects read from + * the source. + * @throws DefinitionsFactoryException if the source is invalid or + * an error occurs when reading definitions. + */ + Map read(Object source); + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/NoSuchDefinitionException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/NoSuchDefinitionException.java new file mode 100644 index 0000000000..6815f2db9c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/NoSuchDefinitionException.java @@ -0,0 +1,35 @@ +/* + * 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.apache.tiles.core.definition; + +/** + * Exception thrown when a definition is not found. + */ +public class NoSuchDefinitionException extends DefinitionsFactoryException { + + /** + * Constructor. + * + * @param msg Message. + */ + public NoSuchDefinitionException(String msg) { + super(msg); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/RefreshMonitor.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/RefreshMonitor.java new file mode 100644 index 0000000000..d5f62d8d23 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/RefreshMonitor.java @@ -0,0 +1,36 @@ +/* + * 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.apache.tiles.core.definition; + +/** + * Implementing this interface means that the object monitors the sources it + * uses to check when they change. + * + * @since 2.1.0 + */ +public interface RefreshMonitor { + + /** + * Indicates whether the sources are out of date and need to be reloaded. + * + * @return true if the sources need to be refreshed. + * @since 2.1.0 + */ + boolean refreshRequired(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactory.java new file mode 100644 index 0000000000..5a35e48256 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactory.java @@ -0,0 +1,86 @@ +/* + * 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.apache.tiles.core.definition; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.request.Request; +import org.apache.tiles.core.definition.dao.DefinitionDAO; +import org.apache.tiles.core.locale.LocaleResolver; + +import java.util.Locale; + +/** + * {@link DefinitionsFactory DefinitionsFactory} implementation that manages + * Definitions configuration data from URLs, without resolving definition + * inheritance when a definition is returned.

+ *

+ * The Definition objects are read from the + * {@link org.apache.tiles.core.definition.digester.DigesterDefinitionsReader} + * class unless another implementation is specified. + *

+ * @since 2.2.1 + */ +public class UnresolvingLocaleDefinitionsFactory implements DefinitionsFactory { + + /** + * The definition DAO that extracts the definitions from the sources. + * + * @since 2.2.1 + */ + protected DefinitionDAO definitionDao; + + /** + * The locale resolver object. + * + * @since 2.2.1 + */ + protected LocaleResolver localeResolver; + + /** + * Sets the locale resolver to use. + * + * @param localeResolver The locale resolver. + * @since 2.2.1 + */ + public void setLocaleResolver(LocaleResolver localeResolver) { + this.localeResolver = localeResolver; + } + + /** + * Sets the definition DAO to use. It must be locale-based. + * + * @param definitionDao The definition DAO. + * @since 2.2.1 + */ + public void setDefinitionDAO(DefinitionDAO definitionDao) { + this.definitionDao = definitionDao; + } + + /** {@inheritDoc} */ + public Definition getDefinition(String name, Request tilesContext) { + Locale locale = null; + + if (tilesContext != null) { + locale = localeResolver.resolveLocale(tilesContext); + } + + return definitionDao.getDefinition(name, locale); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAO.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAO.java new file mode 100644 index 0000000000..cb01af4349 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAO.java @@ -0,0 +1,163 @@ +/* + * 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.apache.tiles.core.definition.dao; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.DefinitionsFactoryException; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.RefreshMonitor; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * Base abstract class for a DAO that is based on URLs and locale as a + * customization key. + * + * @since 2.1.0 + */ +public abstract class BaseLocaleUrlDefinitionDAO implements DefinitionDAO, RefreshMonitor { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(BaseLocaleUrlDefinitionDAO.class); + + /** + * Contains the URL objects identifying where configuration data is found. + * + * @since 2.1.0 + */ + protected List sources; + + /** + * Contains the dates that the URL sources were last modified. + * + * @since 2.1.0 + */ + protected Map lastModifiedDates; + + /** + * Reader used to get definitions from the sources. + * + * @since 2.1.0 + */ + protected DefinitionsReader reader; + + /** + * ApplicationContext to locate the source files. + * + * @since 3.0.0 + */ + protected ApplicationContext applicationContext; + + /** + * Constructor. + */ + public BaseLocaleUrlDefinitionDAO(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + lastModifiedDates = new HashMap<>(); + } + + public void setSources(List sources) { + // filter out any sources that are already localized + ArrayList defaultSources = new ArrayList<>(); + for (ApplicationResource source : sources) { + if (Locale.ROOT.equals(source.getLocale())) { + defaultSources.add(source); + } + } + this.sources = defaultSources; + } + + public void setReader(DefinitionsReader reader) { + this.reader = reader; + } + + /** + * {@inheritDoc} + */ + public boolean refreshRequired() { + boolean status = false; + + Set paths = lastModifiedDates.keySet(); + + try { + for (String path : paths) { + Long lastModifiedDate = lastModifiedDates.get(path); + ApplicationResource resource = applicationContext.getResource(path); + long newModDate = resource.getLastModified(); + if (newModDate != lastModifiedDate) { + status = true; + break; + } + } + } catch (IOException e) { + LOG.warn("Exception while monitoring update times.", e); + return true; + } + return status; + } + + /** + * Loads definitions from an URL without loading from "parent" URLs. + * + * @param resource The URL to read. + * @return The definition map that has been read. + */ + protected Map loadDefinitionsFromResource(ApplicationResource resource) { + Map defsMap = null; + + InputStream stream = null; + try { + lastModifiedDates.put(resource.getLocalePath(), resource + .getLastModified()); + + // Definition must be collected, starting from the base + // source up to the last localized file. + stream = resource.getInputStream(); + defsMap = reader.read(stream); + } catch (FileNotFoundException e) { + // File not found. continue. + LOG.debug("File {} not found, continue", resource); + } catch (IOException e) { + throw new DefinitionsFactoryException("I/O error processing configuration.", e); + } finally { + try { + if (stream != null) { + stream.close(); + } + } catch (IOException ignore) { + } + } + + return defsMap; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAO.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAO.java new file mode 100644 index 0000000000..b280fc97b0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAO.java @@ -0,0 +1,272 @@ +/* + * 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.apache.tiles.core.definition.dao; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolverAware; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.locale.LocaleUtil; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; + +/** + *

+ * A definitions DAO (loading URLs and using Locale as a customization key) that + * caches definitions that have been loaded in a raw way (i.e. with inheritance + * that is not resolved). + *

+ *

+ * It can check if the URLs change, but by default this feature is turned off. + *

+ * + * @since 2.1.0 + */ +public class CachingLocaleUrlDefinitionDAO extends BaseLocaleUrlDefinitionDAO implements PatternDefinitionResolverAware { + + /** + * Initialization parameter to set whether we want to refresh URLs when they + * change. + * + * @since 2.1.0 + */ + public static final String CHECK_REFRESH_INIT_PARAMETER = "org.apache.tiles.definition.dao.LocaleUrlDefinitionDAO.CHECK_REFRESH"; + + /** + * The locale-specific set of definitions objects. + * + * @since 2.1.0 + */ + protected Map> locale2definitionMap; + + /** + * Flag that, when true, enables automatic checking of URLs + * changing. + * + * @since 2.1.0 + */ + protected boolean checkRefresh = false; + + /** + * Resolves definitions using patterns. + * + * @since 2.2.0 + */ + protected PatternDefinitionResolver definitionResolver; + + /** + * Constructor. + * + * @since 2.1.0 + */ + public CachingLocaleUrlDefinitionDAO(ApplicationContext applicationContext) { + super(applicationContext); + locale2definitionMap = new HashMap<>(); + } + + /** + * {@inheritDoc} + */ + public void setPatternDefinitionResolver( + PatternDefinitionResolver definitionResolver) { + this.definitionResolver = definitionResolver; + } + + /** + * {@inheritDoc} + */ + public Definition getDefinition(String name, Locale customizationKey) { + Definition retValue = null; + if (customizationKey == null) { + customizationKey = Locale.ROOT; + } + Map definitions = getDefinitions(customizationKey); + if (definitions != null) { + retValue = definitions.get(name); + + if (retValue == null) { + retValue = getDefinitionFromResolver(name, customizationKey); + + if (retValue != null) { + synchronized (definitions) { + definitions.put(name, retValue); + } + } + } + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + public Map getDefinitions(Locale customizationKey) { + if (customizationKey == null) { + customizationKey = Locale.ROOT; + } + Map retValue = locale2definitionMap + .get(customizationKey); + if (retValue == null || (checkRefresh && refreshRequired())) { + retValue = checkAndloadDefinitions(customizationKey); + } + return retValue; + } + + /** + * Sets the flag to check source refresh. If not called, the default is + * false. + * + * @param checkRefresh When true, enables automatic checking + * of sources changing. + * @since 2.1.0 + */ + public void setCheckRefresh(boolean checkRefresh) { + this.checkRefresh = checkRefresh; + } + + /** + * Returns a definition from the definition resolver. + * + * @param name The name of the definition. + * @param customizationKey The customization key to use. + * @return The resolved definition. + */ + protected Definition getDefinitionFromResolver(String name, + Locale customizationKey) { + return definitionResolver.resolveDefinition(name, + customizationKey); + } + + /** + * Checks if sources have changed. If yes, it clears the cache. Then continues + * loading definitions. + * + * @param customizationKey The locale to use when loading sources. + * @return The loaded definitions. + * @since 2.1.0 + */ + protected synchronized Map checkAndloadDefinitions(Locale customizationKey) { + Map existingDefinitions = locale2definitionMap.get(customizationKey); + boolean definitionsAlreadyLoaded = existingDefinitions != null; + if (definitionsAlreadyLoaded) { + return existingDefinitions; + } + if (checkRefresh && refreshRequired()) { + locale2definitionMap.clear(); + definitionResolver.clearPatternPaths(customizationKey); + } + loadDefinitions(customizationKey); + return locale2definitionMap.get(customizationKey); + } + + /** + * Tries to load definitions if necessary. + * + * @param customizationKey The locale to use when loading sources. + * @return The loaded definitions. + * @since 2.1.0 + */ + protected Map loadDefinitions(Locale customizationKey) { + Map localeDefsMap = locale2definitionMap + .get(customizationKey); + if (localeDefsMap != null) { + return localeDefsMap; + } + + return loadDefinitionsFromResources(customizationKey); + } + + /** + * Loads definitions from the sources. + * + * @param customizationKey The locale to use when loading Resources. + * @return The loaded definitions. + * @since 2.1.0 + */ + protected Map loadDefinitionsFromResources(Locale customizationKey) { + Map localeDefsMap = loadRawDefinitionsFromResources(customizationKey); + Map defsMap = definitionResolver + .storeDefinitionPatterns(copyDefinitionMap(localeDefsMap), + customizationKey); + locale2definitionMap.put(customizationKey, defsMap); + return localeDefsMap; + } + + /** + * Loads the raw definitions from the sources associated with a locale. + * + * @param customizationKey The locale to use when loading Resources. + * @return The loaded definitions. + * @since 2.1.3 + */ + protected Map loadRawDefinitionsFromResources(Locale customizationKey) { + Map localeDefsMap; + + Locale parentLocale = LocaleUtil.getParentLocale(customizationKey); + localeDefsMap = new LinkedHashMap<>(); + if (parentLocale != null) { + Map parentDefs = loadRawDefinitionsFromResources(parentLocale); + if (parentDefs != null) { + localeDefsMap.putAll(parentDefs); + } + } + // For each source, the resource must be loaded. + for (ApplicationResource resource : sources) { + ApplicationResource newResource = applicationContext.getResource(resource, customizationKey); + if (newResource != null) { + Map defsMap = loadDefinitionsFromResource(newResource); + if (defsMap != null) { + localeDefsMap.putAll(defsMap); + } + } + } + return localeDefsMap; + } + + /** + * Loads parent definitions, i.e. definitions mapped to a parent locale. + * + * @param parentLocale The locale to use when loading URLs. + * @return The loaded parent definitions. + * @since 2.1.0 + */ + protected Map loadParentDefinitions(Locale parentLocale) { + return loadDefinitions(parentLocale); + } + + /** + * Copies the definition map to be passed to a higher level of customization + * key. + * + * @param localeDefsMap The map of definition to be copied. + * @return The copy of the definition map. This particular implementation + * return the localeDefsMap itself. + * @since 2.1.4 + */ + protected Map copyDefinitionMap( + Map localeDefsMap) { + return localeDefsMap; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/DefinitionDAO.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/DefinitionDAO.java new file mode 100644 index 0000000000..ce0b1ef4a7 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/DefinitionDAO.java @@ -0,0 +1,54 @@ +/* + * 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.apache.tiles.core.definition.dao; + +import org.apache.tiles.api.Definition; + +import java.util.Map; + +/** + * It represents an object that provides definitions, depending on a + * customization key. + * + * @param The customization key class. + * @since 2.1.0 + */ +public interface DefinitionDAO { + + /** + * Returns a definition, given its name and the customization key. + * + * @param name The name of the definition. + * @param customizationKey The customization key. + * @return The requested definition, if found, otherwise null. + * The inheritance of the definition must not be resolved. + * @since 2.1.0 + */ + Definition getDefinition(String name, K customizationKey); + + /** + * Returns all the definitions used of a customization key. + * + * @param customizationKey The customization key. + * @return All the definitions that are connected to the customization key. + * The inheritance of the definitions must not be resolved. + * @since 2.1.0 + */ + Map getDefinitions(K customizationKey); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAO.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAO.java new file mode 100644 index 0000000000..d6af2f87ba --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAO.java @@ -0,0 +1,172 @@ +/* + * 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.apache.tiles.core.definition.dao; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.request.ApplicationContext; + +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + *

+ * A definitions DAO (loading URLs and using Locale as a customization key) that + * caches definitions that have been loaded and resolves inheritances. + *

+ *

+ * It can check if the URLs change, but by default this feature is turned off. + *

+ * + * @since 2.1.0 + */ +public class ResolvingLocaleUrlDefinitionDAO extends CachingLocaleUrlDefinitionDAO { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(ResolvingLocaleUrlDefinitionDAO.class); + + public ResolvingLocaleUrlDefinitionDAO(ApplicationContext applicationContext) { + super(applicationContext); + } + + /** {@inheritDoc} */ + @Override + protected Map loadParentDefinitions(Locale parentLocale) { + return loadRawDefinitionsFromResources(parentLocale); + } + + @Override + protected Map loadDefinitions(Locale customizationKey) { + Map localeDefsMap = super.loadDefinitions(customizationKey); + Map defsMap = definitionResolver + .storeDefinitionPatterns(copyDefinitionMap(localeDefsMap), + customizationKey); + resolveInheritances(defsMap, customizationKey); + locale2definitionMap.put(customizationKey, defsMap); + return defsMap; + } + + /** {@inheritDoc} */ + @Override + protected Definition getDefinitionFromResolver(String name, + Locale customizationKey) { + Definition retValue = super.getDefinitionFromResolver(name, customizationKey); + if (retValue != null && retValue.getExtends() != null) { + Definition parent = getDefinition(retValue.getExtends(), customizationKey); + retValue.inherit(parent); + } + + return retValue; + } + + /** + * Resolve locale-specific extended instances. + * + * @param map The definition map containing the definitions to resolve. + * @param locale The locale to use. + * @throws NoSuchDefinitionException If a parent definition is not found. + * @since 2.1.0 + */ + protected void resolveInheritances(Map map, Locale locale) { + if (map != null) { + Set alreadyResolvedDefinitions = new HashSet<>(); + for (Definition definition : map.values()) { + resolveInheritance(definition, map, locale, + alreadyResolvedDefinitions); + } // end loop + } + } + + /** + * Resolve locale-specific inheritance. First, resolve parent's inheritance, + * then set template to the parent's template. Also copy attributes setted + * in parent, and not set in child If instance doesn't extend anything, do + * nothing. + * + * @param definition The definition to resolve + * @param definitions The definitions to take when obtaining a parent + * definition. + * @param locale The locale to use. + * @param alreadyResolvedDefinitions The set of the definitions that have + * been already resolved. + * @throws NoSuchDefinitionException If an inheritance can not be solved. + * @since 2.1.0 + */ + protected void resolveInheritance(Definition definition, + Map definitions, Locale locale, + Set alreadyResolvedDefinitions) { + // Already done, or not needed ? + if (!definition.isExtending() || alreadyResolvedDefinitions.contains(definition.getName())) { + return; + } + + LOG.debug("Resolve definition for child name='{}' extends='{}.", definition.getName(), definition.getExtends()); + + // Set as visited to avoid endless recursivity. + alreadyResolvedDefinitions.add(definition.getName()); + + // Resolve parent before itself. + Definition parent = definitions.get(definition.getExtends()); + if (parent == null) { // error + String msg = "Error while resolving definition inheritance: child '" + + definition.getName() + + "' can't find its ancestor '" + + definition.getExtends() + + "'. Please check your description file."; + // to do : find better exception + throw new NoSuchDefinitionException(msg); + } + + resolveInheritance(parent, definitions, locale, + alreadyResolvedDefinitions); + + definition.inherit(parent); + } + + /** + * Copies the definition map to be passed to a higher level of customization + * key. + * + * @param localeDefsMap The map of definition to be copied. + * @return The copy of the definition map. This particular implementation + * deep-copies the localeDefsMap into a {@link LinkedHashMap}. + * @since 2.1.4 + */ + @Override + protected Map copyDefinitionMap( + Map localeDefsMap) { + Map retValue = new LinkedHashMap<>( + localeDefsMap.size()); + + for (Map.Entry entry : localeDefsMap.entrySet()) { + Definition definition = new Definition(entry.getValue()); + retValue.put(entry.getKey(), definition); + } + + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/package-info.java new file mode 100644 index 0000000000..93cee86176 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +/** + * Classes to simply load definitions depending on a customization key. + * The package contains also basic implementations. + */ +package org.apache.tiles.core.definition.dao; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReader.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReader.java new file mode 100644 index 0000000000..ccbed0a819 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReader.java @@ -0,0 +1,479 @@ +/* + * 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.apache.tiles.core.definition.digester; + +import org.apache.commons.digester.Digester; +import org.apache.commons.digester.Rule; +import org.apache.struts2.StrutsException; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.core.definition.DefinitionsFactoryException; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.xml.sax.Attributes; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.SAXParseException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Reads {@link Definition} objects from + * an XML InputStream using Digester.

+ *

+ * This DefinitionsReader implementation expects the source to be + * passed as an InputStream. It parses XML data from the source + * and builds a Map of Definition objects. + *

+ *

+ *

+ * The Digester object can be configured by passing in initialization + * parameters. Currently the only parameter that is supported is the + * validating parameter. This value is set to false + * by default. To enable DTD validation for XML Definition files, give the init + * method a parameter with a key of + * org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE + * and a value of "true".

+ *

+ * The Definition objects are stored internally in a Map. The Map is stored as + * an instance variable rather than a local variable in the read + * method. This means that instances of this class are not + * thread-safe and access by multiple threads must be synchronized. + *

+ */ +public class DigesterDefinitionsReader implements DefinitionsReader { + + /** + * Digester validation parameter name. + */ + public static final String PARSER_VALIDATE_PARAMETER_NAME = "org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE"; + + // Digester rules constants for tag interception. + + /** + * Intercepts a <definition> tag. + */ + private static final String DEFINITION_TAG = "tiles-definitions/definition"; + + /** + * Intercepts a <put-attribute> tag. + */ + private static final String PUT_TAG = "*/definition/put-attribute"; + + /** + * Intercepts a <definition> inside a <put-attribute> tag. + */ + private static final String PUT_DEFINITION_TAG = "*/put-attribute/definition"; + + /** + * Intercepts a <definition> inside an <add-attribute> tag. + */ + private static final String ADD_DEFINITION_TAG = "*/add-attribute/definition"; + + /** + * Intercepts a <put-list-attribute> tag inside a %lt;definition> + * tag. + */ + private static final String DEF_LIST_TAG = "*/definition/put-list-attribute"; + + /** + * Intercepts a <add-attribute> tag. + */ + private static final String ADD_LIST_ELE_TAG = "*/add-attribute"; + + /** + * Intercepts a <add-list-attribute> tag. + */ + private static final String NESTED_LIST = "*/add-list-attribute"; + + // Handler class names. + + /** + * The handler to create definitions. + * + * @since 2.1.0 + */ + protected static final String DEFINITION_HANDLER_CLASS = + Definition.class.getName(); + + /** + * The handler to create attributes. + * + * @since 2.1.0 + */ + protected static final String PUT_ATTRIBUTE_HANDLER_CLASS = + Attribute.class.getName(); + + /** + * The handler to create list attributes. + * + * @since 2.1.0 + */ + protected static final String LIST_HANDLER_CLASS = + ListAttribute.class.getName(); + + /** + * Digester rule to manage definition filling. + * + * @since 2.1.2 + */ + public static class FillDefinitionRule extends Rule { + + /** {@inheritDoc} */ + @Override + public void begin(String namespace, String name, Attributes attributes) { + Definition definition = (Definition) digester.peek(); + definition.setName(attributes.getValue("name")); + definition.setPreparer(attributes.getValue("preparer")); + String extendsAttribute = attributes.getValue("extends"); + definition.setExtends(extendsAttribute); + + String template = attributes.getValue("template"); + Attribute attribute = Attribute.createTemplateAttribute(template); + attribute.setExpressionObject(Expression + .createExpressionFromDescribedExpression(attributes + .getValue("templateExpression"))); + attribute.setRole(attributes.getValue("role")); + String templateType = attributes.getValue("templateType"); + if (templateType != null) { + attribute.setRenderer(templateType); + } else if (extendsAttribute != null) { + attribute.setRenderer(null); + } + definition.setTemplateAttribute(attribute); + } + } + + /** + * Digester rule to manage attribute filling. + * + * @since 2.1.0 + */ + public static class FillAttributeRule extends Rule { + + /** {@inheritDoc} */ + @Override + public void begin(String namespace, String name, Attributes attributes) { + Attribute attribute = (Attribute) digester.peek(); + attribute.setValue(attributes.getValue("value")); + String expression = attributes.getValue("expression"); + attribute.setExpressionObject(Expression + .createExpressionFromDescribedExpression(expression)); + attribute.setRole(attributes.getValue("role")); + attribute.setRenderer(attributes.getValue("type")); + } + } + + /** + * Digester rule to manage assignment of the attribute to the parent + * element. + * + * @since 2.1.0 + */ + public static class PutAttributeRule extends Rule { + + /** {@inheritDoc} */ + @Override + public void begin(String namespace, String name, Attributes attributes) { + Attribute attribute = (Attribute) digester.peek(0); + Definition definition = (Definition) digester.peek(1); + definition.putAttribute(attributes.getValue("name"), attribute, + "true".equals(attributes.getValue("cascade"))); + } + } + + /** + * Digester rule to manage assignment of a nested definition in an attribute + * value. + * + * @since 2.1.0 + */ + public class AddNestedDefinitionRule extends Rule { + + /** {@inheritDoc} */ + @Override + public void begin(String namespace, String name, Attributes attributes) { + Definition definition = (Definition) digester.peek(0); + if (definition.getName() == null) { + definition.setName(getNextUniqueDefinitionName(definitions)); + } + Attribute attribute = (Attribute) digester.peek(1); + attribute.setValue(definition.getName()); + attribute.setRenderer("definition"); + } + } + + /** + * Digester object used to read Definition data + * from the source. + */ + protected Digester digester; + + /** + * The set of public identifiers, and corresponding resource names for + * the versions of the configuration file DTDs we know about. There + * MUST be an even number of Strings in this list! + */ + protected String[] registrations; + + /** + * Stores Definition objects. + */ + private Map definitions; + + /** + * Index to be used to create unique definition names for anonymous + * (nested) definitions. + */ + private int anonymousDefinitionIndex = 1; + + /** + * Creates a new instance of DigesterDefinitionsReader. + */ + public DigesterDefinitionsReader() { + digester = new Digester(); + digester.setNamespaceAware(true); + digester.setUseContextClassLoader(true); + digester.setErrorHandler(new ThrowingErrorHandler()); + try { + //OWASP + //https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html + digester.setFeature("http://xml.org/sax/features/external-general-entities", false); + digester.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + // Disable external DTDs as well + digester.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + digester.setXIncludeAware(false); + } catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) { + throw new StrutsException("Unable to disable external XML entity parsing", e); + } + + // Register our local copy of the DTDs that we can find + String[] registrations = getRegistrations(); + for (int i = 0; i < registrations.length; i += 2) { + URL url = this.getClass().getResource( + registrations[i + 1]); + if (url != null) { + digester.register(registrations[i], url.toString()); + } + } + + initSyntax(digester); + } + + /** + * Sets the validation of XML files. + * + * @param validating true means that XML validation is turned + * on. false otherwise. + * @since 3.3.0 + */ + public void setValidating(boolean validating) { + digester.setValidating(validating); + } + + /** + * Reads {@link Definition} objects from a source. + *

+ * Implementations should publish what type of source object is expected. + * + * @param source The InputStream source from which definitions + * will be read. + * @return a Map of Definition objects read from + * the source. + * @throws DefinitionsFactoryException If the source is invalid or + * an error occurs when reading definitions. + */ + public Map read(Object source) { + // This is an instance variable instead of a local variable because + // we want to be able to call the addDefinition method to populate it. + // But we reset the Map here, which, of course, has threading implications. + definitions = new LinkedHashMap<>(); + + if (source == null) { + // Perhaps we should throw an exception here. + return null; + } + + InputStream input; + try { + input = (InputStream) source; + } catch (ClassCastException e) { + throw new DefinitionsFactoryException( + "Invalid source type. Requires java.io.InputStream.", e); + } + + try { + // set first object in stack + //digester.clear(); + digester.push(this); + // parse + digester.parse(input); + + } catch (SAXException e) { + throw new DefinitionsFactoryException( + "XML error reading definitions.", e); + } catch (IOException e) { + throw new DefinitionsFactoryException( + "I/O Error reading definitions.", e); + } finally { + digester.clear(); + } + + return definitions; + } + + /** + * Initialised the syntax for reading XML files containing Tiles + * definitions. + * + * @param digester The digester to initialize. + */ + protected void initSyntax(Digester digester) { + initDigesterForTilesDefinitionsSyntax(digester); + } + + + /** + * Init digester for Tiles syntax with first element = tiles-definitions. + * + * @param digester Digester instance to use. + */ + private void initDigesterForTilesDefinitionsSyntax(Digester digester) { + // syntax rules + digester.addObjectCreate(DEFINITION_TAG, DEFINITION_HANDLER_CLASS); + digester.addRule(DEFINITION_TAG, new FillDefinitionRule()); + digester.addSetNext(DEFINITION_TAG, "addDefinition", DEFINITION_HANDLER_CLASS); + + // nested definition rules + digester.addObjectCreate(PUT_DEFINITION_TAG, DEFINITION_HANDLER_CLASS); + digester.addRule(PUT_DEFINITION_TAG, new FillDefinitionRule()); + digester.addSetRoot(PUT_DEFINITION_TAG, "addDefinition"); + digester.addRule(PUT_DEFINITION_TAG, new AddNestedDefinitionRule()); + digester.addObjectCreate(ADD_DEFINITION_TAG, DEFINITION_HANDLER_CLASS); + digester.addRule(ADD_DEFINITION_TAG, new FillDefinitionRule()); + digester.addSetRoot(ADD_DEFINITION_TAG, "addDefinition"); + digester.addRule(ADD_DEFINITION_TAG, new AddNestedDefinitionRule()); + + // put / putAttribute rules + // Rules for a same pattern are called in order, but rule.end() are called + // in reverse order. + // SetNext and CallMethod use rule.end() method. So, placing SetNext in + // first position ensure it will be called last (sic). + digester.addObjectCreate(PUT_TAG, PUT_ATTRIBUTE_HANDLER_CLASS); + digester.addRule(PUT_TAG, new FillAttributeRule()); + digester.addRule(PUT_TAG, new PutAttributeRule()); + // Definition level list rules + // This is rules for lists nested in a definition + digester.addObjectCreate(DEF_LIST_TAG, LIST_HANDLER_CLASS); + digester.addSetProperties(DEF_LIST_TAG); + digester.addRule(DEF_LIST_TAG, new PutAttributeRule()); + // list elements rules + // We use Attribute class to avoid rewriting a new class. + // Name part can't be used in listElement attribute. + digester.addObjectCreate(ADD_LIST_ELE_TAG, PUT_ATTRIBUTE_HANDLER_CLASS); + digester.addRule(ADD_LIST_ELE_TAG, new FillAttributeRule()); + digester.addSetNext(ADD_LIST_ELE_TAG, "add", PUT_ATTRIBUTE_HANDLER_CLASS); + + // nested list elements rules + // Create a list handler, and add it to parent list + digester.addObjectCreate(NESTED_LIST, LIST_HANDLER_CLASS); + digester.addSetProperties(NESTED_LIST); + digester.addSetNext(NESTED_LIST, "add", PUT_ATTRIBUTE_HANDLER_CLASS); + } + + /** + * Adds a new Definition to the internal Map or replaces + * an existing one. + * + * @param definition The Definition object to be added. + */ + public void addDefinition(Definition definition) { + String name = definition.getName(); + if (name == null) { + throw new DigesterDefinitionsReaderException("A root definition has been defined with no name"); + } + + definitions.put(name, definition); + } + + /** + * Error Handler that throws every exception it receives. + */ + private static class ThrowingErrorHandler implements ErrorHandler { + + /** {@inheritDoc} */ + public void warning(SAXParseException exception) throws SAXException { + throw exception; + } + + /** {@inheritDoc} */ + public void error(SAXParseException exception) throws SAXException { + throw exception; + } + + /** {@inheritDoc} */ + public void fatalError(SAXParseException exception) throws SAXException { + throw exception; + } + } + + /** + * Returns the registrations for local DTDs. + * + * @return An array containing the locations for registrations of local + * DTDs. + * @since 2.1.0 + */ + protected String[] getRegistrations() { + if (registrations == null) { + registrations = new String[] { + "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN", + "/org/apache/tiles/resources/tiles-config_3_0.dtd"}; + } + return registrations; + } + + /** + * Create a unique definition name usable to store anonymous definitions. + * + * @param definitions The already created definitions. + * @return The unique definition name to be used to store the definition. + * @since 2.1.0 + */ + protected String getNextUniqueDefinitionName( + Map definitions) { + String candidate; + + do { + candidate = "$anonymousDefinition" + anonymousDefinitionIndex; + anonymousDefinitionIndex++; + } while (definitions.containsKey(candidate)); + + return candidate; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderException.java new file mode 100644 index 0000000000..ca501e089b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderException.java @@ -0,0 +1,40 @@ +/* + * 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.apache.tiles.core.definition.digester; + +import org.apache.tiles.api.TilesException; + +/** + * Indicates that something went wrong during the use of + * {@link DigesterDefinitionsReader}. + * @since 2.1.0 + */ +public class DigesterDefinitionsReaderException extends TilesException { + + /** + * Constructor. + * + * @param message The detail message. + * @since 2.1.0 + */ + public DigesterDefinitionsReaderException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/package-info.java new file mode 100644 index 0000000000..49764f7cc0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Allows reading definitions with the use of Jakarta Commons Digester. + */ +package org.apache.tiles.core.definition.digester; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/package-info.java new file mode 100644 index 0000000000..1dc51fc77a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +/** + * It contains classes and interfaces to allow manipulations of "definitions", i.e. + * objects made of a template page and a number of filled attributes. + */ +package org.apache.tiles.core.definition; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolver.java new file mode 100644 index 0000000000..a960ec9bf2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolver.java @@ -0,0 +1,106 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A pattern definition resolver that stores {@link DefinitionPatternMatcher} + * separated by customization key.
+ * Implementations should provide a way to translate a definition to a + * {@link DefinitionPatternMatcher}. + * + * @param The type of the customization key. + * @since 2.2.0 + */ +public abstract class AbstractPatternDefinitionResolver implements PatternDefinitionResolver { + + /** + * Stores patterns depending on the locale they refer to. + */ + private final Map> localePatternPaths = new HashMap<>(); + + /** {@inheritDoc} */ + public Definition resolveDefinition(String name, T customizationKey) { + Definition retValue = null; + if (localePatternPaths.containsKey(customizationKey)) { + retValue = searchAndResolveDefinition(localePatternPaths + .get(customizationKey), name); + } + return retValue; + } + + /** {@inheritDoc} */ + public Map storeDefinitionPatterns(Map localeDefsMap, T customizationKey) { + List lpaths = localePatternPaths.computeIfAbsent(customizationKey, k -> new ArrayList<>()); + return addDefinitionsAsPatternMatchers(lpaths, localeDefsMap); + } + + /** + * Adds definitions, filtering and adding them to the list of definition + * pattern matchers. Only a subset of definitions will be transformed into + * definition pattern matchers. + * + * @param matchers The list containing the currently stored definition pattern + * matchers. + * @param defsMap The definition map to parse. + * @return The map of the definitions not recognized as containing + * definition patterns. + * @since 2.2.1 + */ + protected abstract Map addDefinitionsAsPatternMatchers(List matchers, Map defsMap); + + /** + * Try to resolve a definition by iterating all pattern matchers. + * + * @param paths The list containing the currently stored paths. + * @param name The name of the definition to resolve. + * @return A definition, if found, or null if not. + */ + private Definition searchAndResolveDefinition(List paths, String name) { + Definition d = null; + + for (DefinitionPatternMatcher wm : paths) { + d = wm.createDefinition(name); + if (d != null) { + break; + } + } + + return d; + } + + + /** + * Used to clear all entries in the localePatternPaths for a specific locale. Necessary when reloading definition + * files to ensure that the list is cleared first + * + * @param customizationKey customization key + */ + @Override + public void clearPatternPaths(T customizationKey) { + if (localePatternPaths.get(customizationKey) != null) + localePatternPaths.get(customizationKey).clear(); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolver.java new file mode 100644 index 0000000000..541805c232 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolver.java @@ -0,0 +1,75 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * A pattern definition resolver that stores {@link org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher} + * separated by customization key.
+ * It delegates creation of definition pattern matchers to a + * {@link DefinitionPatternMatcherFactory} and recgnizes patterns through the + * use of a {@link PatternRecognizer}. + * + * @param The type of the customization key. + * @since 2.2.0 + */ +public class BasicPatternDefinitionResolver extends AbstractPatternDefinitionResolver { + + /** + * The factory of pattern matchers. + */ + private final DefinitionPatternMatcherFactory definitionPatternMatcherFactory; + + /** + * The pattern recognizer. + */ + private final PatternRecognizer patternRecognizer; + + /** + * Constructor. + * + * @param definitionPatternMatcherFactory The definition pattern matcher factory. + * @param patternRecognizer The pattern recognizer. + */ + public BasicPatternDefinitionResolver(DefinitionPatternMatcherFactory definitionPatternMatcherFactory, PatternRecognizer patternRecognizer) { + this.definitionPatternMatcherFactory = definitionPatternMatcherFactory; + this.patternRecognizer = patternRecognizer; + } + + /** {@inheritDoc} */ + @Override + protected Map addDefinitionsAsPatternMatchers(List matchers, Map defsMap) { + Set excludedKeys = new LinkedHashSet<>(); + for (Map.Entry de : defsMap.entrySet()) { + String key = de.getKey(); + if (patternRecognizer.isPatternRecognized(key)) { + matchers.add(definitionPatternMatcherFactory.createDefinitionPatternMatcher(key, de.getValue())); + } else { + excludedKeys.add(key); + } + } + return PatternUtil.createExtractedMap(defsMap, excludedKeys); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcher.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcher.java new file mode 100644 index 0000000000..6577806502 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcher.java @@ -0,0 +1,40 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; + +/** + * Matches a definition name to a definition, through pattern-matching. The + * matched pattern should be a single one. + * @since 2.2.0 + */ +public interface DefinitionPatternMatcher { + + /** + * Creates a definition, given the definition name, through the use of + * pattern matching. + * + * @param definitionName The definition name to match. + * @return The created definition, if matched, or null if not + * matched. + * @since 2.2.0 + */ + Definition createDefinition(String definitionName); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcherFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcherFactory.java new file mode 100644 index 0000000000..df58907447 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcherFactory.java @@ -0,0 +1,41 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; + +/** + * Creates a new definition pattern matcher for the given pattern and the given + * base definition with pattern expressions. + * @since 2.2.0 + */ +public interface DefinitionPatternMatcherFactory { + + /** + * Creates a new definition pattern matcher. + * + * @param pattern The pattern to be matched. + * @param definition The base definition. Created definitions by + * {@link DefinitionPatternMatcher#createDefinition(String)} will created + * with this one as a basis. + * @return The definition pattern matcher. + * @since 2.2.0 + */ + DefinitionPatternMatcher createDefinitionPatternMatcher(String pattern, Definition definition); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolver.java new file mode 100644 index 0000000000..959f082b9e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolver.java @@ -0,0 +1,63 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; + +import java.util.Map; + +/** + * Resolves a definition starting from patterns stored in definition maps. + * + * @param The type of the customization key. + * @since 2.2.0 + */ +public interface PatternDefinitionResolver { + + /** + * Stores definition patterns. + * + * @param localeDefsMap The map of definitions that may contain also + * patterns. + * @param customizationKey The customization key. + * @return The map of the definitions not recognized as containing + * definition patterns. + * @since 2.2.1 + */ + Map storeDefinitionPatterns(Map localeDefsMap, T customizationKey); + + /** + * Resolves a definition searching in all patterns for the requested + * customization key. + * + * @param name The name of the definition. + * @param customizationKey The customization key. + * @return The resolved definition. + * @since 2.2.0 + */ + Definition resolveDefinition(String name, T customizationKey); + + /** + * Used to clear all entries in the localePatternPaths for a specific locale. Necessary when reloading definition + * files to ensure that the list is cleared first + * + * @param customizationKey customization key + */ + void clearPatternPaths(T customizationKey); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolverAware.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolverAware.java new file mode 100644 index 0000000000..e91945973e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolverAware.java @@ -0,0 +1,36 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +/** + * It indicates an object that uses a {@link org.apache.tiles.core.definition.pattern.PatternDefinitionResolver}. + * + * @param The type of the customization key. + * @since 2.2.0 + */ +public interface PatternDefinitionResolverAware { + + /** + * Sets the pattern definition resolver to use. + * + * @param definitionResolver The pattern definition resolver. + * @since 2.2.0 + */ + void setPatternDefinitionResolver(PatternDefinitionResolver definitionResolver); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternRecognizer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternRecognizer.java new file mode 100644 index 0000000000..0f3b23e66c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternRecognizer.java @@ -0,0 +1,37 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +/** + * Checks if a pattern (or a candidate one) is recognized as a pattern. + * + * @since 2.2.0 + */ +public interface PatternRecognizer { + + /** + * Checks if a pattern is recognized as a pattern. + * + * @param candidatePattern The pattern to check. + * @return true if the pattern has been recognized. + * @since 2.2.0 + */ + boolean isPatternRecognized(String candidatePattern); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternUtil.java new file mode 100644 index 0000000000..6d3dc39bc1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternUtil.java @@ -0,0 +1,240 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.ListAttribute; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utilities for pattern matching and substitution. + * + * @since 2.2.0 + */ +public final class PatternUtil { + + /** + * The root locale. Notice that this is a replacement for {@link Locale#ROOT} for + * Java 1.6. + */ + private static final Locale ROOT_LOCALE = new Locale("", ""); + + /** Pattern to find {.*} occurrences that do not match {[0-9]+} so to prevent MessageFormat from crashing. + */ + private static final Pattern INVALID_FORMAT_ELEMENT = Pattern.compile("\\{[^}0-9]+}"); + + /** + * Private constructor to avoid instantiation. + */ + private PatternUtil() { + } + + /** + * Creates a definition given its representation with wildcards and + * attribute values with placeholders, replacing real values into + * placeholders. + * + * @param d The definition to replace. + * @param name The name of the definition to be created. + * @param varsOrig The variables to be substituted. + * @return The definition that can be rendered. + * @since 2.2.0 + */ + public static Definition replacePlaceholders(Definition d, String name, + Object... varsOrig) { + + Object[] vars = replaceNullsWithBlank(varsOrig); + + Definition nudef = new Definition(); + + nudef.setExtends(replace(d.getExtends(), vars)); + nudef.setName(name); + nudef.setPreparer(replace(d.getPreparer(), vars)); + Attribute templateAttribute = d.getTemplateAttribute(); + if (templateAttribute != null) { + nudef.setTemplateAttribute(replaceVarsInAttribute( + templateAttribute, vars)); + } + + Set attributeNames = d.getLocalAttributeNames(); + if (attributeNames != null && !attributeNames.isEmpty()) { + for (String attributeName : attributeNames) { + Attribute attr = d.getLocalAttribute(attributeName); + Attribute nuattr = replaceVarsInAttribute(attr, vars); + + nudef.putAttribute(replace(attributeName, vars), nuattr); + } + } + + attributeNames = d.getCascadedAttributeNames(); + if (attributeNames != null && !attributeNames.isEmpty()) { + for (String attributeName : attributeNames) { + Attribute attr = d.getCascadedAttribute(attributeName); + Attribute nuattr = replaceVarsInAttribute(attr, vars); + + nudef.putAttribute(replace(attributeName, vars), nuattr, true); + } + } + + return nudef; + } + + /** + * Creates a new map that contains all the entries of the + * defsMap whose keys are contained in keys. + * + * @param map The map to read. + * @param keys The keys to extract. + * @param The key of the map. + * @param The value of the map. + * @return The extracted map. + * @since 2.2.1 + */ + public static Map createExtractedMap(Map map, Set keys) { + Map retValue = new LinkedHashMap<>(); + for (K key : keys) { + retValue.put(key, map.get(key)); + } + return retValue; + } + + /** + * Replaces variables into an attribute. + * + * @param attr The attribute to be used as a basis, containing placeholders + * for variables. + * @param vars The variables to replace. + * @return A new instance of an attribute, whose properties have been + * replaced with variables' values. + */ + private static Attribute replaceVarsInAttribute(Attribute attr, + Object... vars) { + Attribute nuattr; + if (attr instanceof ListAttribute) { + nuattr = replaceVarsInListAttribute((ListAttribute) attr, vars); + } else { + nuattr = replaceVarsInSimpleAttribute(attr, vars); + } + return nuattr; + } + + /** + * Replaces variables into a simple (not list) attribute. + * + * @param attr The attribute to be used as a basis, containing placeholders + * for variables. + * @param vars The variables to replace. + * @return A new instance of an attribute, whose properties have been + * replaced with variables' values. + */ + private static Attribute replaceVarsInSimpleAttribute(Attribute attr, + Object... vars) { + Attribute nuattr; + nuattr = new Attribute(); + + nuattr.setRole(replace(attr.getRole(), vars)); + nuattr.setRenderer(attr.getRenderer()); + Expression expressionObject = attr.getExpressionObject(); + if (expressionObject != null) { + Expression newExpressionObject = Expression + .createExpression(replace(expressionObject.getExpression(), vars), expressionObject.getLanguage()); + nuattr.setExpressionObject(newExpressionObject); + } + + Object value = attr.getValue(); + if (value instanceof String) { + value = replace((String) value, vars); + } + nuattr.setValue(value); + return nuattr; + } + + /** + * Replaces variables into a list attribute. + * + * @param listAttr The attribute to be used as a basis, containing attributes + * that may contain placeholders for variables. + * @param vars The variables to replace. + * @return A new instance of an attribute, whose properties have been + * replaced with variables' values. + */ + private static Attribute replaceVarsInListAttribute(ListAttribute listAttr, + Object... vars) { + Attribute nuattr; + ListAttribute nuListAttr = new ListAttribute(); + nuListAttr.setInherit(listAttr.isInherit()); + List nuItems = nuListAttr.getValue(); + for (Attribute item : listAttr.getValue()) { + Attribute child = item; + child = replaceVarsInAttribute(child, vars); + nuItems.add(child); + } + nuattr = nuListAttr; + return nuattr; + } + + /** + * Replaces a string with placeholders using values of a variable map. + * + * @param st The string to replace. + * @param vars The variables. + * @return The replaced string. + */ + private static String replace(String st, Object... vars) { + if (st != null && st.indexOf('{') >= 0) { + + // replace them with markers + List originals = new ArrayList<>(); + for(Matcher m = INVALID_FORMAT_ELEMENT.matcher(st); m.find() ; m = INVALID_FORMAT_ELEMENT.matcher(st)) { + originals.add(m.group()); + st = m.replaceFirst("INVALID_FORMAT_ELEMENT"); + } + + // do the MessageFormat replacement (escaping quote characters) + st = new MessageFormat(st.replaceAll("'", "'''"), ROOT_LOCALE) + .format(vars, new StringBuffer(), null).toString(); + + // return the markers to their original invalid occurrences + for (String original : originals) { + st = st.replaceFirst("INVALID_FORMAT_ELEMENT", original); + } + } + return st; + } + + private static Object[] replaceNullsWithBlank(Object[] varsOrig) { + Object[] vars = new Object[varsOrig.length]; + for(int i = 0; i < varsOrig.length; ++i) { + vars[i] = null != varsOrig[i] ? varsOrig[i] : ""; + } + return vars; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolver.java new file mode 100644 index 0000000000..a2148f1d85 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolver.java @@ -0,0 +1,103 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * This resolver allows the use of multiple pattern matching languages. The + * syntax of definition names must be LANGUAGENAME:expression.
+ * The different languages must be registered through the use of + * {@link #registerDefinitionPatternMatcherFactory(String, DefinitionPatternMatcherFactory)} + * method before using this resolver. + * + * @param The type of the customization key. + * @since 2.2.0 + */ +public class PrefixedPatternDefinitionResolver extends AbstractPatternDefinitionResolver { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(PrefixedPatternDefinitionResolver.class); + + /** + * Matches languages names to the corresponding + * {@link DefinitionPatternMatcherFactory}. + */ + private final Map language2matcherFactory; + + /** + * Constructor. + * + * @since 2.2.0 + */ + public PrefixedPatternDefinitionResolver() { + language2matcherFactory = new HashMap<>(); + } + + /** + * Registers a {@link DefinitionPatternMatcherFactory} connected to a + * particular language. + * + * @param language The name of the language. + * @param factory The pattern matcher factory to register. + * @since 2.2.0 + */ + public void registerDefinitionPatternMatcherFactory(String language, + DefinitionPatternMatcherFactory factory) { + language2matcherFactory.put(language, factory); + } + + /** {@inheritDoc} */ + @Override + protected Map addDefinitionsAsPatternMatchers(List matchers, Map defsMap) { + Set excludedKeys = new LinkedHashSet(); + for (Map.Entry entry : defsMap.entrySet()) { + String key = entry.getKey(); + Expression expression = Expression + .createExpressionFromDescribedExpression(key); + if (expression.getLanguage() != null) { + DefinitionPatternMatcherFactory factory = language2matcherFactory + .get(expression.getLanguage()); + if (factory != null) { + DefinitionPatternMatcher matcher = factory + .createDefinitionPatternMatcher(expression + .getExpression(), new Definition(entry + .getValue())); + matchers.add(matcher); + } else { + LOG.warn("Cannot find a DefinitionPatternMatcherFactory for expression '{}'", key); + } + } else { + excludedKeys.add(key); + } + } + return PatternUtil.createExtractedMap(defsMap, excludedKeys); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/package-info.java new file mode 100644 index 0000000000..d23eb0cad1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Classes to manage pattern matching in definition names, and substitution in attributes. + */ +package org.apache.tiles.core.definition.pattern; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcher.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcher.java new file mode 100644 index 0000000000..f060d69a56 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcher.java @@ -0,0 +1,72 @@ +/* + * 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.apache.tiles.core.definition.pattern.regexp; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.apache.tiles.core.definition.pattern.PatternUtil; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Matches regular expression patterns in definitions. + * + * @since 2.2.0 + */ +public class RegexpDefinitionPatternMatcher implements DefinitionPatternMatcher { + + /** + * The pattern to match. + */ + private final Pattern pattern; + + /** + * The definition to use as a basis. + */ + private final Definition definition; + + /** + * Constructor. + * + * @param pattern The pattern to use, in string form. + * @param definition The definition to use as a basis. + * @since 2.2.0 + */ + public RegexpDefinitionPatternMatcher(String pattern, Definition definition) { + this.pattern = Pattern.compile(pattern); + this.definition = definition; + } + + /** {@inheritDoc} */ + public Definition createDefinition(String definitionName) { + Definition retValue = null; + Matcher matcher = pattern.matcher(definitionName); + if (matcher.matches()) { + int groupCount = matcher.groupCount() + 1; + Object[] vars = new Object[groupCount]; + for (int i = 0; i < groupCount; i++) { + vars[i] = matcher.group(i); + } + retValue = PatternUtil.replacePlaceholders(definition, definitionName, vars); + } + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactory.java new file mode 100644 index 0000000000..77ae96c16b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactory.java @@ -0,0 +1,36 @@ +/* + * 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.apache.tiles.core.definition.pattern.regexp; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcherFactory; + +/** + * Creates instances of {@link RegexpDefinitionPatternMatcher}. + */ +public class RegexpDefinitionPatternMatcherFactory implements DefinitionPatternMatcherFactory { + + /** + * {@inheritDoc} + */ + public DefinitionPatternMatcher createDefinitionPatternMatcher(String pattern, Definition definition) { + return new RegexpDefinitionPatternMatcher(pattern, definition); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/package-info.java new file mode 100644 index 0000000000..dd679897ae --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * In Tiles it is possible to use regular expression patterns thanks to this package. + */ +package org.apache.tiles.core.definition.pattern.regexp; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcher.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcher.java new file mode 100644 index 0000000000..2650471597 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcher.java @@ -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.apache.tiles.core.definition.pattern.wildcard; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.apache.tiles.core.definition.pattern.PatternUtil; +import org.apache.tiles.core.util.WildcardHelper; + +import java.util.List; + +/** + * Matches wildcard patterns in definitions. + * + * @since 2.2.0 + */ +public class WildcardDefinitionPatternMatcher implements DefinitionPatternMatcher { + + /** + * Allows to parse wildcard expressions and to recognize substitution + * variables. + */ + private final WildcardHelper wildcardHelper; + + /** + * The definition to use as a basis. + */ + private final Definition definition; + + /** + * The pattern to use. + */ + private final int[] pattern; + + /** + * Constructor. + * + * @param pattern The pattern to use, in string form. + * @param definition The definition to use as a basis. + * @param wildcardHelper The object that parses wildcard expressions and + * recognized substitution variables. + * @since 2.2.0 + */ + public WildcardDefinitionPatternMatcher(String pattern, + Definition definition, WildcardHelper wildcardHelper) { + this.wildcardHelper = wildcardHelper; + this.definition = definition; + this.pattern = wildcardHelper.compilePattern(pattern); + } + + /** {@inheritDoc} */ + public Definition createDefinition(String definitionName) { + List vars = wildcardHelper.match(definitionName, pattern); + Definition d = null; + + if (vars != null) { + d = PatternUtil.replacePlaceholders(definition, definitionName, vars.toArray()); + } + + return d; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactory.java new file mode 100644 index 0000000000..34c1c793cc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactory.java @@ -0,0 +1,54 @@ +/* + * 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.apache.tiles.core.definition.pattern.wildcard; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcherFactory; +import org.apache.tiles.core.definition.pattern.PatternRecognizer; +import org.apache.tiles.core.util.WildcardHelper; + +/** + * Creates instances of {@link WildcardDefinitionPatternMatcher}. + * + * @since 2.2.0 + */ +public class WildcardDefinitionPatternMatcherFactory implements DefinitionPatternMatcherFactory, PatternRecognizer { + + /** + * Allows to parse wildcard expressions and to recognize substitution + * variables. + */ + private final WildcardHelper wildcardHelper = new WildcardHelper(); + + /** + * {@inheritDoc} + */ + public DefinitionPatternMatcher createDefinitionPatternMatcher( + String pattern, Definition definition) { + return new WildcardDefinitionPatternMatcher(pattern, definition, wildcardHelper); + } + + /** + * {@inheritDoc} + */ + public boolean isPatternRecognized(String candidatePattern) { + return candidatePattern.indexOf('*') >= 0; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/package-info.java new file mode 100644 index 0000000000..2b7f1231e8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * In Tiles it is possible to use wildcard patterns thanks to this package. + */ +package org.apache.tiles.core.definition.pattern.wildcard; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AbstractAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AbstractAttributeEvaluator.java new file mode 100644 index 0000000000..b035a0bbc1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AbstractAttributeEvaluator.java @@ -0,0 +1,50 @@ +/* + * 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.apache.tiles.core.evaluator; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.apache.tiles.request.Request; + +/** + * Abstract class to link a correct evaluation of an attribute, by evaluating + * {@link Attribute#getValue()} and then {@link Attribute#getExpressionObject()}. + * + * @since 2.1.2 + */ +public abstract class AbstractAttributeEvaluator implements AttributeEvaluator { + + /** {@inheritDoc} */ + public Object evaluate(Attribute attribute, Request request) { + if (attribute == null) { + throw new IllegalArgumentException("The attribute cannot be null"); + } + + Object retValue = attribute.getValue(); + + if (retValue == null) { + Expression expression = attribute.getExpressionObject(); + if (expression != null) { + retValue = evaluate(attribute.getExpressionObject().getExpression(), request); + } + } + + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluator.java new file mode 100644 index 0000000000..487c306c41 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluator.java @@ -0,0 +1,50 @@ +/* + * 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.apache.tiles.core.evaluator; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.request.Request; + +/** + * It represents an object that resolves a string to return an object. + * + * @since 2.1.0 + */ +public interface AttributeEvaluator { + + /** + * Evaluates an expression. + * + * @param expression The expression to evaluate. + * @param request The request object. + * @return The evaluated object. + * @since 2.1.0 + */ + Object evaluate(String expression, Request request); + + /** + * Evaluates an attribute value. + * + * @param attribute The attribute to evaluate. + * @param request The request object. + * @return The evaluated object. + * @since 2.1.0 + */ + Object evaluate(Attribute attribute, Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactory.java new file mode 100644 index 0000000000..56725d065b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactory.java @@ -0,0 +1,48 @@ +/* + * 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.apache.tiles.core.evaluator; + +import org.apache.tiles.api.Attribute; + +/** + * Creates an attribute evaluator using the language or an attribute. + * + * @since 2.2.0 + */ +public interface AttributeEvaluatorFactory { + + /** + * Creates and attribute evaluator using an attribute. + * + * @param attribute The attribute used to obtain the evaluator. + * @return The attribute evaluator. It must not be null. + * @since 2.2.0 + */ + AttributeEvaluator getAttributeEvaluator(Attribute attribute); + + /** + * Creates and attribute evaluator for the given expression language. + * + * @param language The name of the expression language. + * @return The attribute evaluator. It must not be null. + * @since 2.2.0 + */ + AttributeEvaluator getAttributeEvaluator(String language); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactoryAware.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactoryAware.java new file mode 100644 index 0000000000..f7dee1eec3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactoryAware.java @@ -0,0 +1,35 @@ +/* + * 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.apache.tiles.core.evaluator; + +/** + * It represents an object that can use an {@link AttributeEvaluatorFactory}. + * + * @since 2.2.0 + */ +public interface AttributeEvaluatorFactoryAware { + + /** + * Sets the attribute evaluator factory. + * + * @param attributeEvaluatorFactory The attribute evaluator factory to use. + * @since 2.2.0 + */ + void setAttributeEvaluatorFactory(AttributeEvaluatorFactory attributeEvaluatorFactory); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactory.java new file mode 100644 index 0000000000..7f87dc38d4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactory.java @@ -0,0 +1,88 @@ +/* + * 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.apache.tiles.core.evaluator; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; + +import java.util.HashMap; +import java.util.Map; + +/** + * Basic implementation of {@link AttributeEvaluatorFactory}. It supports a + * default attribute evaluator, in case the language is not recognized. + * + * @since 2.2.0 + */ +public class BasicAttributeEvaluatorFactory implements AttributeEvaluatorFactory { + + /** + * The default evaluator to return if it is not found in the map of known + * languages. + */ + private final AttributeEvaluator defaultEvaluator; + + /** + * Maps names of expression languages to their attribute evaluator. + * + * @since 2.2.0 + */ + private final Map language2evaluator; + + /** + * Constructor. + * + * @param defaultEvaluator The default evaluator to return if it is not + * found in the map of known languages. + * @since 2.2.0 + */ + public BasicAttributeEvaluatorFactory(AttributeEvaluator defaultEvaluator) { + this.defaultEvaluator = defaultEvaluator; + language2evaluator = new HashMap<>(); + } + + /** + * Registers a known expression language with its attribute evaluator. + * + * @param language The name of the expression language. + * @param evaluator The associated attribute evaluator. + * @since 2.2.0 + */ + public void registerAttributeEvaluator(String language, AttributeEvaluator evaluator) { + language2evaluator.put(language, evaluator); + } + + /** {@inheritDoc} */ + public AttributeEvaluator getAttributeEvaluator(String language) { + AttributeEvaluator retValue = language2evaluator.get(language); + if (retValue == null) { + retValue = defaultEvaluator; + } + return retValue; + } + + /** {@inheritDoc} */ + public AttributeEvaluator getAttributeEvaluator(Attribute attribute) { + Expression expression = attribute.getExpressionObject(); + if (expression != null) { + return getAttributeEvaluator(expression.getLanguage()); + } + return defaultEvaluator; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/EvaluationException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/EvaluationException.java new file mode 100644 index 0000000000..f5073706fb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/EvaluationException.java @@ -0,0 +1,50 @@ +/* + * 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.apache.tiles.core.evaluator; + +import org.apache.tiles.api.TilesException; + +/** + * Exception raised when an expression language evaluation fails. + * + * @since 2.2.0 + */ +public class EvaluationException extends TilesException { + + /** + * Constructor. + * + * @param e The cause. + * @since 2.2.0 + */ + public EvaluationException(Throwable e) { + super(e); + } + + /** + * Constructor. + * + * @param message The message- + * @param e The cause. + * @since 2.2.0 + */ + public EvaluationException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluator.java new file mode 100644 index 0000000000..7900872ac7 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluator.java @@ -0,0 +1,36 @@ +/* + * 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.apache.tiles.core.evaluator.impl; + +import org.apache.tiles.core.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.request.Request; + +/** + * Resolves a string and returns the string itself. It is useful for backward + * compatibility. + * + * @since 2.1.0 + */ +public class DirectAttributeEvaluator extends AbstractAttributeEvaluator { + + /** {@inheritDoc} */ + public Object evaluate(String expression, Request request) { + return expression; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/package-info.java new file mode 100644 index 0000000000..c8b19297c1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Classes to manage attribute value evaluation. + */ +package org.apache.tiles.core.evaluator.impl; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/package-info.java new file mode 100644 index 0000000000..2285788b6b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Interfaces to manage attribute value evaluation. + */ +package org.apache.tiles.core.evaluator; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/factory/AbstractTilesContainerFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/AbstractTilesContainerFactory.java new file mode 100644 index 0000000000..c64a309319 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/AbstractTilesContainerFactory.java @@ -0,0 +1,41 @@ +/* + * 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.apache.tiles.core.factory; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.ApplicationContext; + +/** + * Abstract Factory that creates instances of {@link TilesContainer}. + * + * @since 2.1.0 + */ +public abstract class AbstractTilesContainerFactory { + + /** + * Creates a Tiles container. + * + * @param applicationContext The Tiles application context object. + * @return The created container. + * @throws TilesContainerFactoryException If something goes wrong during + * instantiation. + * @since 2.1.1 + */ + public abstract TilesContainer createContainer(ApplicationContext applicationContext); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/factory/BasicTilesContainerFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/BasicTilesContainerFactory.java new file mode 100644 index 0000000000..7a424d31c1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/BasicTilesContainerFactory.java @@ -0,0 +1,406 @@ +/* + * 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.apache.tiles.core.factory; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.UnresolvingLocaleDefinitionsFactory; +import org.apache.tiles.core.definition.dao.BaseLocaleUrlDefinitionDAO; +import org.apache.tiles.core.definition.dao.DefinitionDAO; +import org.apache.tiles.core.definition.dao.ResolvingLocaleUrlDefinitionDAO; +import org.apache.tiles.core.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.core.definition.pattern.BasicPatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolverAware; +import org.apache.tiles.core.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.BasicAttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.impl.DirectAttributeEvaluator; +import org.apache.tiles.core.impl.BasicTilesContainer; +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.core.locale.impl.DefaultLocaleResolver; +import org.apache.tiles.core.prepare.factory.BasicPreparerFactory; +import org.apache.tiles.core.prepare.factory.PreparerFactory; +import org.apache.tiles.core.renderer.DefinitionRenderer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.render.BasicRendererFactory; +import org.apache.tiles.request.render.ChainedDelegateRenderer; +import org.apache.tiles.request.render.DispatchRenderer; +import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.render.RendererFactory; +import org.apache.tiles.request.render.StringRenderer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** + * Factory that builds a standard Tiles container using only Java code. + * + * @since 2.1.0 + */ +public class BasicTilesContainerFactory extends AbstractTilesContainerFactory { + + /** + * The string renderer name. + */ + protected static final String STRING_RENDERER_NAME = "string"; + + /** + * The template renderer name. + */ + protected static final String TEMPLATE_RENDERER_NAME = "template"; + + /** + * The definition renderer name. + */ + protected static final String DEFINITION_RENDERER_NAME = "definition"; + + /** + * {@inheritDoc} + */ + @Override + public TilesContainer createContainer(ApplicationContext applicationContext) { + BasicTilesContainer container = instantiateContainer(applicationContext); + container.setApplicationContext(applicationContext); + LocaleResolver resolver = createLocaleResolver(applicationContext); + container.setDefinitionsFactory(createDefinitionsFactory(applicationContext, resolver)); + AttributeEvaluatorFactory attributeEvaluatorFactory = createAttributeEvaluatorFactory(applicationContext, resolver); + container.setAttributeEvaluatorFactory(attributeEvaluatorFactory); + container.setPreparerFactory(createPreparerFactory(applicationContext)); + TilesContainer injectedContainer = createDecoratedContainer(container, applicationContext); + container.setRendererFactory(createRendererFactory(applicationContext, injectedContainer, attributeEvaluatorFactory)); + return injectedContainer; + } + + /** + * Instantiate the container, without initialization. + * + * @param context The Tiles application context object. + * @return The instantiated container. + * @since 2.1.1 + */ + protected BasicTilesContainer instantiateContainer(ApplicationContext context) { + return new BasicTilesContainer(); + } + + /** + * Instantiate the container that will be injected to child objects. + * + * @param originalContainer The original instantiated container. + * @param context The Tiles application context object. + * @return The instantiated container. + * @since 3.0.0 + */ + protected TilesContainer createDecoratedContainer( + TilesContainer originalContainer, + ApplicationContext context + ) { + return originalContainer; + } + + /** + * Creates the definitions factory. By default it creates a + * {@link UnresolvingLocaleDefinitionsFactory} with default dependencies. + * + * @param applicationContext The Tiles application context. + * @param resolver The locale resolver. + * @return The definitions factory. + * @since 2.1.1 + */ + protected DefinitionsFactory createDefinitionsFactory( + ApplicationContext applicationContext, + LocaleResolver resolver + ) { + UnresolvingLocaleDefinitionsFactory factory = instantiateDefinitionsFactory(applicationContext, resolver); + factory.setLocaleResolver(resolver); + factory.setDefinitionDAO(createLocaleDefinitionDao(applicationContext, resolver)); + return factory; + } + + /** + * Instantiate a new definitions factory based on Locale. + * + * @param applicationContext The Tiles application context. + * @param resolver The locale resolver. + * @return The definitions factory. + * @since 2.2.1 + */ + protected UnresolvingLocaleDefinitionsFactory instantiateDefinitionsFactory( + ApplicationContext applicationContext, + LocaleResolver resolver + ) { + return new UnresolvingLocaleDefinitionsFactory(); + } + + + /** + * Instantiate (and does not initialize) a Locale-based definition DAO. + * + * @param applicationContext The Tiles application context. + * @param resolver The locale resolver. + * @return The definition DAO. + * @since 2.1.1 + */ + protected BaseLocaleUrlDefinitionDAO instantiateLocaleDefinitionDao( + ApplicationContext applicationContext, + LocaleResolver resolver + ) { + return new ResolvingLocaleUrlDefinitionDAO(applicationContext); + } + + /** + * Creates a Locale-based definition DAO. + * + * @param applicationContext The Tiles application context. + * @param resolver The locale resolver. + * @return The definition DAO. + * @since 2.1.1 + */ + @SuppressWarnings("unchecked") + protected DefinitionDAO createLocaleDefinitionDao(ApplicationContext applicationContext, LocaleResolver resolver) { + BaseLocaleUrlDefinitionDAO definitionDao = instantiateLocaleDefinitionDao(applicationContext, resolver); + definitionDao.setReader(createDefinitionsReader(applicationContext)); + definitionDao.setSources(getSources(applicationContext)); + if (definitionDao instanceof PatternDefinitionResolverAware) { + ((PatternDefinitionResolverAware) definitionDao) + .setPatternDefinitionResolver(createPatternDefinitionResolver(Locale.class)); + } + return definitionDao; + } + + /** + * Creates the locale resolver. By default it creates a + * {@link DefaultLocaleResolver}. + * + * @param applicationContext The Tiles application context. + * @return The locale resolver. + * @since 2.1.1 + */ + protected LocaleResolver createLocaleResolver(ApplicationContext applicationContext) { + return new DefaultLocaleResolver(); + } + + /** + * Creates the definitions reader. By default it creates a + * {@link DigesterDefinitionsReader}. + * + * @param applicationContext The Tiles application context. + * @return The definitions reader. + * @since 2.1.1 + */ + protected DefinitionsReader createDefinitionsReader(ApplicationContext applicationContext) { + return new DigesterDefinitionsReader(); + } + + /** + * Returns a list containing the resources to be parsed. By default, it returns a + * list containing the resource at "/WEB-INF/tiles.xml". + * + * @param applicationContext The Tiles application context. + * @return The resources. + * @since 2.1.1 + */ + protected List getSources(ApplicationContext applicationContext) { + List retValue = new ArrayList<>(1); + retValue.add(applicationContext.getResource("/WEB-INF/tiles.xml")); + return retValue; + } + + /** + * Creates the attribute evaluator factory to use. By default it returns a + * {@link BasicAttributeEvaluatorFactory} containing the + * {@link DirectAttributeEvaluator} as the default evaluator. + * + * @param applicationContext The Tiles application context. + * @param resolver The locale resolver. + * @return The evaluator factory. + * @since 2.2.0 + */ + protected AttributeEvaluatorFactory createAttributeEvaluatorFactory( + ApplicationContext applicationContext, + LocaleResolver resolver) { + return new BasicAttributeEvaluatorFactory(new DirectAttributeEvaluator()); + } + + /** + * Creates the preparer factory to use. By default it returns a + * {@link BasicPreparerFactory}. + * + * @param applicationContext The Tiles application context. + * @return The preparer factory. + * @since 2.1.1 + */ + protected PreparerFactory createPreparerFactory(ApplicationContext applicationContext) { + return new BasicPreparerFactory(); + } + + /** + * Creates a renderer factory. By default, it returns a + * {@link BasicRendererFactory}, composed of an + * {@link ChainedDelegateRenderer} as default, and delegates of + * {@link StringRenderer}, {@link DispatchRenderer}, + * {@link DefinitionRenderer}. + * + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @return The renderer factory. + * @since 2.2.0 + */ + protected RendererFactory createRendererFactory(ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory) { + BasicRendererFactory retValue = new BasicRendererFactory(); + registerAttributeRenderers(retValue, applicationContext, container, + attributeEvaluatorFactory); + retValue.setDefaultRenderer(createDefaultAttributeRenderer(retValue, + applicationContext, container, attributeEvaluatorFactory)); + return retValue; + } + + /** + * Creates the default attribute renderer. By default it is an + * {@link ChainedDelegateRenderer}. + * + * @param rendererFactory The renderer factory to configure. + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @return The default attribute renderer. + * @since 3.0.0 + */ + protected Renderer createDefaultAttributeRenderer( + BasicRendererFactory rendererFactory, + ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory) { + ChainedDelegateRenderer retValue = new ChainedDelegateRenderer(); + retValue.addAttributeRenderer(rendererFactory.getRenderer(DEFINITION_RENDERER_NAME)); + retValue.addAttributeRenderer(rendererFactory.getRenderer(TEMPLATE_RENDERER_NAME)); + retValue.addAttributeRenderer(rendererFactory.getRenderer(STRING_RENDERER_NAME)); + return retValue; + } + + /** + * Creates a new pattern definition resolver. By default, it instantiate a + * {@link BasicPatternDefinitionResolver} with + * {@link WildcardDefinitionPatternMatcherFactory} to manage wildcard + * substitution. + * + * @param The type of the customization key. + * @param customizationKeyClass The customization key class. + * @return The pattern definition resolver. + * @since 2.2.0 + */ + protected PatternDefinitionResolver createPatternDefinitionResolver(Class customizationKeyClass) { + WildcardDefinitionPatternMatcherFactory definitionPatternMatcherFactory = new WildcardDefinitionPatternMatcherFactory(); + return new BasicPatternDefinitionResolver<>(definitionPatternMatcherFactory, definitionPatternMatcherFactory); + } + + /** + * Registers attribute renderers in a {@link BasicRendererFactory}. By + * default, it registers delegates to {@link StringRenderer}, + * {@link DispatchRenderer} and {@link DefinitionRenderer}. + * + * @param rendererFactory The renderer factory to configure. + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @since 2.2.0 + */ + protected void registerAttributeRenderers( + BasicRendererFactory rendererFactory, + ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory + ) { + rendererFactory.registerRenderer( + STRING_RENDERER_NAME, + createStringAttributeRenderer(rendererFactory, applicationContext, container, attributeEvaluatorFactory) + ); + rendererFactory.registerRenderer( + TEMPLATE_RENDERER_NAME, + createTemplateAttributeRenderer(rendererFactory, applicationContext, container, attributeEvaluatorFactory) + ); + rendererFactory.registerRenderer( + DEFINITION_RENDERER_NAME, + createDefinitionAttributeRenderer(rendererFactory, applicationContext, container, attributeEvaluatorFactory) + ); + } + + /** + * Creates an attribute renderer to render strings. + * + * @param rendererFactory The renderer factory to configure. + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @return The renderer. + * @since 3.0.0 + */ + protected Renderer createStringAttributeRenderer( + BasicRendererFactory rendererFactory, + ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory + ) { + return new StringRenderer(); + } + + /** + * Creates a {@link Renderer} that uses a {@link DispatchRenderer}. + * + * @param rendererFactory The renderer factory to configure. + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @return The renderer. + * @since 2.2.1 + */ + protected Renderer createTemplateAttributeRenderer( + BasicRendererFactory rendererFactory, + ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory + ) { + return new DispatchRenderer(); + } + + /** + * Creates a {@link Renderer} using a {@link DefinitionRenderer}. + * + * @param rendererFactory The renderer factory to configure. + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @return The renderer. + * @since 3.0.0 + */ + protected Renderer createDefinitionAttributeRenderer( + BasicRendererFactory rendererFactory, + ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory + ) { + return new DefinitionRenderer(container); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/factory/TilesContainerFactoryException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/TilesContainerFactoryException.java new file mode 100644 index 0000000000..8f1bdd4e57 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/TilesContainerFactoryException.java @@ -0,0 +1,41 @@ +/* + * 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.apache.tiles.core.factory; + +import org.apache.tiles.api.TilesException; + +/** + * Indicates that something went wrong in {@link AbstractTilesContainerFactory} use. + * + * @since 2.1.0 + */ +public class TilesContainerFactoryException extends TilesException { + + /** + * Constructor. + * + * @param message The detail message. + * @param e The exception to be wrapped. + * @since 2.1.0 + */ + public TilesContainerFactoryException(String message, Throwable e) { + super(message, e); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/factory/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/package-info.java new file mode 100644 index 0000000000..a9848e8654 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Factory classes, to allow creation of container instances. + */ +package org.apache.tiles.core.factory; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/impl/BasicTilesContainer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/BasicTilesContainer.java new file mode 100644 index 0000000000..922d01613e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/BasicTilesContainer.java @@ -0,0 +1,398 @@ +/* + * 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.apache.tiles.core.impl; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.BasicAttributeContext; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.core.evaluator.AttributeEvaluator; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactoryAware; +import org.apache.tiles.core.prepare.factory.NoSuchPreparerException; +import org.apache.tiles.core.prepare.factory.PreparerFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.CannotRenderException; +import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.render.RendererFactory; + +import java.io.IOException; +import java.util.Deque; +import java.util.LinkedList; +import java.util.Map; + +/** + * Basic implementation of the tiles container interface. + * In most cases, this container will be customized by + * injecting customized services, not necessarily by + * override the container + * + * @since 2.0 + */ +public class BasicTilesContainer implements TilesContainer, AttributeEvaluatorFactoryAware { + + /** + * Name used to store attribute context stack. + */ + private static final String ATTRIBUTE_CONTEXT_STACK = + "org.apache.tiles.AttributeContext.STACK"; + + /** + * Log instance for all BasicTilesContainer + * instances. + */ + private static final Logger LOG = LogManager.getLogger(BasicTilesContainer.class); + + /** + * The Tiles application context object. + */ + private ApplicationContext context; + + /** + * The definitions factory. + */ + private DefinitionsFactory definitionsFactory; + + /** + * The preparer factory. + */ + private PreparerFactory preparerFactory; + + /** + * The renderer factory. + */ + private RendererFactory rendererFactory; + + /** + * The attribute evaluator. + */ + private AttributeEvaluatorFactory attributeEvaluatorFactory; + + /** + * {@inheritDoc} + */ + public AttributeContext startContext(Request request) { + AttributeContext context = new BasicAttributeContext(); + Deque stack = getContextStack(request); + if (!stack.isEmpty()) { + AttributeContext parent = stack.peek(); + context.inheritCascadedAttributes(parent); + } + stack.push(context); + return context; + } + + /** + * {@inheritDoc} + */ + public void endContext(Request request) { + popContext(request); + } + + /** + * {@inheritDoc} + */ + public void renderContext(Request request) { + AttributeContext attributeContext = getAttributeContext(request); + + render(request, attributeContext); + } + + /** + * Returns the Tiles application context used by this container. + * + * @return the application context for this container. + */ + public ApplicationContext getApplicationContext() { + return context; + } + + /** + * Sets the Tiles application context to use. + * + * @param context The Tiles application context. + */ + public void setApplicationContext(ApplicationContext context) { + this.context = context; + } + + /** + * {@inheritDoc} + */ + public AttributeContext getAttributeContext(Request request) { + AttributeContext context = getContext(request); + if (context == null) { + context = new BasicAttributeContext(); + pushContext(context, request); + } + return context; + + } + + /** + * Set the definitions factory. This method first ensures + * that the container has not yet been initialized. + * + * @param definitionsFactory the definitions factory for this instance. + */ + public void setDefinitionsFactory(DefinitionsFactory definitionsFactory) { + this.definitionsFactory = definitionsFactory; + } + + /** + * Set the preparerInstance factory. This method first ensures + * that the container has not yet been initialized. + * + * @param preparerFactory the preparerInstance factory for this conainer. + */ + public void setPreparerFactory(PreparerFactory preparerFactory) { + this.preparerFactory = preparerFactory; + } + + /** + * Sets the renderer instance factory. + * + * @param rendererFactory the renderer instance factory for this container. + * @since 2.1.0 + */ + public void setRendererFactory(RendererFactory rendererFactory) { + this.rendererFactory = rendererFactory; + } + + /** + * {@inheritDoc} + */ + public void setAttributeEvaluatorFactory( + AttributeEvaluatorFactory attributeEvaluatorFactory) { + this.attributeEvaluatorFactory = attributeEvaluatorFactory; + } + + /** + * {@inheritDoc} + */ + public void prepare(String preparer, Request request) { + prepare(request, preparer, false); + } + + /** + * {@inheritDoc} + */ + public void render(String definitionName, Request request) { + LOG.debug("Render request received for definition '{}'", definitionName); + + Definition definition = getDefinition(definitionName, request); + + if (definition == null) { + throw new NoSuchDefinitionException("Unable to find the definition '" + definitionName + "'"); + } + + render(definition, request); + } + + /** + * Renders the specified definition. + * + * @param definition The definition to render. + * @param request The request context. + * @since 2.1.3 + */ + public void render(Definition definition, Request request) { + AttributeContext originalContext = getAttributeContext(request); + BasicAttributeContext subContext = new BasicAttributeContext(originalContext); + subContext.inherit(definition); + + pushContext(subContext, request); + + try { + render(request, subContext); + } finally { + popContext(request); + } + } + + /** + * {@inheritDoc} + */ + public void render(Attribute attr, Request request) + throws IOException { + if (attr == null) { + throw new CannotRenderException("Cannot render a null attribute"); + } + + if (attr.isPermitted(request)) { + Renderer renderer = rendererFactory.getRenderer(attr.getRenderer()); + Object value = evaluate(attr, request); + if (!(value instanceof String)) { + throw new CannotRenderException( + "Cannot render an attribute that is not a string, toString returns: " + + value); + } + renderer.render((String) value, request); + } + } + + /** + * {@inheritDoc} + */ + public Object evaluate(Attribute attribute, Request request) { + AttributeEvaluator evaluator = attributeEvaluatorFactory.getAttributeEvaluator(attribute); + return evaluator.evaluate(attribute, request); + } + + /** + * {@inheritDoc} + */ + public boolean isValidDefinition(String definitionName, Request request) { + try { + Definition definition = getDefinition(definitionName, request); + return definition != null; + } catch (NoSuchDefinitionException nsde) { + LOG.debug("Cannot find definition '{}'", definitionName); + LOG.debug("Exception related to the not found definition", nsde); + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public Definition getDefinition(String definitionName, Request request) { + return definitionsFactory.getDefinition(definitionName, request); + } + + /** + * Returns the context stack. + * + * @param tilesContext The Tiles context object to use. + * @return The needed stack of contexts. + * @since 2.0.6 + */ + @SuppressWarnings("unchecked") + protected Deque getContextStack(Request tilesContext) { + Map requestScope = tilesContext.getContext("request"); + Deque contextStack = (Deque) requestScope + .get(ATTRIBUTE_CONTEXT_STACK); + if (contextStack == null) { + contextStack = new LinkedList<>(); + requestScope.put(ATTRIBUTE_CONTEXT_STACK, contextStack); + } + + return contextStack; + } + + /** + * Pushes a context object in the stack. + * + * @param context The context to push. + * @param tilesContext The Tiles context object to use. + * @since 2.0.6 + */ + protected void pushContext(AttributeContext context, + Request tilesContext) { + Deque contextStack = getContextStack(tilesContext); + contextStack.push(context); + } + + /** + * Pops a context object out of the stack. + * + * @param tilesContext The Tiles context object to use. + * @return The popped context object. + * @since 2.0.6 + */ + protected AttributeContext popContext(Request tilesContext) { + Deque contextStack = getContextStack(tilesContext); + return contextStack.pop(); + } + + /** + * Get attribute context from request. + * + * @param tilesContext current Tiles application context. + * @return BasicAttributeContext or null if context is not found. + * @since 2.0.6 + */ + protected AttributeContext getContext(Request tilesContext) { + Deque contextStack = getContextStack(tilesContext); + if (!contextStack.isEmpty()) { + return contextStack.peek(); + } + return null; + } + + /** + * Execute a preparer. + * + * @param context The request context. + * @param preparerName The name of the preparer. + * @param ignoreMissing If true if the preparer is not found, + * it ignores the problem. + * @throws NoSuchPreparerException If the preparer is not found (and + * ignoreMissing is not set) or if the preparer itself threw an + * exception. + */ + private void prepare(Request context, String preparerName, boolean ignoreMissing) { + + LOG.debug("Prepare request received for '{}'", preparerName); + + ViewPreparer preparer = preparerFactory.getPreparer(preparerName, context); + if (preparer == null && ignoreMissing) { + return; + } + + if (preparer == null) { + throw new NoSuchPreparerException("Preparer '" + preparerName + " not found"); + } + + AttributeContext attributeContext = getContext(context); + + preparer.execute(context, attributeContext); + } + + /** + * Renders the specified attribute context. + * + * @param request The request context. + * @param attributeContext The context to render. + * @throws InvalidTemplateException If the template is not valid. + * @throws CannotRenderException If something goes wrong during rendering. + * @since 2.1.3 + */ + protected void render(Request request, + AttributeContext attributeContext) { + + try { + if (attributeContext.getPreparer() != null) { + prepare(request, attributeContext.getPreparer(), true); + } + + render(attributeContext.getTemplateAttribute(), request); + } catch (IOException e) { + throw new CannotRenderException(e.getMessage(), e); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/impl/InvalidTemplateException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/InvalidTemplateException.java new file mode 100644 index 0000000000..7b95722ff4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/InvalidTemplateException.java @@ -0,0 +1,50 @@ +/* + * 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.apache.tiles.core.impl; + +import org.apache.tiles.api.TilesException; + +/** + * An invalid template has been identified. + * + * @since 2.1.0 + */ +public class InvalidTemplateException extends TilesException { + + /** + * Constructor. + * + * @param message The detail message. + * @since 2.1.0 + */ + public InvalidTemplateException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param e The exception to be wrapped. + * @since 2.1.0 + */ + public InvalidTemplateException(Throwable e) { + super(e); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainer.java new file mode 100644 index 0000000000..0a18c7333d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainer.java @@ -0,0 +1,222 @@ +/* + * 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.apache.tiles.core.impl.mgmt; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.TilesContainerWrapper; +import org.apache.tiles.api.mgmt.MutableTilesContainer; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.request.Request; + +import java.util.HashMap; +import java.util.Map; + +/** + * Manages custom and configured definitions, so they can be used by the + * container, instead of using a simple {@link org.apache.tiles.core.definition.DefinitionsFactory}. + */ +public class CachingTilesContainer extends TilesContainerWrapper implements MutableTilesContainer { + + /** + * The default name of the attribute in which storing custom definitions. + */ + private static final String DEFAULT_DEFINITIONS_ATTRIBUTE_NAME = "org.apache.tiles.impl.mgmt.DefinitionManager.DEFINITIONS"; + + /** + * The name of the attribute in which storing custom definitions. + */ + private final String definitionsAttributeName; + + /** + * Constructor. + * + * @param originalContainer The original container to wrap. + */ + public CachingTilesContainer(TilesContainer originalContainer) { + super(originalContainer); + definitionsAttributeName = DEFAULT_DEFINITIONS_ATTRIBUTE_NAME; + } + + /** + * Returns a definition by name. + * + * @param definition The name of the definition. + * @param request The current request. + * @return The requested definition, either main or custom. + */ + public Definition getDefinition(String definition, Request request) { + Definition retValue; + retValue = getCustomDefinition(definition, request); + if (retValue == null) { + retValue = super.getDefinition(definition, request); + } + return retValue; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isValidDefinition(String definition, Request request) { + if (getCustomDefinition(definition, request) != null) { + return true; + } + return super.isValidDefinition(definition, request); + } + + /** + * {@inheritDoc} + */ + @Override + public void register(Definition definition, Request request) { + Map definitions = getOrCreateDefinitions(request); + if (definition.getName() == null) { + definition.setName(getNextUniqueDefinitionName(definitions)); + } + + if (definition.isExtending()) { + this.resolveInheritance(definition, request); + } + + definitions.put(definition.getName(), definition); + } + + /** + * {@inheritDoc} + */ + @Override + public void render(String definition, Request request) { + Definition toRender = getDefinition(definition, request); + if (toRender == null) { + throw new NoSuchDefinitionException("Cannot find definition named '" + definition + "'"); + } + super.render(toRender, request); + } + + /** + * Resolve inheritance. + * First, resolve parent's inheritance, then set template to the parent's + * template. + * Also copy attributes set in parent, and not set in child + * If instance doesn't extend anything, do nothing. + * + * @param definition The definition that needs to have its inheritances + * resolved. + * @param request The current request. + * @throws org.apache.tiles.core.definition.DefinitionsFactoryException If an + * inheritance can not be solved. + */ + private void resolveInheritance(Definition definition, + Request request) { + // Already done, or not needed ? + if (!definition.isExtending()) { + return; + } + + String parentDefinitionName = definition.getExtends(); + + boolean recurse = true; + Definition parent = getCustomDefinition(parentDefinitionName, request); + if (parent == null) { + parent = container.getDefinition(parentDefinitionName, request); + recurse = false; + } + + if (parent == null) { + throw new NoSuchDefinitionException( + "Error while resolving definition inheritance: child '" + + definition.getName() + + "' can't find its ancestor '" + + parentDefinitionName + + "'. Please check your description file."); + } + + // Resolve parent before itself. + if (recurse) { + resolveInheritance(parent, request); + } + definition.inherit(parent); + } + + /** + * Returns the map with custom definitions for the current request. + * + * @param request The current request. + * @return A map that connects a definition name to a definition. + */ + @SuppressWarnings("unchecked") + private Map getDefinitions( + Request request) { + return (Map) request.getContext("request") + .get(definitionsAttributeName); + } + + /** + * Returns a map of type "definition name -> definition" and, if it has not + * been defined before, creates one. + * + * @param request The current request. + * @return A map that connects a definition name to a definition. + */ + @SuppressWarnings("unchecked") + private Map getOrCreateDefinitions(Request request) { + Map definitions = (Map) request.getContext("request").get(definitionsAttributeName); + if (definitions == null) { + definitions = new HashMap<>(); + request.getContext("request").put(definitionsAttributeName, definitions); + } + + return definitions; + } + + /** + * Create a unique definition name usable to store anonymous definitions. + * + * @param definitions The already created definitions. + * @return The unique definition name to be used to store the definition. + * @since 2.1.0 + */ + private String getNextUniqueDefinitionName(Map definitions) { + String candidate; + int anonymousDefinitionIndex = 1; + + do { + candidate = "$anonymousMutableDefinition" + anonymousDefinitionIndex; + anonymousDefinitionIndex++; + } while (definitions.containsKey(candidate)); + + return candidate; + } + + /** + * Returns a custom definition from the cache. + * + * @param definition The definition to search. + * @param request The request. + * @return The requested definition. + */ + private Definition getCustomDefinition(String definition, Request request) { + Map definitions = getDefinitions(request); + if (definitions != null) { + return definitions.get(definition); + } + return null; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/package-info.java new file mode 100644 index 0000000000..e63fbe3fb1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * It contains the basic implementations of mutable Tiles containers. + */ +package org.apache.tiles.core.impl.mgmt; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/impl/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/package-info.java new file mode 100644 index 0000000000..7b89ff86e6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * It contains the basic implementations of Tiles container. + */ +package org.apache.tiles.core.impl; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/locale/LocaleResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/LocaleResolver.java new file mode 100644 index 0000000000..de73dc17ed --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/LocaleResolver.java @@ -0,0 +1,38 @@ +/* + * 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.apache.tiles.core.locale; + +import org.apache.tiles.request.Request; + +import java.util.Locale; + +/** + * It represents an object able to resolve the current locale for the current + * request, where its strategy depends on its implementation. + */ +public interface LocaleResolver { + + /** + * Resolves the locale. + * + * @param request The Tiles request object. + * @return The current locale for the current request. + */ + Locale resolveLocale(Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/DefaultLocaleResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/DefaultLocaleResolver.java new file mode 100644 index 0000000000..57d63b5973 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/DefaultLocaleResolver.java @@ -0,0 +1,55 @@ +/* + * 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.apache.tiles.core.locale.impl; + +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.request.Request; + +import java.util.Locale; +import java.util.Map; + +/** + * Default implementation of LocaleResolver
+ * It tries to take the locale from the session-scoped attribute + * {@link DefaultLocaleResolver#LOCALE_KEY}. If it is not found, it returns the + * locale included in the request. + */ +public class DefaultLocaleResolver implements LocaleResolver { + + /** + * The attribute name that is used to store the current locale. + */ + public static final String LOCALE_KEY = "org.apache.tiles.LOCALE"; + + /** + * {@inheritDoc} + */ + public Locale resolveLocale(Request request) { + Locale retValue = null; + Map session = request.getContext("session"); + if (session != null) { + retValue = (Locale) session.get(DefaultLocaleResolver.LOCALE_KEY); + } + if (retValue == null) { + retValue = request.getRequestLocale(); + } + + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/package-info.java new file mode 100644 index 0000000000..d8bb3d6bc8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Basic implementation of the locale resolver. + */ +package org.apache.tiles.core.locale.impl; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/locale/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/package-info.java new file mode 100644 index 0000000000..0470b39dfb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +/** + * Classes and interfaces to allow locale resolution in an application, i.e. it + * allows to specify how to access the locale that the user wants to use. + */ +package org.apache.tiles.core.locale; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/BasicPreparerFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/BasicPreparerFactory.java new file mode 100644 index 0000000000..b28151da20 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/BasicPreparerFactory.java @@ -0,0 +1,84 @@ +/* + * 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.apache.tiles.core.prepare.factory; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.reflect.ClassUtil; + +import java.util.HashMap; +import java.util.Map; + +/** + * Default implementation of the {@link org.apache.tiles.core.prepare.factory.PreparerFactory}. + * This factory provides no contextual configuration. It + * simply instantiates the named preparerInstance and returns it. + * + * @since Tiles 2.0 + */ +public class BasicPreparerFactory implements PreparerFactory { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(BasicPreparerFactory.class); + + /** + * Maps a preparer name to the instantiated preparer. + */ + protected Map preparers; + + /** + * Constructor. + */ + public BasicPreparerFactory() { + this.preparers = new HashMap<>(); + } + + + /** + * Create a new instance of the named preparerInstance. This factory + * expects all names to be qualified class names. + * + * @param name the named preparerInstance + * @param context current context + * @return ViewPreparer instance + */ + public ViewPreparer getPreparer(String name, Request context) { + if (!preparers.containsKey(name)) { + preparers.put(name, createPreparer(name)); + } + + return preparers.get(name); + } + + /** + * Creates a view preparer for the given name. + * + * @param name The name of the preparer. + * @return The created preparer. + */ + protected ViewPreparer createPreparer(String name) { + LOG.debug("Creating ViewPreparer '{}'", name); + Object instance = ClassUtil.instantiate(name, true); + return (ViewPreparer) instance; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/NoSuchPreparerException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/NoSuchPreparerException.java new file mode 100644 index 0000000000..1d4b502827 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/NoSuchPreparerException.java @@ -0,0 +1,39 @@ +/* + * 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.apache.tiles.core.prepare.factory; + +import org.apache.tiles.api.preparer.PreparerException; + +/** + * Thrown when the named preparerInstance can not be found. + * + * @since 2.0 + */ +public class NoSuchPreparerException extends PreparerException { + + /** + * Constructor. + * + * @param message The message to include. + */ + public NoSuchPreparerException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/PreparerFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/PreparerFactory.java new file mode 100644 index 0000000000..073ab3fb61 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/PreparerFactory.java @@ -0,0 +1,49 @@ +/* + * 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.apache.tiles.core.prepare.factory; + +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.request.Request; + +/** + *

+ * Factory interface used to create/retrieve instances of + * the {@link ViewPreparer} interface. + *

+ * + *

+ * This factory provides an extension point into the default + * tiles implementation. Implementors wishing to provide + * per request initialization of the ViewPreparer (for instance) + * may provide a custom prerparer. + *

+ * + * @since 2.0 + */ +public interface PreparerFactory { + + /** + * Create the named {link ViewPreparer} for the specified context. + * + * @param name ViewPreparer name, commonly the qualified classname. + * @param context the context within which the preparerInstance will be invoked. + * @return instance of the ViewPreparer + */ + ViewPreparer getPreparer(String name, Request context); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/package-info.java new file mode 100644 index 0000000000..c228befe80 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/package-info.java @@ -0,0 +1,26 @@ +/* + * 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. + */ +/** + * "View preparers" are objects that allows the "preparation" of a Tiles artifact + * (definition, template or attribute) before it is rendered.
+ * It is useful, for example, when a view item should be built and stored in a + * particular context (e.g. a menu) and then rendered. + */ +package org.apache.tiles.core.prepare.factory; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/DefinitionRenderer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/DefinitionRenderer.java new file mode 100644 index 0000000000..9becc6e431 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/DefinitionRenderer.java @@ -0,0 +1,67 @@ +/* + * 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.apache.tiles.core.renderer; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.CannotRenderException; +import org.apache.tiles.request.render.Renderer; + +import java.io.IOException; + +/** + * Renders an attribute that contains a reference to a definition. + * + * @since 3.0.0 + */ +public class DefinitionRenderer implements Renderer { + + /** + * The Tiles container. + */ + private final TilesContainer container; + + /** + * Constructor. + * + * @param container The Tiles container. + */ + public DefinitionRenderer(TilesContainer container) { + this.container = container; + } + + /** + * {@inheritDoc} + */ + @Override + public void render(String path, Request request) throws IOException { + if (path == null) { + throw new CannotRenderException("Cannot dispatch a null path"); + } + + container.render(path, request); + } + + /** + * {@inheritDoc} + */ + public boolean isRenderable(String path, Request request) { + return path != null && container.isValidDefinition(path, request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/package-info.java new file mode 100644 index 0000000000..089580e860 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Interfaces to manage attribute rendering. + */ +package org.apache.tiles.core.renderer; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/startup/AbstractTilesInitializer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/AbstractTilesInitializer.java new file mode 100644 index 0000000000..012665bf0d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/AbstractTilesInitializer.java @@ -0,0 +1,110 @@ +/* + * 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.apache.tiles.core.startup; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.core.factory.AbstractTilesContainerFactory; +import org.apache.tiles.request.ApplicationAccess; +import org.apache.tiles.request.ApplicationContext; + +/** + * Default Tiles initialization delegate implementation under a servlet + * environment. It uses init parameters to create the + * {@link ApplicationContext} and the {@link TilesContainer}. + * + * @since 2.2.0 + */ +public abstract class AbstractTilesInitializer implements TilesInitializer { + + /** + * The initialized application context. + */ + private ApplicationContext applicationContext; + + /** + * {@inheritDoc} + */ + public void initialize(ApplicationContext applicationContext) { + this.applicationContext = createTilesApplicationContext(applicationContext); + ApplicationAccess.register(applicationContext); + String key = getContainerKey(this.applicationContext); + // The initialized container. + TilesContainer container = createContainer(this.applicationContext); + TilesAccess.setContainer(this.applicationContext, container, key); + } + + /** + * {@inheritDoc} + */ + public void destroy() { + TilesAccess.setContainer(applicationContext, null, getContainerKey(applicationContext)); + } + + /** + * Creates the Tiles application context, to be used across all the + * Tiles-based application. If you override this class, please override this + * method.
+ * This implementation returns the preliminary context passed as a parameter + * + * @param preliminaryContext The preliminary application context to use. + * @return The Tiles application context. + * @since 2.2.0 + */ + protected ApplicationContext createTilesApplicationContext(ApplicationContext preliminaryContext) { + return preliminaryContext; + } + + /** + * Returns the container key under which the container will be stored. + * This implementation returns null so that the container will + * be the default one. + * + * @param applicationContext The Tiles application context to use. + * @return The container key. + * @since 2.2.0 + */ + protected String getContainerKey(ApplicationContext applicationContext) { + return null; + } + + /** + * Creates a Tiles container. If you override this class, please override + * this method or {@link #createContainerFactory(ApplicationContext)}. + * + * @param context The servlet context to use. + * @return The created container. + * @since 2.2.0 + */ + protected TilesContainer createContainer(ApplicationContext context) { + AbstractTilesContainerFactory factory = createContainerFactory(context); + return factory.createContainer(context); + } + + /** + * Creates a Tiles container factory. If you override this class, please + * override this method or {@link #createContainer(ApplicationContext)}. + * + * @param context The servlet context to use. + * @return The created container factory. + * @since 2.2.0 + */ + protected abstract AbstractTilesContainerFactory createContainerFactory( + ApplicationContext context); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/startup/TilesInitializer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/TilesInitializer.java new file mode 100644 index 0000000000..d9bfc0f6e9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/TilesInitializer.java @@ -0,0 +1,45 @@ +/* + * 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.apache.tiles.core.startup; + +import org.apache.tiles.request.ApplicationContext; + +/** + * Tiles initialization delegate. It initializes Tiles container(s) and the + * application context to use across all the application. + */ +public interface TilesInitializer { + + /** + * Initializes Tiles. + * + * @param preliminaryContext The preliminary application context to use. It + * will be overwritten with the real instance later. Use a context usable + * under your current environment, like ServletTilesApplicationContext or + * PortletTilesApplicationContext. + */ + void initialize(ApplicationContext preliminaryContext); + + /** + * Destroys the Tiles container. + * + * @since 2.2.0 + */ + void destroy(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/startup/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/package-info.java new file mode 100644 index 0000000000..3c06d86e34 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ +/** + * Classes to start the Tiles engine up. Use these classes in your environment by + * using a preliminary TilesApplicationContext that expose at least the needed + * initialization parameters. + */ +package org.apache.tiles.core.startup; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/util/CombinedBeanInfo.java b/plugins/tiles/src/main/java/org/apache/tiles/core/util/CombinedBeanInfo.java new file mode 100644 index 0000000000..425a3d7bfe --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/util/CombinedBeanInfo.java @@ -0,0 +1,95 @@ +/* + * 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.apache.tiles.core.util; + +import org.apache.tiles.request.reflect.ClassUtil; + +import java.beans.FeatureDescriptor; +import java.beans.PropertyDescriptor; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Contains the bean infos about one or more classes. + * @since 2.2.0 + */ +public class CombinedBeanInfo { + /** + * The descriptors of the introspected classes. + */ + private final List descriptors; + + /** + * Maps analyzed classes to the map of introspected properties. + */ + private final Map, Map> class2descriptors; + + /** + * Constructor. + * @param clazzes The list of classes to analyze and combine. + * + * @since 2.2.0 + */ + public CombinedBeanInfo(Class... clazzes) { + descriptors = new ArrayList<>(); + class2descriptors = new LinkedHashMap<>(); + for (Class clazz : clazzes) { + Map mappedDescriptors = new LinkedHashMap<>(); + ClassUtil.collectBeanInfo(clazz, mappedDescriptors); + descriptors.addAll(mappedDescriptors.values()); + class2descriptors.put(clazz, mappedDescriptors); + } + } + + /** + * Returns the descriptors of all the introspected classes. + * + * @return The feature descriptors. + * @since 2.2.0 + */ + public List getDescriptors() { + return descriptors; + } + + /** + * Returns a map of the introspected properties for the given class. + * + * @param clazz The class to get the properties from. + * @return The map of property descriptors. + * @since 2.2.0 + */ + public Map getMappedDescriptors(Class clazz) { + return class2descriptors.get(clazz); + } + + /** + * Returns the set of properties for the given introspected class. + * + * @param clazz The class to get the properties from. + * @return The set of properties. + * @since 2.2.0 + */ + public Set getProperties(Class clazz) { + return class2descriptors.get(clazz).keySet(); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/util/WildcardHelper.java b/plugins/tiles/src/main/java/org/apache/tiles/core/util/WildcardHelper.java new file mode 100644 index 0000000000..35f54a0641 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/util/WildcardHelper.java @@ -0,0 +1,543 @@ +/* + * 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.apache.tiles.core.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * This class is an utility class that perform wilcard-patterns matching and + * isolation taken from Apache Struts that is taken, in turn, from Apache + * Struts. + * + * @since 2.1.0 + */ +public class WildcardHelper { + /** + * The int representing '*' in the pattern int []. + * + * @since 2.1.0 + */ + protected static final int MATCH_FILE = -1; + + /** + * The int representing '**' in the pattern int []. + * + * @since 2.1.0 + */ + protected static final int MATCH_PATH = -2; + + /** + * The int representing begin in the pattern int []. + * + * @since 2.1.0 + */ + protected static final int MATCH_BEGIN = -4; + + /** + * The int representing end in pattern int []. + * + * @since 2.1.0 + */ + protected static final int MATCH_THEEND = -5; + + /** + * The int value that terminates the pattern int []. + * + * @since 2.1.0 + */ + protected static final int MATCH_END = -3; + + /** + * The length of the placeholder. + * + * @since 2.1.0 + */ + private static final int PLACEHOLDER_LENGTH = 3; + + /** + *

+ * Translate the given String into a int [] + * representing the pattern matchable by this class.
+ * This function translates a String into an int array + * converting the special '*' and '\' characters.
+ * Here is how the conversion algorithm works: + *

+ * + *
    + * + *
  • The '*' character is converted to MATCH_FILE, meaning that zero or + * more characters (excluding the path separator '/') are to be matched.
  • + * + *
  • The '**' sequence is converted to MATCH_PATH, meaning that zero or + * more characters (including the path separator '/') are to be matched.
  • + * + *
  • The '\' character is used as an escape sequence ('\*' is translated + * in '*', not in MATCH_FILE). If an exact '\' character is to be matched + * the source string must contain a '\\'. sequence.
  • + * + *
+ * + *

+ * When more than two '*' characters, not separated by another character, + * are found their value is considered as '**' (MATCH_PATH).
+ * The array is always terminated by a special value (MATCH_END).
+ * All MATCH* values are less than zero, while normal characters are equal + * or greater. + *

+ * + * @param data The string to translate. + * @return The encoded string as an int array, terminated by the MATCH_END + * value (don't consider the array length). + * @throws NullPointerException If data is null. + * @since 2.1.0 + */ + public int[] compilePattern(String data) { + // Prepare the arrays + int[] expr = new int[data.length() + 2]; + char[] buff = data.toCharArray(); + + // Prepare variables for the translation loop + int y = 0; + boolean slash = false; + + // Must start from beginning + expr[y++] = MATCH_BEGIN; + + if (buff.length > 0) { + if (buff[0] == '\\') { + slash = true; + } else if (buff[0] == '*') { + expr[y++] = MATCH_FILE; + } else { + expr[y++] = buff[0]; + } + + // Main translation loop + for (int x = 1; x < buff.length; x++) { + // If the previous char was '\' simply copy this char. + if (slash) { + expr[y++] = buff[x]; + slash = false; + + // If the previous char was not '\' we have to do a bunch of + // checks + } else { + // If this char is '\' declare that and continue + if (buff[x] == '\\') { + slash = true; + + // If this char is '*' check the previous one + } else if (buff[x] == '*') { + // If the previous character als was '*' match a path + if (expr[y - 1] <= MATCH_FILE) { + expr[y - 1] = MATCH_PATH; + } else { + expr[y++] = MATCH_FILE; + } + } else { + expr[y++] = buff[x]; + } + } + } + } + + // Must match end at the end + expr[y] = MATCH_THEEND; + + return expr; + } + + /** + * Match a pattern agains a string and isolates wildcard replacement into a + * Stack. + * + * @param data The string to match + * @param expr The compiled wildcard expression + * @return The list of matched variables, or null if it does not match. + * @throws NullPointerException If any parameters are null + * @since 2.2.0 + */ + public List match(String data, int[] expr) { + List varsValues = null; + + if (data == null) { + throw new NullPointerException("No data provided"); + } + + if (expr == null) { + throw new NullPointerException("No pattern expression provided"); + } + + char[] buff = data.toCharArray(); + + // Allocate the result buffer + char[] rslt = new char[expr.length + buff.length]; + + // The previous and current position of the expression character + // (MATCH_*) + int charpos = 0; + + // The position in the expression, input, translation and result arrays + int exprpos = 0; + int buffpos = 0; + int rsltpos = 0; + int offset = -1; + + // First check for MATCH_BEGIN + boolean matchBegin = false; + + if (expr[charpos] == MATCH_BEGIN) { + matchBegin = true; + exprpos = ++charpos; + } + + // Search the fist expression character (except MATCH_BEGIN - already + // skipped) + while (expr[charpos] >= 0) { + charpos++; + } + + // The expression charater (MATCH_*) + int exprchr = expr[charpos]; + + while (true) { + // Check if the data in the expression array before the current + // expression character matches the data in the input buffer + if (matchBegin) { + if (!matchArray(expr, exprpos, charpos, buff, buffpos)) { + return null; + } + + matchBegin = false; + } else { + offset = indexOfArray(expr, exprpos, charpos, buff, buffpos); + + if (offset < 0) { + return null; + } + } + + // Check for MATCH_BEGIN + if (matchBegin) { + if (offset != 0) { + return null; + } + + matchBegin = false; + } + + // Advance buffpos + buffpos += (charpos - exprpos); + + // Check for END's + if (exprchr == MATCH_END) { + if (rsltpos > 0) { + varsValues = addAndCreateList(varsValues, new String(rslt, + 0, rsltpos)); + } + + // Don't care about rest of input buffer + varsValues = addElementOnTop(varsValues, data); + return varsValues; + } else if (exprchr == MATCH_THEEND) { + if (rsltpos > 0) { + varsValues = addAndCreateList(varsValues, new String(rslt, + 0, rsltpos)); + } + + // Check that we reach buffer's end + if (buffpos == buff.length) { + addElementOnTop(varsValues, data); + return varsValues; + } + return null; + } + + // Search the next expression character + exprpos = ++charpos; + + while (expr[charpos] >= 0) { + charpos++; + } + + int prevchr = exprchr; + + exprchr = expr[charpos]; + + // We have here prevchr == * or **. + offset = (prevchr == MATCH_FILE) ? indexOfArray(expr, exprpos, + charpos, buff, buffpos) : lastIndexOfArray(expr, exprpos, + charpos, buff, buffpos); + + if (offset < 0) { + return null; + } + + // Copy the data from the source buffer into the result buffer + // to substitute the expression character + if (prevchr == MATCH_PATH) { + while (buffpos < offset) { + rslt[rsltpos++] = buff[buffpos++]; + } + } else { + // Matching file, don't copy '/' + while (buffpos < offset) { + if (buff[buffpos] == '/') { + return null; + } + + rslt[rsltpos++] = buff[buffpos++]; + } + } + + varsValues = addAndCreateList(varsValues, new String(rslt, 0, + rsltpos)); + rsltpos = 0; + } + } + + /** + * Get the offset of a part of an int array within a char array.
+ * This method return the index in d of the first occurrence after dpos of + * that part of array specified by r, starting at rpos and terminating at + * rend. + * + * @param r The array containing the data that need to be matched in d. + * @param rpos The index of the first character in r to look for. + * @param rend The index of the last character in r to look for plus 1. + * @param d The array of char that should contain a part of r. + * @param dpos The starting offset in d for the matching. + * @return The offset in d of the part of r matched in d or -1 if that was + * not found. + * @since 2.1.0 + */ + protected int indexOfArray(int[] r, int rpos, int rend, char[] d, int dpos) { + // Check if pos and len are legal + if (rend < rpos) { + throw new IllegalArgumentException("rend < rpos"); + } + + // If we need to match a zero length string return current dpos + if (rend == rpos) { + return (d.length); // ?? dpos? + } + + // If we need to match a 1 char length string do it simply + if ((rend - rpos) == 1) { + // Search for the specified character + for (int x = dpos; x < d.length; x++) { + if (r[rpos] == d[x]) { + return (x); + } + } + } + + // Main string matching loop. It gets executed if the characters to + // match are less then the characters left in the d buffer + while (((dpos + rend) - rpos) <= d.length) { + // Set current startpoint in d + int y = dpos; + + // Check every character in d for equity. If the string is matched + // return dpos + for (int x = rpos; x <= rend; x++) { + if (x == rend) { + return (dpos); + } + + if (r[x] != d[y++]) { + break; + } + } + + // Increase dpos to search for the same string at next offset + dpos++; + } + + // The remaining chars in d buffer were not enough or the string + // wasn't matched + return (-1); + } + + /** + * Get the offset of a last occurance of an int array within a char array. + *
+ * This method return the index in d of the last occurrence after dpos of + * that part of array specified by r, starting at rpos and terminating at + * rend. + * + * @param r The array containing the data that need to be matched in d. + * @param rpos The index of the first character in r to look for. + * @param rend The index of the last character in r to look for plus 1. + * @param d The array of char that should contain a part of r. + * @param dpos The starting offset in d for the matching. + * @return The offset in d of the last part of r matched in d or -1 if that + * was not found. + * @since 2.1.0 + */ + protected int lastIndexOfArray(int[] r, int rpos, int rend, char[] d, + int dpos) { + // Check if pos and len are legal + if (rend < rpos) { + throw new IllegalArgumentException("rend < rpos"); + } + + // If we need to match a zero length string return current dpos + if (rend == rpos) { + return (d.length); // ?? dpos? + } + + // If we need to match a 1 char length string do it simply + if ((rend - rpos) == 1) { + // Search for the specified character + for (int x = d.length - 1; x > dpos; x--) { + if (r[rpos] == d[x]) { + return (x); + } + } + } + + // Main string matching loop. It gets executed if the characters to + // match are less then the characters left in the d buffer + int l = d.length - (rend - rpos); + + while (l >= dpos) { + // Set current startpoint in d + int y = l; + + // Check every character in d for equity. If the string is matched + // return dpos + for (int x = rpos; x <= rend; x++) { + if (x == rend) { + return (l); + } + + if (r[x] != d[y++]) { + break; + } + } + + // Decrease l to search for the same string at next offset + l--; + } + + // The remaining chars in d buffer were not enough or the string + // wasn't matched + return (-1); + } + + /** + * Matches elements of array r from rpos to rend with array d, starting from + * dpos.
+ * This method return true if elements of array r from rpos to rend equals + * elements of array d starting from dpos to dpos+(rend-rpos). + * + * @param r The array containing the data that need to be matched in d. + * @param rpos The index of the first character in r to look for. + * @param rend The index of the last character in r to look for. + * @param d The array of char that should start from a part of r. + * @param dpos The starting offset in d for the matching. + * @return true if array d starts from portion of array r. + * @since 2.1.0 + */ + protected boolean matchArray(int[] r, int rpos, int rend, char[] d, int dpos) { + if ((d.length - dpos) < (rend - rpos)) { + return (false); + } + + for (int i = rpos; i < rend; i++) { + if (r[i] != d[dpos++]) { + return (false); + } + } + + return (true); + } + + /** + *

+ * Inserts into a value wildcard-matched strings where specified. + *

+ * + * @param val The value to convert + * @param vars A Map of wildcard-matched strings + * @return The new value + * @since 2.1.0 + */ + public static String convertParam(String val, Map vars) { + if (val == null) { + return null; + } else if (!val.contains("{")) { + return val; + } + + Map.Entry entry; + StringBuilder key = new StringBuilder("{0}"); + StringBuilder ret = new StringBuilder(val); + String keyTmp; + int x; + + for (Map.Entry integerStringEntry : vars.entrySet()) { + entry = integerStringEntry; + key.setCharAt(1, entry.getKey().toString().charAt(0)); + keyTmp = key.toString(); + + // Replace all instances of the placeholder + while ((x = ret.toString().indexOf(keyTmp)) > -1) { + ret.replace(x, x + PLACEHOLDER_LENGTH, entry.getValue()); + } + } + + return ret.toString(); + } + + /** + * Adds and object to a list. If the list is null, it creates it. + * + * @param The type of the element. + * @param list The list. + * @param data The data to add. + * @return The list itself, or a new one if it is null. + */ + private List addAndCreateList(List list, T data) { + if (list == null) { + list = new ArrayList<>(); + } + list.add(data); + return list; + } + + /** + * Adds and object on top of a list. If the list is null, it creates it. + * + * @param The type of the element. + * @param list The list. + * @param data The data to add. + * @return The list itself, or a new one if it is null. + */ + private List addElementOnTop(List list, T data) { + if (list == null) { + list = new ArrayList<>(); + } + list.add(0, data); + return list; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/util/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/util/package-info.java new file mode 100644 index 0000000000..9d03dc0e5d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/util/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Static utility classes used throughout the implementation. + */ +package org.apache.tiles.core.util; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/ELAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/tiles/el/ELAttributeEvaluator.java new file mode 100644 index 0000000000..cfa68da8a2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/ELAttributeEvaluator.java @@ -0,0 +1,92 @@ +/* + * 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.apache.tiles.el; + +import org.apache.tiles.core.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +import javax.el.ELResolver; +import javax.el.ExpressionFactory; +import javax.el.ValueExpression; + +/** + * Evaluates string expression with typical EL syntax.
+ * You can use normal EL syntax, knowing the root objects are + * {@link Request}, {@link ApplicationContext} and beans + * contained in request, session and application scope. + * + * @since 2.2.1 + */ +public class ELAttributeEvaluator extends AbstractAttributeEvaluator { + + /** + * The EL expression factory. + * + * @since 2.2.1 + */ + protected ExpressionFactory expressionFactory; + + /** + * The EL resolver to use. + * + * @since 2.2.1 + */ + protected ELResolver resolver; + + /** + * Constructor. + * + * @since 2.2.1 + */ + public ELAttributeEvaluator() { + } + + /** + * Sets the expression factory to use. + * + * @param expressionFactory The expression factory. + * @since 2.2.1 + */ + public void setExpressionFactory(ExpressionFactory expressionFactory) { + this.expressionFactory = expressionFactory; + } + + /** + * Sets the EL resolver to use. + * + * @param resolver The EL resolver. + * @since 2.2.1 + */ + public void setResolver(ELResolver resolver) { + this.resolver = resolver; + } + + /** {@inheritDoc} */ + public Object evaluate(String expression, Request request) { + ELContextImpl context = new ELContextImpl(resolver); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, + request.getApplicationContext()); + ValueExpression valueExpression = expressionFactory + .createValueExpression(context, expression, Object.class); + + return valueExpression.getValue(context); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/ELContextImpl.java b/plugins/tiles/src/main/java/org/apache/tiles/el/ELContextImpl.java new file mode 100644 index 0000000000..8e162ae404 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/ELContextImpl.java @@ -0,0 +1,144 @@ +/* + * 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.apache.tiles.el; + +import javax.el.ELContext; +import javax.el.ELResolver; +import javax.el.FunctionMapper; +import javax.el.ValueExpression; +import javax.el.VariableMapper; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * Implementation of ELContext.
+ * Copied from Apache Tomcat 6.0.16 source code. + * + * @since 2.2.1 + */ +public class ELContextImpl extends ELContext { + + /** + * A null function mapper. + */ + private static final FunctionMapper NULL_FUNCTION_MAPPER = new FunctionMapper() { + @Override + public Method resolveFunction(String prefix, String localName) { + return null; + } + }; + + /** + * Default implementation for the variable mapper. + */ + private static final class VariableMapperImpl extends VariableMapper { + + /** + * The mapped variables. + */ + private Map vars; + + /** {@inheritDoc} */ + @Override + public ValueExpression resolveVariable(String variable) { + if (vars == null) { + return null; + } + return vars.get(variable); + } + + /** {@inheritDoc} */ + @Override + public ValueExpression setVariable(String variable, + ValueExpression expression) { + if (vars == null) { + vars = new HashMap<>(); + } + return vars.put(variable, expression); + } + + } + + /** + * The EL resolver to use. + */ + private final ELResolver resolver; + + /** + * The function mapper to use. + */ + private FunctionMapper functionMapper = NULL_FUNCTION_MAPPER; + + /** + * The variable mapper to use. + */ + private VariableMapper variableMapper; + + /** + * Constructor. + * + * @param resolver The resolver to use. + */ + public ELContextImpl(ELResolver resolver) { + this.resolver = resolver; + } + + /** {@inheritDoc} */ + @Override + public ELResolver getELResolver() { + return this.resolver; + } + + /** {@inheritDoc} */ + @Override + public FunctionMapper getFunctionMapper() { + return this.functionMapper; + } + + /** {@inheritDoc} */ + @Override + public VariableMapper getVariableMapper() { + if (this.variableMapper == null) { + this.variableMapper = new VariableMapperImpl(); + } + return this.variableMapper; + } + + /** + * Sets the function mapper to use. + * + * @param functionMapper The function mapper. + * @since 2.2.1 + */ + public void setFunctionMapper(FunctionMapper functionMapper) { + this.functionMapper = functionMapper; + } + + /** + * Sets the variable mapper to use. + * + * @param variableMapper The variable mapper. + * @since 2.2.1 + */ + public void setVariableMapper(VariableMapper variableMapper) { + this.variableMapper = variableMapper; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/ExpressionFactoryFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/el/ExpressionFactoryFactory.java new file mode 100644 index 0000000000..f19a9e0e89 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/ExpressionFactoryFactory.java @@ -0,0 +1,37 @@ +/* + * 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.apache.tiles.el; + +import javax.el.ExpressionFactory; + +/** + * Interface to define a factory of {@link ExpressionFactory}. + * + * @since 2.2.1 + */ +public interface ExpressionFactoryFactory { + + /** + * Returns the expression factory to use. + * + * @return The expression factory. + * @since 2.2.1 + */ + ExpressionFactory getExpressionFactory(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/JspExpressionFactoryFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/el/JspExpressionFactoryFactory.java new file mode 100644 index 0000000000..5b9bd108b4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/JspExpressionFactoryFactory.java @@ -0,0 +1,63 @@ +/* + * 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.apache.tiles.el; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationContextAware; + +import javax.el.ExpressionFactory; +import javax.servlet.ServletContext; +import javax.servlet.jsp.JspFactory; + +/** + * Uses the JSP 2.1 {@link ExpressionFactory} to be used in Tiles. + * + * @since 2.2.1 + */ +public class JspExpressionFactoryFactory implements ExpressionFactoryFactory, ApplicationContextAware { + + /** + * The servlet context. + * + * @since 2.2.1 + */ + protected ServletContext servletContext; + + /** + * {@inheritDoc} + */ + public void setApplicationContext(ApplicationContext applicationContext) { + Object context = applicationContext.getContext(); + if (context instanceof ServletContext) { + this.servletContext = (ServletContext) context; + } else { + throw new IllegalArgumentException( + "The application context does not hold an instance of " + + "ServletContext, consider using JuelExpressionFactoryFactory"); + } + } + + /** + * {@inheritDoc} + */ + public ExpressionFactory getExpressionFactory() { + return JspFactory.getDefaultFactory().getJspApplicationContext( + servletContext).getExpressionFactory(); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/ScopeELResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/el/ScopeELResolver.java new file mode 100644 index 0000000000..8086e113ab --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/ScopeELResolver.java @@ -0,0 +1,143 @@ +/* + * 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.apache.tiles.el; + +import org.apache.tiles.request.Request; + +import javax.el.ELContext; +import javax.el.ELResolver; +import java.beans.FeatureDescriptor; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Resolves beans in request, session and application scope. + * + * @since 2.2.1 + */ +public class ScopeELResolver extends ELResolver { + + /** + * The length of the suffix: "Scope". + */ + private static final int SUFFIX_LENGTH = 5; + + /** + * {@inheritDoc} + */ + @Override + public Class getCommonPropertyType(ELContext context, Object base) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + return Map.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Iterator getFeatureDescriptors(ELContext context, Object base) { + if (base != null) { + return Collections.emptyIterator(); + } + + List list = new ArrayList<>(); + + Request request = (Request) context + .getContext(Request.class); + for (String scope : request.getAvailableScopes()) { + FeatureDescriptor descriptor = new FeatureDescriptor(); + descriptor.setDisplayName(scope + "Scope"); + descriptor.setExpert(false); + descriptor.setHidden(false); + descriptor.setName(scope + "Scope"); + descriptor.setPreferred(true); + descriptor.setShortDescription(""); + descriptor.setValue("type", Map.class); + descriptor.setValue("resolvableAtDesignTime", Boolean.FALSE); + list.add(descriptor); + } + + return list.iterator(); + } + + /** + * {@inheritDoc} + */ + @Override + public Class getType(ELContext context, Object base, Object property) { + if (base != null || !(property instanceof String) || !((String) property).endsWith("Scope")) { + return null; + } + + return Map.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getValue(ELContext context, Object base, Object property) { + if (base != null) { + return null; + } + + Object retValue = null; + String propertyString = (String) property; + if (property != null && propertyString.endsWith("Scope")) { + Request request = (Request) context + .getContext(Request.class); + retValue = request.getContext(propertyString.substring(0, + propertyString.length() - SUFFIX_LENGTH)); + } + + if (retValue != null) { + context.setPropertyResolved(true); + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isReadOnly(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException(); + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void setValue(ELContext context, Object base, Object property, + Object value) { + // Does nothing for the moment. + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextBeanELResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextBeanELResolver.java new file mode 100644 index 0000000000..117b4e6147 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextBeanELResolver.java @@ -0,0 +1,172 @@ +/* + * 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.apache.tiles.el; + +import org.apache.tiles.request.Request; + +import javax.el.ELContext; +import javax.el.ELResolver; +import java.beans.FeatureDescriptor; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Resolves beans in request, session and application scope. + * + * @since 2.2.1 + */ +public class TilesContextBeanELResolver extends ELResolver { + + /** {@inheritDoc} */ + @Override + public Class getCommonPropertyType(ELContext context, Object base) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + return String.class; + } + + /** {@inheritDoc} */ + @Override + public Iterator getFeatureDescriptors(ELContext context, Object base) { + List list = new ArrayList<>(); + + Request request = (Request) context.getContext(Request.class); + for (String scope : request.getAvailableScopes()) { + collectBeanInfo(request.getContext(scope), list); + } + return list.iterator(); + } + + /** {@inheritDoc} */ + @Override + public Class getType(ELContext context, Object base, Object property) { + if (base != null) { + return null; + } + + Object obj = findObjectByProperty(context, property); + if (obj != null) { + context.setPropertyResolved(true); + return obj.getClass(); + } + return null; + } + + /** {@inheritDoc} */ + @Override + public Object getValue(ELContext context, Object base, Object property) { + if (base != null) { + return null; + } + + Object retValue = findObjectByProperty(context, property); + + if (retValue != null) { + context.setPropertyResolved(true); + } + + return retValue; + } + + /** {@inheritDoc} */ + @Override + public boolean isReadOnly(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException(); + } + + return true; + } + + /** {@inheritDoc} */ + @Override + public void setValue(ELContext context, Object base, Object property, + Object value) { + // Does nothing for the moment. + } + + /** + * Collects bean infos from a map's values and filling a list. + * + * @param map The map containing the bean to be inspected. + * @param list The list to fill. + * @since 2.2.1 + */ + protected void collectBeanInfo(Map map, List list) { + if (map == null || map.isEmpty()) { + return; + } + + for (Map.Entry entry : map.entrySet()) { + FeatureDescriptor descriptor = new FeatureDescriptor(); + descriptor.setDisplayName(entry.getKey()); + descriptor.setExpert(false); + descriptor.setHidden(false); + descriptor.setName(entry.getKey()); + descriptor.setPreferred(true); + descriptor.setShortDescription(""); + descriptor.setValue("type", String.class); + descriptor.setValue("resolvableAtDesignTime", Boolean.FALSE); + list.add(descriptor); + } + } + + /** + * Finds an object in request, session or application scope, in this order. + * + * @param context The context to use. + * @param property The property used as an attribute name. + * @return The found bean, if it exists, or null otherwise. + * @since 2.2.1 + */ + protected Object findObjectByProperty(ELContext context, Object property) { + Object retValue; + Request request = (Request) context.getContext(Request.class); + String prop = property.toString(); + String[] scopes = request.getAvailableScopes().toArray(new String[0]); + int i = 0; + do { + retValue = getObject(request.getContext(scopes[i]), prop); + i++; + } while (retValue == null && i < scopes.length); + + return retValue; + } + + /** + * Returns an object from a map in a null-safe manner. + * + * @param map The map to use. + * @param property The property to use as a key. + * @return The object, if present, or null otherwise. + * @since 2.2.1 + */ + protected Object getObject(Map map, String property) { + Object retValue = null; + if (map != null) { + retValue = map.get(property); + } + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextELResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextELResolver.java new file mode 100644 index 0000000000..1296c5c344 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextELResolver.java @@ -0,0 +1,156 @@ +/* + * 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.apache.tiles.el; + +import org.apache.tiles.core.util.CombinedBeanInfo; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +import javax.el.ELContext; +import javax.el.ELResolver; +import java.beans.FeatureDescriptor; +import java.util.Iterator; + +/** + * Resolves properties of {@link Request} and + * {@link ApplicationContext}. + * + * @since 2.2.1 + */ +public class TilesContextELResolver extends ELResolver { + + /** + * Internal bean resolver to resolve beans in any context. + */ + private final ELResolver beanElResolver; + + /** + * Constructor. + * + * @param beanElResolver The used bean resolver. + */ + public TilesContextELResolver(ELResolver beanElResolver) { + this.beanElResolver = beanElResolver; + } + + /** + * The beaninfos about {@link Request} and {@link ApplicationContext}. + */ + private final CombinedBeanInfo requestBeanInfo = new CombinedBeanInfo(Request.class, ApplicationContext.class); + + /** + * {@inheritDoc} + */ + @Override + public Class getCommonPropertyType(ELContext context, Object base) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + return String.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Iterator getFeatureDescriptors(ELContext context, + Object base) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + return requestBeanInfo.getDescriptors().iterator(); + } + + /** + * {@inheritDoc} + */ + @Override + public Class getType(ELContext context, Object base, Object property) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + Class retValue = null; + if (requestBeanInfo.getProperties(Request.class).contains(property)) { + Request request = (Request) context.getContext(Request.class); + retValue = beanElResolver.getType(context, request, property); + } else if (requestBeanInfo.getProperties(ApplicationContext.class).contains(property)) { + ApplicationContext applicationContext = (ApplicationContext) context.getContext(ApplicationContext.class); + retValue = beanElResolver.getType(context, applicationContext, property); + } + + if (retValue != null) { + context.setPropertyResolved(true); + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getValue(ELContext context, Object base, Object property) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + Object retValue = null; + + if (requestBeanInfo.getProperties(Request.class).contains(property)) { + Request request = (Request) context.getContext(Request.class); + retValue = beanElResolver.getValue(context, request, property); + } else if (requestBeanInfo.getProperties(ApplicationContext.class).contains(property)) { + ApplicationContext applicationContext = (ApplicationContext) context.getContext(ApplicationContext.class); + retValue = beanElResolver.getValue(context, applicationContext, property); + } + + if (retValue != null) { + context.setPropertyResolved(true); + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isReadOnly(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException(); + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void setValue(ELContext context, Object base, Object property, Object value) { + // Does nothing for the moment. + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/el/package-info.java new file mode 100644 index 0000000000..f1886e81fd --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Attribute evaluator classes that can perform EL evaluation for attributes. + */ +package org.apache.tiles.el; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/package-info.java new file mode 100644 index 0000000000..7f77267d65 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Classes for supporting FreeMarker in Tiles. + */ +package org.apache.tiles.freemarker; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddAttributeFMModel.java new file mode 100644 index 0000000000..5c656fe874 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddAttributeFMModel.java @@ -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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Add an element to the surrounding list. Equivalent to 'putAttribute', but for + * list element. + *

+ * + *

+ * Add an element to the surrounding list. This tag can only be used inside + * 'putListAttribute' or 'addListAttribute' tags. Value can come from a direct + * assignment (value="aValue") + *

+ */ +public class AddAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.AddAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public AddAttributeFMModel(org.apache.tiles.template.AddAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("value", java.lang.Object.class, null), + runtime.getParameter("expression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("type", java.lang.String.class, null), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddListAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddListAttributeFMModel.java new file mode 100644 index 0000000000..ef81f9a448 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddListAttributeFMModel.java @@ -0,0 +1,73 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Declare a list that will be pass as an attribute. + *

+ *

+ * Declare a list that will be pass as an attribute . List elements are added + * using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used + * inside 'insertTemplate', 'insertDefinition' or 'definition' tag. + *

+ */ +public class AddListAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.AddListAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public AddListAttributeFMModel(org.apache.tiles.template.AddListAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("role", java.lang.String.class, null), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/DefinitionFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/DefinitionFMModel.java new file mode 100644 index 0000000000..433f44fbfc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/DefinitionFMModel.java @@ -0,0 +1,76 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Create a definition at runtime. + *

+ *

+ * Create a new definition at runtime. Newly created definition will be + * available across the entire request. + *

+ */ +public class DefinitionFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.DefinitionModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public DefinitionFMModel(org.apache.tiles.template.DefinitionModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("extends", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/GetAsStringFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/GetAsStringFMModel.java new file mode 100644 index 0000000000..555a708e1d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/GetAsStringFMModel.java @@ -0,0 +1,81 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Render the value of the specified template attribute to the current Writer + *

+ * + *

+ * Retrieve the value of the specified template attribute property, and render + * it to the current Writer as a String. The usual toString() conversions is + * applied on found value. + *

+ */ +public class GetAsStringFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.GetAsStringModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public GetAsStringFMModel(org.apache.tiles.template.GetAsStringModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("ignore", java.lang.Boolean.class, false), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("defaultValue", java.lang.Object.class, null), + runtime.getParameter("defaultValueRole", java.lang.String.class, null), + runtime.getParameter("defaultValueType", java.lang.String.class, null), + runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", org.apache.tiles.api.Attribute.class, null), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/ImportAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/ImportAttributeFMModel.java new file mode 100644 index 0000000000..ebee22db9e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/ImportAttributeFMModel.java @@ -0,0 +1,74 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Import attribute(s) in specified context. + *

+ *

+ * Import attribute(s) to requested scope. Attribute name and scope are + * optional. If not specified, all attributes are imported in page scope. Once + * imported, an attribute can be used as any other beans from jsp contexts. + *

+ */ +public class ImportAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.ImportAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public ImportAttributeFMModel(org.apache.tiles.template.ImportAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("scope", java.lang.String.class, null), + runtime.getParameter("toName", java.lang.String.class, null), + runtime.getParameter("ignore", java.lang.Boolean.class, false), request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertAttributeFMModel.java new file mode 100644 index 0000000000..67b36eec4d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertAttributeFMModel.java @@ -0,0 +1,94 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Inserts the value of an attribute into the page. + *

+ *

+ * This tag can be flexibly used to insert the value of an attribute into a + * page. As in other usages in Tiles, every attribute can be determined to have + * a "type", either set explicitly when it was defined, or "computed". If the + * type is not explicit, then if the attribute value is a valid definition, it + * will be inserted as such. Otherwise, if it begins with a "/" character, it + * will be treated as a "template". Finally, if it has not otherwise been + * assigned a type, it will be treated as a String and included without any + * special handling. + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertAttribute name="body" />
+ * 
+ */ +public class InsertAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public InsertAttributeFMModel(org.apache.tiles.template.InsertAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("ignore", java.lang.Boolean.class, false), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("defaultValue", java.lang.Object.class, null), + runtime.getParameter("defaultValueRole", java.lang.String.class, null), + runtime.getParameter("defaultValueType", java.lang.String.class, null), + runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", org.apache.tiles.api.Attribute.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertDefinitionFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertDefinitionFMModel.java new file mode 100644 index 0000000000..0f1cdd838c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertDefinitionFMModel.java @@ -0,0 +1,99 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Insert a definition. + *

+ *

+ * Insert a definition with the possibility to override and specify parameters + * (called attributes). A definition can be seen as a (partially or totally) + * filled template that can override or complete attribute values. + * <tiles:insertDefinition> allows to define these attributes and pass + * them to the inserted jsp page, called template. Attributes are defined using + * nested tag <tiles:putAttribute> or <tiles:putListAttribute>. + *

+ *

+ * You must specify name tag attribute, for inserting a definition from + * definitions factory. + *

+ *

+ * Example : + *

+ * + *
+ *     <tiles:insertDefinition name=".my.tiles.defininition flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertDefinition>
+ * 
+ */ +public class InsertDefinitionFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertDefinitionModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public InsertDefinitionFMModel(org.apache.tiles.template.InsertDefinitionModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("templateType", java.lang.String.class, null), + runtime.getParameter("templateExpression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertTemplateFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertTemplateFMModel.java new file mode 100644 index 0000000000..64c04acc97 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertTemplateFMModel.java @@ -0,0 +1,98 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Insert a template. + *

+ *

+ * Insert a template with the possibility to pass parameters (called + * attributes). A template can be seen as a procedure that can take parameters + * or attributes. <tiles:insertTemplate> allows to define these attributes + * and pass them to the inserted jsp page, called template. Attributes are + * defined using nested tag <tiles:putAttribute> or + * <tiles:putListAttribute>. + *

+ *

+ * You must specify template attribute, for inserting a template + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertTemplate template="/basic/myLayout.jsp" flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertTemplate>
+ * 
+ */ +public class InsertTemplateFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertTemplateModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public InsertTemplateFMModel(org.apache.tiles.template.InsertTemplateModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("templateType", java.lang.String.class, null), + runtime.getParameter("templateExpression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutAttributeFMModel.java new file mode 100644 index 0000000000..3d71b32a3a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutAttributeFMModel.java @@ -0,0 +1,101 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Put an attribute in enclosing attribute container tag. + *

+ *

+ * Enclosing attribute container tag can be : + *

    + *
  • <initContainer>
  • + *
  • <definition>
  • + *
  • <insertAttribute>
  • + *
  • <insertDefinition>
  • + *
  • <putListAttribute>
  • + *
+ * (or any other tag which implements the PutAttributeTagParent interface. + * Exception is thrown if no appropriate tag can be found. + *

+ *

+ * Put tag can have following atributes : + *

    + *
  • name : Name of the attribute
  • + *
  • value : value to put as attribute
  • + *
  • type : value type. Possible type are : string (value is used as direct + * string), template (value is used as a page url to insert), definition (value + * is used as a definition name to insert), object (value is used as it is)
  • + *
  • role : Role to check when 'insertAttribute' will be called.
  • + *
+ *

+ *

+ * Value can also come from tag body. Tag body is taken into account only if + * value is not set by one of the tag attributes. In this case Attribute type is + * "string", unless tag body define another type. + *

+ */ +public class PutAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.PutAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public PutAttributeFMModel(org.apache.tiles.template.PutAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", java.lang.Object.class, null), + runtime.getParameter("expression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("type", java.lang.String.class, null), + runtime.getParameter("cascade", java.lang.Boolean.class, false), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutListAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutListAttributeFMModel.java new file mode 100644 index 0000000000..3eb5cb2c72 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutListAttributeFMModel.java @@ -0,0 +1,76 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Declare a list that will be pass as attribute to tile. + *

+ *

+ * Declare a list that will be pass as attribute to tile. List elements are + * added using the tags 'addAttribute' or 'addListAttribute'. This tag can only + * be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. + *

+ */ +public class PutListAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.PutListAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public PutListAttributeFMModel(org.apache.tiles.template.PutListAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("inherit", java.lang.Boolean.class, false), + runtime.getParameter("cascade", java.lang.Boolean.class, false), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/SetCurrentContainerFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/SetCurrentContainerFMModel.java new file mode 100644 index 0000000000..66d56ce349 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/SetCurrentContainerFMModel.java @@ -0,0 +1,64 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + * Selects a container to be used as the "current" container. + */ +public class SetCurrentContainerFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.SetCurrentContainerModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public SetCurrentContainerFMModel(org.apache.tiles.template.SetCurrentContainerModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(runtime.getParameter("containerKey", java.lang.String.class, null), request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/TilesFMModelRepository.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/TilesFMModelRepository.java new file mode 100644 index 0000000000..d91766a2be --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/TilesFMModelRepository.java @@ -0,0 +1,199 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +/** + * This tag library provides Tiles tags. + */ +public class TilesFMModelRepository { + + /** + * The "insertDefinition" directive. + */ + private InsertDefinitionFMModel insertDefinition; + + /** + * The "importAttribute" directive. + */ + private ImportAttributeFMModel importAttribute; + + /** + * The "setCurrentContainer" directive. + */ + private SetCurrentContainerFMModel setCurrentContainer; + + /** + * The "addListAttribute" directive. + */ + private AddListAttributeFMModel addListAttribute; + + /** + * The "getAsString" directive. + */ + private GetAsStringFMModel getAsString; + + /** + * The "insertAttribute" directive. + */ + private InsertAttributeFMModel insertAttribute; + + /** + * The "putAttribute" directive. + */ + private PutAttributeFMModel putAttribute; + + /** + * The "definition" directive. + */ + private DefinitionFMModel definition; + + /** + * The "addAttribute" directive. + */ + private AddAttributeFMModel addAttribute; + + /** + * The "putListAttribute" directive. + */ + private PutListAttributeFMModel putListAttribute; + + /** + * The "insertTemplate" directive. + */ + private InsertTemplateFMModel insertTemplate; + + /** + * Constructor. + */ + public TilesFMModelRepository() { + insertDefinition = new InsertDefinitionFMModel(new org.apache.tiles.template.InsertDefinitionModel()); + importAttribute = new ImportAttributeFMModel(new org.apache.tiles.template.ImportAttributeModel()); + setCurrentContainer = new SetCurrentContainerFMModel(new org.apache.tiles.template.SetCurrentContainerModel()); + addListAttribute = new AddListAttributeFMModel(new org.apache.tiles.template.AddListAttributeModel()); + getAsString = new GetAsStringFMModel(new org.apache.tiles.template.GetAsStringModel()); + insertAttribute = new InsertAttributeFMModel(new org.apache.tiles.template.InsertAttributeModel()); + putAttribute = new PutAttributeFMModel(new org.apache.tiles.template.PutAttributeModel()); + definition = new DefinitionFMModel(new org.apache.tiles.template.DefinitionModel()); + addAttribute = new AddAttributeFMModel(new org.apache.tiles.template.AddAttributeModel()); + putListAttribute = new PutListAttributeFMModel(new org.apache.tiles.template.PutListAttributeModel()); + insertTemplate = new InsertTemplateFMModel(new org.apache.tiles.template.InsertTemplateModel()); + } + + /** + * Returns the "insertDefinition" directive. + * + * @return The "insertDefinition" directive. + */ + public InsertDefinitionFMModel getInsertDefinition() { + return insertDefinition; + } + + /** + * Returns the "importAttribute" directive. + * + * @return The "importAttribute" directive. + */ + public ImportAttributeFMModel getImportAttribute() { + return importAttribute; + } + + /** + * Returns the "setCurrentContainer" directive. + * + * @return The "setCurrentContainer" directive. + */ + public SetCurrentContainerFMModel getSetCurrentContainer() { + return setCurrentContainer; + } + + /** + * Returns the "addListAttribute" directive. + * + * @return The "addListAttribute" directive. + */ + public AddListAttributeFMModel getAddListAttribute() { + return addListAttribute; + } + + /** + * Returns the "getAsString" directive. + * + * @return The "getAsString" directive. + */ + public GetAsStringFMModel getGetAsString() { + return getAsString; + } + + /** + * Returns the "insertAttribute" directive. + * + * @return The "insertAttribute" directive. + */ + public InsertAttributeFMModel getInsertAttribute() { + return insertAttribute; + } + + /** + * Returns the "putAttribute" directive. + * + * @return The "putAttribute" directive. + */ + public PutAttributeFMModel getPutAttribute() { + return putAttribute; + } + + /** + * Returns the "definition" directive. + * + * @return The "definition" directive. + */ + public DefinitionFMModel getDefinition() { + return definition; + } + + /** + * Returns the "addAttribute" directive. + * + * @return The "addAttribute" directive. + */ + public AddAttributeFMModel getAddAttribute() { + return addAttribute; + } + + /** + * Returns the "putListAttribute" directive. + * + * @return The "putListAttribute" directive. + */ + public PutListAttributeFMModel getPutListAttribute() { + return putListAttribute; + } + + /** + * Returns the "insertTemplate" directive. + * + * @return The "insertTemplate" directive. + */ + public InsertTemplateFMModel getInsertTemplate() { + return insertTemplate; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/AnyScopePropertyAccessor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/AnyScopePropertyAccessor.java new file mode 100644 index 0000000000..aca95ce5f2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/AnyScopePropertyAccessor.java @@ -0,0 +1,89 @@ +/* + * 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.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.PropertyAccessor; +import org.apache.tiles.request.Request; + +import java.util.Map; + +/** + * Accesses attributes in any scope. + */ +public class AnyScopePropertyAccessor implements PropertyAccessor { + + @Override + public Object getProperty(Map context, Object target, Object name) { + Request request = (Request) target; + String attributeName = (String) name; + for (String scopeName : request.getAvailableScopes()) { + Map scope = request.getContext(scopeName); + if (scope.containsKey(attributeName)) { + return scope.get(attributeName); + } + } + return null; + } + + @Override + public String getSourceAccessor(OgnlContext context, Object target, Object index) { + Request request = (Request) target; + String attributeName = (String) index; + for (String scopeName : request.getAvailableScopes()) { + Map scope = request.getContext(scopeName); + if (scope.containsKey(attributeName)) { + return ".getContext(\"" + scopeName + "\").get(index)"; + } + } + return null; + } + + @Override + public String getSourceSetter(OgnlContext context, Object target, Object index) { + Request request = (Request) target; + String attributeName = (String) index; + String[] availableScopes = request.getAvailableScopes().toArray(new String[0]); + for (String scopeName : availableScopes) { + Map scope = request.getContext(scopeName); + if (scope.containsKey(attributeName)) { + return ".getContext(\"" + scopeName + "\").put(index, target)"; + } + } + return ".getContext(\"" + availableScopes[0] + "\").put(index, target)"; + } + + @Override + public void setProperty(Map context, Object target, Object name, Object value) { + Request request = (Request) target; + String attributeName = (String) name; + String[] availableScopes = request.getAvailableScopes().toArray(new String[0]); + for (String scopeName : availableScopes) { + Map scope = request.getContext(scopeName); + if (scope.containsKey(attributeName)) { + scope.put(attributeName, value); + return; + } + } + if (availableScopes.length > 0) { + request.getContext(availableScopes[0]).put(attributeName, value); + } + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/DelegatePropertyAccessor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/DelegatePropertyAccessor.java new file mode 100644 index 0000000000..637823a9b6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/DelegatePropertyAccessor.java @@ -0,0 +1,84 @@ +/* + * 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.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.OgnlException; +import ognl.PropertyAccessor; + +import java.util.Map; + +/** + * Uses a {@link PropertyAccessorDelegateFactory} to delegate the methods to + * another {@link PropertyAccessor}. + * + * @param The type of the accessed root object. + * @since 2.2.0 + */ +public class DelegatePropertyAccessor implements PropertyAccessor { + + /** + * The property accessor factory. + * + * @since 2.2.0 + */ + private final PropertyAccessorDelegateFactory factory; + + /** + * Constructor. + * + * @param factory The property accessor factory. + * @since 2.2.0 + */ + public DelegatePropertyAccessor(PropertyAccessorDelegateFactory factory) { + this.factory = factory; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public Object getProperty(Map context, Object target, Object name) throws OgnlException { + return factory.getPropertyAccessor((String) name, (T) target).getProperty(context, target, name); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { + factory.getPropertyAccessor((String) name, (T) target).setProperty(context, target, name, value); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public String getSourceAccessor(OgnlContext context, Object target, Object index) { + return factory.getPropertyAccessor((String) index, (T) target).getSourceAccessor(context, target, index); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public String getSourceSetter(OgnlContext context, Object target, Object index) { + return factory.getPropertyAccessor((String) index, (T) target).getSourceSetter(context, target, index); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessor.java new file mode 100644 index 0000000000..dbafb66c72 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessor.java @@ -0,0 +1,93 @@ +/* + * 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.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.OgnlException; +import ognl.PropertyAccessor; + +import java.util.Map; + +/** + * Uses a {@link PropertyAccessor} as a delegate, but passing a nested object as + * target. + * + * @param The root object type from which the target object will be extracted. + * @since 2.2.0 + */ +public class NestedObjectDelegatePropertyAccessor implements PropertyAccessor { + + /** + * The extractor of the nested object. + * + * @since 2.2.0 + */ + private final NestedObjectExtractor nestedObjectExtractor; + + /** + * The delegated property accessor. + * + * @since 2.2.0 + */ + private final PropertyAccessor propertyAccessor; + + /** + * Constructor. + * + * @param nestedObjectExtractor The extractor of the nested object. + * @param propertyAccessor The delegated property accessor. + * @since 2.2.0 + */ + public NestedObjectDelegatePropertyAccessor(NestedObjectExtractor nestedObjectExtractor, PropertyAccessor propertyAccessor) { + this.nestedObjectExtractor = nestedObjectExtractor; + this.propertyAccessor = propertyAccessor; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public Object getProperty(Map context, Object target, Object name) throws OgnlException { + return propertyAccessor.getProperty(context, nestedObjectExtractor.getNestedObject((T) target), name); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { + propertyAccessor.setProperty(context, nestedObjectExtractor.getNestedObject((T) target), name, value); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public String getSourceAccessor(OgnlContext context, Object target, Object index) { + return propertyAccessor.getSourceAccessor(context, nestedObjectExtractor.getNestedObject((T) target), index); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public String getSourceSetter(OgnlContext context, Object target, Object index) { + return propertyAccessor.getSourceSetter(context, nestedObjectExtractor.getNestedObject((T) target), index); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectExtractor.java new file mode 100644 index 0000000000..ba994d31ba --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectExtractor.java @@ -0,0 +1,37 @@ +/* + * 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.apache.tiles.ognl; + +/** + * Extracts an object using another object as a basis. + * + * @param The type of the root object. + * @since 2.2.0 + */ +public interface NestedObjectExtractor { + + /** + * Extracts the nested object. + * + * @param obj The root object. + * @return The extracted nested object. + * @since 2.2.0 + */ + Object getNestedObject(T obj); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/OGNLAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/OGNLAttributeEvaluator.java new file mode 100644 index 0000000000..cac54fdcb2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/OGNLAttributeEvaluator.java @@ -0,0 +1,45 @@ +/* + * 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.apache.tiles.ognl; + +import ognl.Ognl; +import ognl.OgnlException; +import org.apache.tiles.core.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.core.evaluator.EvaluationException; +import org.apache.tiles.request.Request; + +/** + * Evaluates attribute expressions and expressions with OGNL language. + * + * @since 2.2.0 + */ +public class OGNLAttributeEvaluator extends AbstractAttributeEvaluator { + + /** {@inheritDoc} */ + public Object evaluate(String expression, Request request) { + if (expression == null) { + throw new IllegalArgumentException("The expression parameter cannot be null"); + } + try { + return Ognl.getValue(expression, request); + } catch (OgnlException e) { + throw new EvaluationException("Cannot evaluate OGNL expression '" + expression + "'", e); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/PropertyAccessorDelegateFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/PropertyAccessorDelegateFactory.java new file mode 100644 index 0000000000..b781b402a2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/PropertyAccessorDelegateFactory.java @@ -0,0 +1,43 @@ +/* + * 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.apache.tiles.ognl; + +import ognl.PropertyAccessor; + +/** + * Decides a {@link PropertyAccessor} depending on the property name and the + * object to evaluate. + * + * @param The type of the root object to evaluate. + * @since 2.2.0 + */ +public interface PropertyAccessorDelegateFactory { + + /** + * Returns a prooerty accessor appropriate for the property name and the + * object passed. + * + * @param propertyName The name of the property. + * @param obj The root object to evaluate. + * @return The appropriate property accessor. + * @since 2.2.0 + */ + PropertyAccessor getPropertyAccessor(String propertyName, T obj); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/ScopePropertyAccessor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/ScopePropertyAccessor.java new file mode 100644 index 0000000000..bb45085b60 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/ScopePropertyAccessor.java @@ -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.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.PropertyAccessor; +import org.apache.tiles.request.Request; + +import java.util.Map; + +/** + * Accesses a scope. + */ +public class ScopePropertyAccessor implements PropertyAccessor { + + /** + * The length of the scope suffix: "Scope". + */ + static final int SCOPE_SUFFIX_LENGTH = 5; + + @Override + public Object getProperty(Map context, Object target, Object name) { + Request request = (Request) target; + String scope = (String) name; + if (scope.endsWith("Scope")) { + String scopeName = scope.substring(0, scope.length() - SCOPE_SUFFIX_LENGTH); + return request.getContext(scopeName); + } + return null; + } + + @Override + public String getSourceAccessor(OgnlContext context, Object target, Object index) { + String scope = (String) index; + if (scope.endsWith("Scope")) { + String scopeName = scope.substring(0, scope.length() - SCOPE_SUFFIX_LENGTH); + return ".getContext(\"" + scopeName + "\")"; + } + return null; + } + + @Override + public String getSourceSetter(OgnlContext context, Object target, Object index) { + return null; + } + + @Override + public void setProperty(Map context, Object target, Object name, Object value) { + // Does nothing. + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractor.java new file mode 100644 index 0000000000..60f4321af6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractor.java @@ -0,0 +1,35 @@ +/* + * 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.apache.tiles.ognl; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +/** + * Extracts the application context from a Tiles request. + * + * @since 2.2.0 + */ +public class TilesApplicationContextNestedObjectExtractor implements NestedObjectExtractor { + + /** {@inheritDoc} */ + public ApplicationContext getNestedObject(Request obj) { + return obj.getApplicationContext(); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactory.java new file mode 100644 index 0000000000..5106f656a6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactory.java @@ -0,0 +1,103 @@ +/* + * 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.apache.tiles.ognl; + +import ognl.PropertyAccessor; +import org.apache.tiles.core.util.CombinedBeanInfo; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +/** + * Decides the appropriate {@link PropertyAccessor} for the given property name + * and {@link Request}. + * + * @since 2.2.0 + */ +public class TilesContextPropertyAccessorDelegateFactory implements PropertyAccessorDelegateFactory { + + /** + * The plain object property accessor, to be used directly for + * {@link Request}. + */ + private final PropertyAccessor objectPropertyAccessor; + + /** + * The application context property accessor. + */ + private final PropertyAccessor applicationContextPropertyAccessor; + + /** + * The request scope property accessor. + */ + private final PropertyAccessor anyScopePropertyAccessor; + + /** + * The session scope property accessor. + */ + private final PropertyAccessor scopePropertyAccessor; + + /** + * The bean info of {@link Request} and + * {@link ApplicationContext}. + */ + private final CombinedBeanInfo beanInfo; + + /** + * Constructor. + * + * @param objectPropertyAccessor The plain object property accessor, to be + * used directly for {@link Request}. + * @param applicationContextPropertyAccessor The application context + * property accessor. + * @param anyScopePropertyAccessor The request scope property accessor. + * @param scopePropertyAccessor The session scope property accessor. + * @since 2.2.0 + */ + public TilesContextPropertyAccessorDelegateFactory( + PropertyAccessor objectPropertyAccessor, + PropertyAccessor applicationContextPropertyAccessor, + PropertyAccessor anyScopePropertyAccessor, + PropertyAccessor scopePropertyAccessor + ) { + beanInfo = new CombinedBeanInfo(Request.class, ApplicationContext.class); + this.objectPropertyAccessor = objectPropertyAccessor; + this.applicationContextPropertyAccessor = applicationContextPropertyAccessor; + this.anyScopePropertyAccessor = anyScopePropertyAccessor; + this.scopePropertyAccessor = scopePropertyAccessor; + } + + /** {@inheritDoc} */ + public PropertyAccessor getPropertyAccessor(String propertyName, Request request) { + PropertyAccessor retValue; + if (propertyName.endsWith("Scope")) { + String scopeName = propertyName.substring(0, propertyName.length() - ScopePropertyAccessor.SCOPE_SUFFIX_LENGTH); + if (request.getContext(scopeName) != null) { + return scopePropertyAccessor; + } + } + if (beanInfo.getMappedDescriptors(Request.class).containsKey(propertyName)) { + retValue = objectPropertyAccessor; + } else if (beanInfo.getMappedDescriptors(ApplicationContext.class).containsKey(propertyName)) { + retValue = applicationContextPropertyAccessor; + } else { + return anyScopePropertyAccessor; + } + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/package-info.java new file mode 100644 index 0000000000..69d74a282c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Attribute evaluator classes that can perform OGNL evaluation for attributes. + */ +package org.apache.tiles.ognl; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractClientRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractClientRequest.java new file mode 100644 index 0000000000..459c54c1b9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractClientRequest.java @@ -0,0 +1,91 @@ +/* + * 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.apache.tiles.request; + +import java.io.IOException; +import java.util.Map; + +/** + * Base class for "client" requests, i.e. requests that come unchanged by the + * container, such as ServletRequest and PortletRequest. + */ +public abstract class AbstractClientRequest extends AbstractRequest { + + /** + * The application context. + */ + private final ApplicationContext applicationContext; + + /** + * Constructor. + * + * @param applicationContext The application context. + */ + public AbstractClientRequest(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + + @Override + public void dispatch(String path) throws IOException { + if (isForceInclude()) { + doInclude(path); + } else { + setForceInclude(true); + doForward(path); + } + } + + @Override + public void include(String path) throws IOException { + setForceInclude(true); + doInclude(path); + } + + @Override + public ApplicationContext getApplicationContext() { + return applicationContext; + } + + /** + * Returns the application scope. + * + * @return The application scope. + */ + public Map getApplicationScope() { + return applicationContext.getApplicationScope(); + } + + /** + * Forwards to a path. + * + * @param path The path to forward to. + * @throws IOException If something goes wrong when forwarding. + */ + protected abstract void doForward(String path) throws IOException; + + /** + * Includes the result of a path. + * + * @param path The path to forward to. + * @throws IOException If something goes wrong when forwarding. + */ + protected abstract void doInclude(String path) throws IOException; + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractRequest.java new file mode 100644 index 0000000000..7fd52d9c61 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractRequest.java @@ -0,0 +1,54 @@ +/* + * 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.apache.tiles.request; + +/** + * Base request. + */ +public abstract class AbstractRequest implements DispatchRequest { + + /** + * Name of the attribute used to store the force-include option. + */ + public static final String FORCE_INCLUDE_ATTRIBUTE_NAME = AbstractRequest.class.getName() + ".FORCE_INCLUDE"; + + /** + * Sets the flag to force inclusion at next dispatch. + * + * @param forceInclude true means that, at the next dispatch, response + * will be included and never forwarded. + */ + protected void setForceInclude(boolean forceInclude) { + getContext(REQUEST_SCOPE).put(FORCE_INCLUDE_ATTRIBUTE_NAME, forceInclude); + } + + /** + * Checks if, when dispatching to a resource, the result must be included + * and not forwarded to. + * + * @return true if inclusion is forced. + */ + protected boolean isForceInclude() { + Boolean forceInclude = (Boolean) getContext(REQUEST_SCOPE).get(FORCE_INCLUDE_ATTRIBUTE_NAME); + if (forceInclude != null) { + return forceInclude; + } + return false; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractViewRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractViewRequest.java new file mode 100644 index 0000000000..9cd74cd744 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractViewRequest.java @@ -0,0 +1,60 @@ +/* + * 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.apache.tiles.request; + +import java.io.IOException; + +/** + * Base class for "view" requests, i.e. requests created into view technologies, + * such as JSP, Velocity and Freemarker. In particular, all calls to + * {@link #dispatch(String)} will cause an inclusion and never a forward. + */ +public class AbstractViewRequest extends DispatchRequestWrapper { + + /** + * Constructor. + * + * @param request The base request. + */ + public AbstractViewRequest(DispatchRequest request) { + super(request); + } + + @Override + public void dispatch(String path) throws IOException { + setForceInclude(true); + doInclude(path); + } + + @Override + public void include(String path) throws IOException { + setForceInclude(true); + doInclude(path); + } + + /** + * Includes the result. By default, uses the wrapped request for the inclusion. + * + * @param path The path whose result will be included. + * @throws IOException If something goes wrong. + */ + protected void doInclude(String path) throws IOException { + getWrappedRequest().include(path); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationAccess.java b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationAccess.java new file mode 100644 index 0000000000..35a1d29edd --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationAccess.java @@ -0,0 +1,47 @@ +/* + * 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.apache.tiles.request; + +/** + * Entry point to get information about the application. + */ +public final class ApplicationAccess { + + /** + * The attribute name that will be used to store the application context itself. + */ + public static final String APPLICATION_CONTEXT_ATTRIBUTE = ApplicationContext.class.getName() + ".ATTRIBUTE"; + + /** + * Constructor. + */ + private ApplicationAccess() { + } + + /** + * Registers an application context. It will be registered into itself as an + * attribute, using the {@link #APPLICATION_CONTEXT_ATTRIBUTE} name. + * + * @param applicationContext The application context to register. + */ + public static void register(ApplicationContext applicationContext) { + applicationContext.getApplicationScope().put(APPLICATION_CONTEXT_ATTRIBUTE, applicationContext); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContext.java b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContext.java new file mode 100644 index 0000000000..d45d907205 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContext.java @@ -0,0 +1,79 @@ +/* + * 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.apache.tiles.request; + +import java.util.Collection; +import java.util.Locale; +import java.util.Map; + +/** + * Defines a set of methods which tiles use to communicate to + * the tiles container and runtime environment. There is only + * one application context per container. + */ +public interface ApplicationContext { + + /** + * Returns the original, technology-dependent, context. + * + * @return The original application context. + */ + Object getContext(); + + /** + * Returns a mutable Map that maps application scope attribute names to + * their values. + * + * @return Map of key value pairs. + */ + Map getApplicationScope(); + + /** + * Return an immutable Map that maps context application initialization + * parameters to their values. + * + * @return initialization parameters + */ + Map getInitParams(); + + /** + * Return the application resource mapped to the specified path. + * + * @param localePath path to the desired resource, including the Locale suffix. + * @return the first located resource which matches the given path or null if no such resource exists. + */ + ApplicationResource getResource(String localePath); + + /** + * Return a localized version of an ApplicationResource. + * + * @param base the ApplicationResource. + * @param locale the desired Locale. + * @return the first located resource which matches the given path or null if no such resource exists. + */ + ApplicationResource getResource(ApplicationResource base, Locale locale); + + /** + * Return the application resources mapped to the specified path. + * + * @param path to the desired resource. + * @return all resources which match the given path. + */ + Collection getResources(String path); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContextAware.java b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContextAware.java new file mode 100644 index 0000000000..5775c72e95 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContextAware.java @@ -0,0 +1,34 @@ +/* + * 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.apache.tiles.request; + + +/** + * It represents an object that can have a reference to the + * {@link ApplicationContext}. + */ +public interface ApplicationContextAware { + + /** + * Sets the Tiles application context. + * + * @param applicationContext The Tiles application context. + */ + void setApplicationContext(ApplicationContext applicationContext); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationResource.java b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationResource.java new file mode 100644 index 0000000000..cf868e8886 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationResource.java @@ -0,0 +1,80 @@ +/* + * 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.apache.tiles.request; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; + +/** + * A (localized) resource accessible through the ApplicationContext. + * Typically, this is a file inside the web application's war. + */ +public interface ApplicationResource { + + /** + * Get the path name for this resource. + * You can access this resource by passing the path to + * {@link ApplicationContext#getResource(String) getResource}. + * + * @return the path including localization. + */ + String getLocalePath(); + + /** + * Get the path name for this resource. Multiple versions of + * a resource can share the same path if the locale part is different. + * + * @return the path excluding localization. + */ + String getPath(); + + /** + * Get the Locale for this resource. + * + * @return the Locale. + */ + Locale getLocale(); + + /** + * Get the path name of another version of the resource. + * + * @param locale the Locale for the new version. + * @return the path including localization. + */ + String getLocalePath(Locale locale); + + /** + * Get a java.io.InputStream to read the contents of this resource. + * + * @return the InputStream. + * @throws IOException if the contents cannot be read. + */ + InputStream getInputStream() throws IOException; + + /** + * Get the last modification date for this resource. + * + * @return the difference, measured in milliseconds, between the current + * time and midnight, January 1, 1970 UTC. + * @throws IOException if the last modification date cannot be found. + */ + long getLastModified() throws IOException; +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequest.java new file mode 100644 index 0000000000..30d208ca09 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequest.java @@ -0,0 +1,51 @@ +/* + * 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.apache.tiles.request; + +import java.io.IOException; + +/** + * Encapsulation of request information. + */ +public interface DispatchRequest extends Request { + + /** + * Dispatches the request to a specified path. + * + * @param path The path to dispatch to. + * @throws IOException If something goes wrong during dispatching. + */ + void dispatch(String path) throws IOException; + + /** + * Includes the response from the specified URL in the current response output. + * + * @param path The path to include. + * @throws IOException If something goes wrong during inclusion. + */ + void include(String path) throws IOException; + + /** + * Sets the content type when rendering the result. + * + * @param contentType The content type. It should follow the specifications + * from W3C about content types. + */ + void setContentType(String contentType); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequestWrapper.java b/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequestWrapper.java new file mode 100644 index 0000000000..cc2ca6a1e0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequestWrapper.java @@ -0,0 +1,139 @@ +/* + * 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.apache.tiles.request; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.tiles.request.attribute.Addable; + +/** + * Delegate for ease of customization. + */ +public class DispatchRequestWrapper extends AbstractRequest implements RequestWrapper { + + /** + * The wrapper request context object. + */ + private final DispatchRequest context; + + /** + * Constructor. + * + * @param context The request context to wrap. + */ + public DispatchRequestWrapper(DispatchRequest context) { + this.context = context; + } + + /** {@inheritDoc} */ + public DispatchRequest getWrappedRequest() { + return context; + } + + /** {@inheritDoc} */ + public Map getHeader() { + return context.getHeader(); + } + + /** {@inheritDoc} */ + public Map getHeaderValues() { + return context.getHeaderValues(); + } + + /** {@inheritDoc} */ + public Addable getResponseHeaders() { + return context.getResponseHeaders(); + } + + /** {@inheritDoc} */ + public Map getContext(String scope) { + return context.getContext(scope); + } + + /** {@inheritDoc} */ + public List getAvailableScopes() { + return context.getAvailableScopes(); + } + + /** {@inheritDoc} */ + public ApplicationContext getApplicationContext() { + return context.getApplicationContext(); + } + + /** {@inheritDoc} */ + public void dispatch(String path) throws IOException { + context.dispatch(path); + } + + /** {@inheritDoc} */ + public void include(String path) throws IOException { + context.include(path); + } + + /** {@inheritDoc} */ + public OutputStream getOutputStream() throws IOException { + return context.getOutputStream(); + } + + /** {@inheritDoc} */ + public Writer getWriter() throws IOException { + return context.getWriter(); + } + + /** {@inheritDoc} */ + public PrintWriter getPrintWriter() throws IOException { + return context.getPrintWriter(); + } + + /** {@inheritDoc} */ + public boolean isResponseCommitted() { + return context.isResponseCommitted(); + } + + /** {@inheritDoc} */ + public void setContentType(String contentType) { + context.setContentType(contentType); + } + + /** {@inheritDoc} */ + public Map getParam() { + return context.getParam(); + } + + /** {@inheritDoc} */ + public Map getParamValues() { + return context.getParamValues(); + } + + /** {@inheritDoc} */ + public Locale getRequestLocale() { + return context.getRequestLocale(); + } + + /** {@inheritDoc} */ + public boolean isUserInRole(String role) { + return context.isUserInRole(role); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/NotAvailableFeatureException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/NotAvailableFeatureException.java new file mode 100644 index 0000000000..ded24acd99 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/NotAvailableFeatureException.java @@ -0,0 +1,36 @@ +/* + * 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.apache.tiles.request; + +/** + * Exception that indicates that a feature could not be used since it is not available. + */ +public class NotAvailableFeatureException extends RequestException { + + /** + * Constructor. + * + * @param message The detail message. + * @param e The cause to be wrapped. + */ + public NotAvailableFeatureException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/Request.java b/plugins/tiles/src/main/java/org/apache/tiles/request/Request.java new file mode 100644 index 0000000000..9a1709f15a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/Request.java @@ -0,0 +1,161 @@ +/* + * 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.apache.tiles.request; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.tiles.request.attribute.Addable; + +/** + * Encapsulation of request information. + */ +public interface Request { + + /** the name of the (mandatory) "application" scope */ + String APPLICATION_SCOPE = "application"; + + /** the name of the "request" context */ + String REQUEST_SCOPE = "request"; + + /** + * Return an immutable Map that maps header names to the first (or only) + * header value (as a String). + * + * @return The header map. + */ + Map getHeader(); + + /** + * Return an immutable Map that maps header names to the set of all values + * specified in the request (as a String array). Header names must be + * matched in a case-insensitive manner. + * + * @return The header values map. + */ + Map getHeaderValues(); + + /** + * Return an Addable object that can be used to write headers to the response. + * + * @return An Addable object. + */ + Addable getResponseHeaders(); + + /** + * Returns a context map, given the scope name. + * This method always return a map for all the scope names returned by + * getAvailableScopes(). That map may be writable, or immutable, depending + * on the implementation. + * + * @param scope The name of the scope. + * @return The context. + */ + Map getContext(String scope); + + /** + * Returns all available scopes. + * The scopes are ordered according to their lifetime, + * the innermost, shorter lived scope appears first, + * and the outermost, longer lived scope appears last. + * Besides, the scopes "request" and "application" always included + * in the list. + * + * @return All the available scopes. + */ + List getAvailableScopes(); + + /** + * Returns the associated application context. + * + * @return The application context associated to this request. + */ + ApplicationContext getApplicationContext(); + + /** + * Returns an output stream to be used to write directly in the response. + * + * @return The output stream that writes in the response. + * @throws IOException If something goes wrong when getting the output stream. + */ + OutputStream getOutputStream() throws IOException; + + /** + * Returns a writer to be used to write directly in the response. + * + * @return The writer that writes in the response. + * @throws IOException If something goes wrong when getting the writer. + */ + Writer getWriter() throws IOException; + + /** + * Returns a print writer to be used to write directly in the response. + * + * @return The print writer that writes in the response. + * @throws IOException If something goes wrong when getting the print + * writer. + */ + PrintWriter getPrintWriter() throws IOException; + + /** + * Checks if the response has been committed. + * + * @return true only if the response has been committed. + */ + boolean isResponseCommitted(); + + /** + * Return an immutable Map that maps request parameter names to the first + * (or only) value (as a String). + * + * @return The parameter map. + */ + Map getParam(); + + /** + * Return an immutable Map that maps request parameter names to the set of + * all values (as a String array). + * + * @return The parameter values map. + */ + Map getParamValues(); + + /** + * Return the preferred Locale in which the client will accept content. + * + * @return The current request locale. It is the locale of the request + * object itself, and it is NOT the locale that the user wants to use. See + * {@link org.apache.tiles.core.locale.LocaleResolver} to implement strategies to + * resolve locales. + */ + Locale getRequestLocale(); + + /** + * Determine whether the specified user is in the given role. + * @param role the role to check against. + * @return true if the user is in the given role. + */ + boolean isUserInRole(String role); + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/RequestException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/RequestException.java new file mode 100644 index 0000000000..dcd8daeaea --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/RequestException.java @@ -0,0 +1,45 @@ +/* + * 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.apache.tiles.request; + +/** + * Thrown when something related to a request fails. + */ +public class RequestException extends RuntimeException { + + /** + * Constructor. + * + * @param message The message of the exception. + */ + public RequestException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param message The message of the exception. + * @param cause The cause. + */ + public RequestException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/RequestWrapper.java b/plugins/tiles/src/main/java/org/apache/tiles/request/RequestWrapper.java new file mode 100644 index 0000000000..a9826d3694 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/RequestWrapper.java @@ -0,0 +1,33 @@ +/* + * 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.apache.tiles.request; + +/** + * Delegate for ease of customization. + */ +public interface RequestWrapper extends Request { + + /** + * Returns the wrapped Tiles request. + * + * @return The wrapped Tiles request. + */ + Request getWrappedRequest(); + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/Addable.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/Addable.java new file mode 100644 index 0000000000..0a6178a56c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/Addable.java @@ -0,0 +1,35 @@ +/* + * 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.apache.tiles.request.attribute; + +/** + * Allows to get and set attributes. + * + * @param The type of the value of the attribute. + */ +public interface Addable { + + /** + * Sets a value for the given key. + * + * @param key The key of the attribute. + * @param value The value of the attribute. + */ + void setValue(String key, V value); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/AttributeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/AttributeExtractor.java new file mode 100644 index 0000000000..b855123f7e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/AttributeExtractor.java @@ -0,0 +1,25 @@ +/* + * 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.apache.tiles.request.attribute; + +/** + * Allows to get, put and remove Object-type attributes. + */ +public interface AttributeExtractor extends HasRemovableKeys, HasAddableKeys { +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/EnumeratedValuesExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/EnumeratedValuesExtractor.java new file mode 100644 index 0000000000..13240b0446 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/EnumeratedValuesExtractor.java @@ -0,0 +1,35 @@ +/* + * 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.apache.tiles.request.attribute; + +import java.util.Enumeration; + +/** + * Allows to get values from multi-valued attributes. + */ +public interface EnumeratedValuesExtractor extends HasAddableKeys { + + /** + * Returns the values stored at the given key. + * + * @param key The key of the attribute. + * @return The values of the attribute. + */ + Enumeration getValues(String key); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasAddableKeys.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasAddableKeys.java new file mode 100644 index 0000000000..1bff1f2c5b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasAddableKeys.java @@ -0,0 +1,27 @@ +/* + * 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.apache.tiles.request.attribute; + +/** + * Allows to get and set attributes. + * + * @param The type of the value of the attribute. + */ +public interface HasAddableKeys extends HasKeys, Addable { +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasKeys.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasKeys.java new file mode 100644 index 0000000000..692cf61cb3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasKeys.java @@ -0,0 +1,44 @@ +/* + * 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.apache.tiles.request.attribute; + +import java.util.Enumeration; + +/** + * Allows to get attributes. + * + * @param The type of the value of the attribute. + */ +public interface HasKeys { + + /** + * The enumeration of the keys of the stored attributes. + * + * @return The keys. + */ + Enumeration getKeys(); + + /** + * Returns the value of the attribute with the given key. + * + * @param key The key of the attribute. + * @return The value. + */ + V getValue(String key); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasRemovableKeys.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasRemovableKeys.java new file mode 100644 index 0000000000..4cb31e3174 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasRemovableKeys.java @@ -0,0 +1,34 @@ +/* + * 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.apache.tiles.request.attribute; + +/** + * Allows to get and remove attributes. + * + * @param The type of the value of the attribute. + */ +public interface HasRemovableKeys extends HasKeys { + + /** + * Removes an attribute. + * + * @param key The key of the attribute to remove. + */ + void removeValue(String key); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/package-info.java new file mode 100644 index 0000000000..054b0e4f9d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/package-info.java @@ -0,0 +1,26 @@ +/* + * 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. + */ +/** + * Methods to get, set and remove attributes from different sources (like HTTP requests + * or sessions). + * By implementing {@link org.apache.tiles.request.attribute.AttributeExtractor}, + * you can use a Map from {@link org.apache.tiles.request.collection} to manipulate the + * attributes of another class. + */ +package org.apache.tiles.request.attribute; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/AddableParameterMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/AddableParameterMap.java new file mode 100644 index 0000000000..d88b90503e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/AddableParameterMap.java @@ -0,0 +1,95 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasAddableKeys; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +/** + * Exposes an {@link HasAddableKeys} object as a put/get (no remove) map. + */ +public class AddableParameterMap extends ReadOnlyEnumerationMap { + + /** + * The request. + */ + private final HasAddableKeys request; + + /** + * Constructor. + * + * @param request The request object to use. + */ + public AddableParameterMap(HasAddableKeys request) { + super(request); + this.request = request; + } + + /** + * {@inheritDoc} + */ + public Set> entrySet() { + return new AddableParameterEntrySet(); + } + + /** + * {@inheritDoc} + */ + public String put(String key, String value) { + String oldValue = request.getValue(key); + request.setValue(key, value); + return oldValue; + } + + + /** + * {@inheritDoc} + */ + public void putAll(Map map) { + for (Entry entry : map + .entrySet()) { + request.setValue(entry.getKey(), entry.getValue()); + } + } + + + /** + * Entry set implementation for {@link AddableParameterMap}. + */ + private class AddableParameterEntrySet extends ReadOnlyEnumerationMap.ReadOnlyEnumerationMapEntrySet { + + @Override + public boolean add(Entry e) { + request.setValue(e.getKey(), e.getValue()); + return true; + } + + @Override + public boolean addAll( + Collection> c) { + for (Entry entry : c) { + request.setValue(entry.getKey(), entry.getValue()); + } + return true; + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/CollectionUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/CollectionUtil.java new file mode 100644 index 0000000000..54cc254a60 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/CollectionUtil.java @@ -0,0 +1,66 @@ +/* + * 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.apache.tiles.request.collection; + +import java.util.Enumeration; + +/** + * Utilities for requests. + */ +public final class CollectionUtil { + + /** + * Constructor. + */ + private CollectionUtil() { + + } + + /** + * Returns the string representation of the key. + * + * @param key The key. + * @return The string representation of the key. + * @throws IllegalArgumentException If the key is null. + */ + public static String key(Object key) { + if (key == null) { + throw new IllegalArgumentException(); + } else if (key instanceof String) { + return ((String) key); + } else { + return (key.toString()); + } + } + + /** + * Returns the number of elements in an enumeration, by iterating it. + * + * @param keys The enumeration. + * @return The number of elements. + */ + public static int enumerationSize(Enumeration keys) { + int n = 0; + while (keys.hasMoreElements()) { + keys.nextElement(); + n++; + } + return n; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/HeaderValuesMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/HeaderValuesMap.java new file mode 100644 index 0000000000..fa50dbab90 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/HeaderValuesMap.java @@ -0,0 +1,556 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import static org.apache.tiles.request.collection.CollectionUtil.enumerationSize; +import static org.apache.tiles.request.collection.CollectionUtil.key; + +/** + * Exposes an {@link EnumeratedValuesExtractor} object as a read-only map. + */ +public class HeaderValuesMap implements Map { + + /** + * The request. + */ + private final EnumeratedValuesExtractor request; + + /** + * Constructor. + * + * @param request The request object to use. + */ + public HeaderValuesMap(EnumeratedValuesExtractor request) { + this.request = request; + } + + + /** + * {@inheritDoc} + */ + public void clear() { + throw new UnsupportedOperationException(); + } + + + /** + * {@inheritDoc} + */ + public boolean containsKey(Object key) { + return (request.getValue(key(key)) != null); + } + + + /** + * {@inheritDoc} + */ + public boolean containsValue(Object value) { + if (!(value instanceof String[])) { + return (false); + } + String[] test = (String[]) value; + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + String name = names.nextElement(); + if (compareHeaders(name, array2set(test))) { + return true; + } + } + return false; + } + + + /** + * {@inheritDoc} + */ + public Set> entrySet() { + return new HeadersEntrySet(); + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof HeaderValuesMap)) { + return false; + } + EnumeratedValuesExtractor otherRequest = ((HeaderValuesMap) obj).request; + boolean retValue = true; + for (Enumeration attribs = request.getKeys(); attribs.hasMoreElements() && retValue; ) { + String parameterName = attribs.nextElement(); + Set valueSet = enumeration2set(otherRequest.getValues(parameterName)); + retValue = compareHeaders(parameterName, valueSet); + } + + return retValue; + } + + + /** + * {@inheritDoc} + */ + public String[] get(Object key) { + return getHeaderValues(key(key)); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + int retValue = 0; + for (Enumeration attribs = request.getKeys(); attribs + .hasMoreElements(); ) { + String parameterName = attribs.nextElement(); + Enumeration values = request.getValues(parameterName); + int valueHash = 0; + while (values.hasMoreElements()) { + valueHash += values.nextElement().hashCode(); + } + retValue += parameterName.hashCode() ^ valueHash; + } + return retValue; + } + + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return !request.getKeys().hasMoreElements(); + } + + + /** + * {@inheritDoc} + */ + public Set keySet() { + return new KeySet(request); + } + + + /** + * {@inheritDoc} + */ + public String[] put(String key, String[] value) { + throw new UnsupportedOperationException(); + } + + + /** + * {@inheritDoc} + */ + public void putAll(Map map) { + throw new UnsupportedOperationException(); + } + + + /** + * {@inheritDoc} + */ + public String[] remove(Object key) { + throw new UnsupportedOperationException(); + } + + + /** + * {@inheritDoc} + */ + public int size() { + return enumerationSize(request.getKeys()); + } + + + /** + * {@inheritDoc} + */ + public Collection values() { + return new HeaderValuesCollection(); + } + + /** + * Extracts values enumeration of an attribute and returns the corresponding array of values. + * + * @param key The key of the attribute. + * @return The values of the attribute. + */ + private String[] getHeaderValues(String key) { + List list = new ArrayList<>(); + Enumeration values = request.getValues(key); + while (values.hasMoreElements()) { + list.add(values.nextElement()); + } + return list.toArray(new String[0]); + } + + /** + * Converts the content of a string enumeration to an array of strings. + * + * @param enumeration The enumeration to convert. + * @return The corresponding array. + */ + private Set enumeration2set(Enumeration enumeration) { + Set retValue = new HashSet<>(); + while (enumeration.hasMoreElements()) { + retValue.add(enumeration.nextElement()); + } + return retValue; + } + + /** + * Transforms a string array in a string set. + * + * @param valueArray The array to convert. + * @return The corresponding set. + */ + private Set array2set(String[] valueArray) { + Set values = new HashSet<>(); + Collections.addAll(values, valueArray); + return values; + } + + /** + * Checks if values of a header attribute are the same as the one passed in + * the set. + * + * @param name The name of the header. + * @param testSet The set of values it must contain. + * @return true if all the values, and only them, are present + * in the header values. + */ + private boolean compareHeaders(String name, Set testSet) { + Enumeration values = request.getValues(name); + boolean matched = true; + while (values.hasMoreElements() && matched) { + String currentValue = values.nextElement(); + matched = testSet.remove(currentValue); + } + matched = matched && testSet.isEmpty(); + return matched; + } + + /** + * Entry set implementation for {@link HeaderValuesMap}. + */ + private class HeadersEntrySet implements Set> { + + @Override + public boolean add(Entry e) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll( + Collection> c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean contains(Object o) { + return containsEntry((Entry) o); + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsAll(Collection c) { + Collection> realCollection = + (Collection>) c; + for (Entry entry : realCollection) { + if (!containsEntry(entry)) { + return false; + } + } + return true; + } + + @Override + public boolean isEmpty() { + return HeaderValuesMap.this.isEmpty(); + } + + @Override + public Iterator> iterator() { + return new HeadersEntrySetIterator(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return HeaderValuesMap.this.size(); + } + + @Override + public Object[] toArray() { + return toList().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Checks whether the given entry is present in the headers. + * + * @param entry The entry to check. + * @return if the key and the values of the entry are present. + */ + private boolean containsEntry(Entry entry) { + Enumeration entryValues = request.getValues(key(entry.getKey())); + String[] valueArray = entry.getValue(); + Set values = array2set(valueArray); + while (entryValues.hasMoreElements()) { + if (!values.remove(entryValues.nextElement())) { + return false; + } + } + return values.isEmpty(); + } + + /** + * Turns this entry set into a list. + * + * @return The collection, turned into a list. + */ + private List> toList() { + List> entries = new ArrayList<>(); + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + entries.add(extractNextEntry(names)); + } + return entries; + } + + /** + * Returns the next entry, by getting the next element in the given enumeration. + * + * @param names The enumeration to get the next name from.. + * @return The next map entry. + */ + private MapEntry extractNextEntry(Enumeration names) { + String name = names.nextElement(); + return new MapEntryArrayValues<>(name, getHeaderValues(name), false); + } + + /** + * Iterates {@link HeadersEntrySet} elements. + */ + private class HeadersEntrySetIterator implements Iterator> { + + /** + * The enumeration to use. + */ + private final Enumeration namesEnumeration = request.getKeys(); + + @Override + public boolean hasNext() { + return namesEnumeration.hasMoreElements(); + } + + @Override + public Entry next() { + if (namesEnumeration.hasMoreElements()) { + return extractNextEntry(namesEnumeration); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } + } + + /** + * It is a collection of all values of the header. Each element is an array + * of values of a single header. + */ + private class HeaderValuesCollection implements Collection { + + @Override + public boolean add(String[] e) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean contains(Object o) { + return containsValue(o); + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsAll(Collection c) { + Collection realCollection = (Collection) c; + for (String[] value : realCollection) { + if (!containsValue(value)) { + return false; + } + } + return true; + } + + @Override + public boolean isEmpty() { + return HeaderValuesMap.this.isEmpty(); + } + + @Override + public Iterator iterator() { + return new HeaderValuesCollectionIterator(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return HeaderValuesMap.this.size(); + } + + @Override + public Object[] toArray() { + return toList().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Turns this collection into a list. + * + * @return The list. + */ + private List toList() { + List entries = new ArrayList<>(); + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + entries.add(enumeration2array(request.getValues(names.nextElement()))); + } + return entries; + } + + /** + * Converts the content of a string enumeration to an array of strings. + * + * @param enumeration The enumeration to convert. + * @return The corresponding array. + */ + private String[] enumeration2array(Enumeration enumeration) { + List list1 = new ArrayList<>(); + while (enumeration.hasMoreElements()) { + list1.add(enumeration.nextElement()); + } + + return list1.toArray(new String[0]); + } + + /** + * Iterates elements of {@link HeaderValuesCollection}. + */ + private class HeaderValuesCollectionIterator implements Iterator { + + /** + * The enumeration of the name of header attributes. + */ + private final Enumeration namesEnumeration = request.getKeys(); + + @Override + public boolean hasNext() { + return namesEnumeration.hasMoreElements(); + } + + @Override + public String[] next() { + if (namesEnumeration.hasMoreElements()) { + return enumeration2array(request.getValues(namesEnumeration.nextElement())); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/KeySet.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/KeySet.java new file mode 100644 index 0000000000..f346880888 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/KeySet.java @@ -0,0 +1,167 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; + +import static org.apache.tiles.request.collection.CollectionUtil.enumerationSize; +import static org.apache.tiles.request.collection.CollectionUtil.key; + +/** + * Exposes keys of a {@link HasKeys} object as a set. + */ +public class KeySet implements Set { + + /** + * The request to read. + */ + private final HasKeys request; + + /** + * Constructor. + * + * @param request The request to read. + */ + public KeySet(HasKeys request) { + this.request = request; + } + + @Override + public boolean add(String e) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean contains(Object o) { + return request.getValue(key(o)) != null; + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsAll(Collection c) { + Collection realCollection = (Collection) c; + for (String key : realCollection) { + if (request.getValue(key(key)) == null) { + return false; + } + } + return true; + } + + @Override + public boolean isEmpty() { + return !request.getKeys().hasMoreElements(); + } + + @Override + public Iterator iterator() { + return new KeySetIterator(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return enumerationSize(request.getKeys()); + } + + @Override + public Object[] toArray() { + return toList().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Turns this set into a list. + * + * @return The corresponding list. + */ + private List toList() { + List entries = new ArrayList(); + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + entries.add(names.nextElement()); + } + return entries; + } + + /** + * Iterates elements of {@link KeySet}. + */ + private class KeySetIterator implements Iterator { + + /** + * The key names enumeration. + */ + private final Enumeration namesEnumeration = request.getKeys(); + + @Override + public boolean hasNext() { + return namesEnumeration.hasMoreElements(); + } + + @Override + public String next() { + if (namesEnumeration.hasMoreElements()) { + return namesEnumeration.nextElement(); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntry.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntry.java new file mode 100644 index 0000000000..58e590816b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntry.java @@ -0,0 +1,124 @@ +/* + * 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.apache.tiles.request.collection; + +import java.util.Map; + +/** + *

Map.Entry implementation that can be constructed to either be read-only + * or not.

+ * + * @param The key type. + * @param The value type. + */ + +public class MapEntry implements Map.Entry { + + /** + *

The entry key.

+ */ + private final K key; + + /** + *

The entry value.

+ */ + private V value; + + /** + *

Whether the entry can be modified.

+ */ + private final boolean modifiable; + + /** + *

Creates a map entry that can either allow modifications or not.

+ * + * @param key The entry key + * @param value The entry value + * @param modifiable Whether the entry should allow modification or not + */ + public MapEntry(K key, V value, boolean modifiable) { + this.key = key; + this.value = value; + this.modifiable = modifiable; + } + + /** + *

Gets the entry key.

+ * + * @return The entry key + */ + public K getKey() { + return key; + } + + /** + *

Gets the entry value.

+ * + * @return The entry key + */ + public V getValue() { + return value; + } + + /** + *

Sets the entry value if the entry can be modified.

+ * + * @param val The new value + * @return The old entry value + * @throws UnsupportedOperationException If the entry cannot be modified + */ + public V setValue(V val) { + if (modifiable) { + V oldVal = this.value; + this.value = val; + return oldVal; + } + throw new UnsupportedOperationException("The map entry is not modifiable"); + } + + /** + *

Determines if this entry is equal to the passed object.

+ * + * @param o The object to test + * @return True if equal, else false + */ + @Override + @SuppressWarnings("unchecked") + public boolean equals(Object o) { + if (o instanceof Map.Entry) { + Map.Entry entry = (Map.Entry) o; + return (this.getKey() == null ? entry.getKey() == null : this + .getKey().equals(entry.getKey())) + && (this.getValue() == null ? entry.getValue() == null + : this.getValue().equals(entry.getValue())); + } + return false; + } + + /** + *

Returns the hashcode for this entry.

+ * + * @return The and'ed hashcode of the key and value + */ + @Override + public int hashCode() { + return (this.getKey() == null ? 0 : this.getKey().hashCode()) + ^ (this.getValue() == null ? 0 : this.getValue().hashCode()); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntryArrayValues.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntryArrayValues.java new file mode 100644 index 0000000000..c9aff7fd37 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntryArrayValues.java @@ -0,0 +1,95 @@ +/* + * 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.apache.tiles.request.collection; + +import java.util.Map; +import java.util.Objects; + +/** + * Multi-valued map entry. + * + * @param The key type. + * @param The value type. + */ +public class MapEntryArrayValues extends MapEntry { + + /** + * Constructor. + * + * @param key The key of the entry. + * @param value The array of values. + * @param modifiable If true the entry is modifiable. + */ + public MapEntryArrayValues(K key, V[] value, boolean modifiable) { + super(key, value, modifiable); + } + + /** + *

Returns the hashcode for this entry.

+ * + * @return The and'ed hashcode of the key and value + */ + @Override + public int hashCode() { + int valueHash = 0; + V[] value = getValue(); + if (value != null) { + for (V v : value) { + valueHash += v.hashCode(); + } + } + + return (this.getKey() == null ? 0 : this.getKey().hashCode()) ^ valueHash; + } + + /** + *

Determines if this entry is equal to the passed object.

+ * + * @param o The object to test + * @return True if equal, else false + */ + @Override + @SuppressWarnings("unchecked") + public boolean equals(Object o) { + if (o instanceof Map.Entry) { + Map.Entry entry = (Map.Entry) o; + if (this.getKey() == null ? entry.getKey() == null : this + .getKey().equals(entry.getKey())) { + V[] values = getValue(); + V[] otherValues = entry.getValue(); + if (values != null) { + if (otherValues != null) { + if (values.length == otherValues.length) { + boolean same = true; + for (int i = 0; i < values.length && same; i++) { + same = Objects.equals(values[i], otherValues[i]); + } + return same; + } + } else { + return false; + } + } else { + return otherValues == null; + } + } + } + return false; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java new file mode 100644 index 0000000000..d5cc16978c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java @@ -0,0 +1,461 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import static org.apache.tiles.request.collection.CollectionUtil.enumerationSize; +import static org.apache.tiles.request.collection.CollectionUtil.key; + +/** + * Wraps an {@link HasKeys} object into a read-only map. + * + * @param The type of the values. + */ +public class ReadOnlyEnumerationMap implements Map { + + /** + * The request. + */ + protected HasKeys request; + + /** + * Constructor. + * + * @param request The request object to use. + */ + public ReadOnlyEnumerationMap(HasKeys request) { + this.request = request; + } + + /** + * {@inheritDoc} + */ + public void clear() { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public boolean containsKey(Object key) { + return (request.getValue(key(key)) != null); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public boolean containsValue(Object value) { + V realValue = (V) value; + for (Enumeration keysIt = request.getKeys(); keysIt.hasMoreElements(); ) { + if (realValue.equals(request.getValue(keysIt.nextElement()))) { + return true; + } + } + return false; + } + + /** + * {@inheritDoc} + */ + public Set> entrySet() { + return new ReadOnlyEnumerationMapEntrySet(); + } + + /** + * {@inheritDoc} + */ + public V get(Object key) { + return (request.getValue(key(key))); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return !request.getKeys().hasMoreElements(); + } + + /** + * {@inheritDoc} + */ + public Set keySet() { + return new KeySet(request); + } + + /** + * {@inheritDoc} + */ + public V put(String key, V value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void putAll(Map map) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public V remove(Object key) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public int size() { + return enumerationSize(request.getKeys()); + } + + /** + * {@inheritDoc} + */ + public Collection values() { + return new ReadOnlyEnumerationMapValuesCollection(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof ReadOnlyEnumerationMap)) { + return false; + } + @SuppressWarnings("unchecked") + HasKeys otherRequest = ((ReadOnlyEnumerationMap) obj).request; + boolean retValue = true; + Set otherKeys; + otherKeys = new HashSet<>(); + for (Enumeration attribs = otherRequest.getKeys(); attribs.hasMoreElements(); ) { + otherKeys.add(attribs.nextElement()); + } + for (Enumeration attribs = request.getKeys(); attribs.hasMoreElements() && retValue; ) { + String parameterName = attribs.nextElement(); + retValue = request.getValue(parameterName).equals(otherRequest.getValue(parameterName)); + otherKeys.remove(parameterName); + } + + return retValue && otherKeys.isEmpty(); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + int retValue = 0; + for (Enumeration attribs = request.getKeys(); attribs + .hasMoreElements(); ) { + String parameterName = attribs.nextElement(); + V value = request.getValue(parameterName); + retValue += parameterName.hashCode() ^ (value == null ? 0 : value.hashCode()); + } + return retValue; + } + + /** + * Entry set implementation for {@link ReadOnlyEnumerationMap}. + */ + class ReadOnlyEnumerationMapEntrySet implements Set> { + + @Override + public boolean add(Entry e) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll( + Collection> c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean contains(Object o) { + return containsEntry((Entry) o); + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsAll(Collection c) { + Collection> realCollection = + (Collection>) c; + for (Entry entry : realCollection) { + if (!containsEntry(entry)) { + return false; + } + } + return true; + } + + @Override + public boolean isEmpty() { + return ReadOnlyEnumerationMap.this.isEmpty(); + } + + @Override + public Iterator> iterator() { + return new ReadOnlyEnumerationMapEntrySetIterator(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return ReadOnlyEnumerationMap.this.size(); + } + + @Override + public Object[] toArray() { + return toList().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Checks whether the entry is present. + * + * @param entry The entry to check. + * @return true if the entry is present. + */ + protected boolean containsEntry(Entry entry) { + V storedValue = request.getValue(key(entry.getKey())); + return storedValue != null && storedValue.equals(entry.getValue()); + } + + /** + * Turns this set into a list. + * + * @return The list. + */ + private List> toList() { + List> entries = new ArrayList<>(); + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + entries.add(extractNextEntry(names)); + } + return entries; + } + + /** + * Returns the next entry, given the enumeration. + * + * @param names The enumeration to get the next key from. + * @return The next entry. + */ + private MapEntry extractNextEntry( + Enumeration names) { + String name = names.nextElement(); + return new MapEntry<>(name, request.getValue(name), false); + } + + /** + * Iterates entries of {@link ReadOnlyEnumerationMap}. + */ + private class ReadOnlyEnumerationMapEntrySetIterator implements Iterator> { + + /** + * Enumerates keys. + */ + private final Enumeration namesEnumeration = request.getKeys(); + + @Override + public boolean hasNext() { + return namesEnumeration.hasMoreElements(); + } + + @Override + public Entry next() { + if (namesEnumeration.hasMoreElements()) { + return extractNextEntry(namesEnumeration); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } + } + + /** + * Values collection for {@link ReadOnlyEnumerationMap}. + */ + private class ReadOnlyEnumerationMapValuesCollection implements Collection { + + @Override + public boolean add(V e) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean contains(Object o) { + return containsValue(o); + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsAll(Collection c) { + Collection realCollection = (Collection) c; + List valueList = new ArrayList<>(realCollection); + for (Enumeration keysEnum = request.getKeys(); keysEnum.hasMoreElements(); ) { + valueList.remove(request.getValue(keysEnum.nextElement())); + if (valueList.isEmpty()) { + return true; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return ReadOnlyEnumerationMap.this.isEmpty(); + } + + @Override + public Iterator iterator() { + return new ReadOnlyEnumerationMapValuesCollectionIterator(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return ReadOnlyEnumerationMap.this.size(); + } + + @Override + public Object[] toArray() { + return toList().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Turns this collection into a list. + * + * @return The list. + */ + private List toList() { + List entries = new ArrayList<>(); + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + entries.add(request.getValue(names.nextElement())); + } + return entries; + } + + /** + * Iterates values of {@link ReadOnlyEnumerationMap}. + */ + private class ReadOnlyEnumerationMapValuesCollectionIterator implements Iterator { + + /** + * Enumerates attribute keys. + */ + private final Enumeration namesEnumeration = request.getKeys(); + + @Override + public boolean hasNext() { + return namesEnumeration.hasMoreElements(); + } + + @Override + public V next() { + if (namesEnumeration.hasMoreElements()) { + return request.getValue(namesEnumeration.nextElement()); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/RemovableKeySet.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/RemovableKeySet.java new file mode 100644 index 0000000000..1ce23f66b3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/RemovableKeySet.java @@ -0,0 +1,91 @@ +/* + * 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.apache.tiles.request.collection; + +import static org.apache.tiles.request.collection.CollectionUtil.*; + +import java.util.Collection; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.apache.tiles.request.attribute.HasRemovableKeys; + +/** + * Wraps {@link HasRemovableKeys} keys as a set. + */ +public class RemovableKeySet extends KeySet { + + /** + * The request. + */ + private final HasRemovableKeys request; + + /** + * Constructor. + * + * @param request The request. + */ + public RemovableKeySet(HasRemovableKeys request) { + super(request); + this.request = request; + } + + @Override + public boolean remove(Object o) { + String strKey = key(o); + Object previous = request.getValue(strKey); + if (previous != null) { + request.removeValue(strKey); + return true; + } + return false; + } + + @SuppressWarnings("unchecked") + @Override + public boolean removeAll(Collection c) { + Collection realCollection = (Collection) c; + boolean retValue = false; + for (String entry : realCollection) { + retValue |= remove(entry); + } + return retValue; + } + + @SuppressWarnings("unchecked") + @Override + public boolean retainAll(Collection c) { + Collection realCollection = (Collection) c; + boolean retValue = false; + Set keysToRemove = new LinkedHashSet<>(); + for (Enumeration keys = request.getKeys(); keys.hasMoreElements();) { + String key = keys.nextElement(); + if (!realCollection.contains(key)) { + retValue = true; + keysToRemove.add(key); + } + } + for (String key : keysToRemove) { + request.removeValue(key); + } + return retValue; + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ScopeMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ScopeMap.java new file mode 100644 index 0000000000..a03ec1f3b0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ScopeMap.java @@ -0,0 +1,169 @@ +/* + * 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.apache.tiles.request.collection; + +import static org.apache.tiles.request.collection.CollectionUtil.*; + +import java.util.Collection; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +/** + * Exposes a scope context as a map. + */ +public class ScopeMap extends ReadOnlyEnumerationMap { + + /** + * The context to read. + */ + private final AttributeExtractor context; + + /** + * Constructor. + * + * @param context The servlet context to use. + */ + public ScopeMap(AttributeExtractor context) { + super(context); + this.context = context; + } + + /** {@inheritDoc} */ + public void clear() { + Enumeration keys = context.getKeys(); + while (keys.hasMoreElements()) { + context.removeValue(keys.nextElement()); + } + } + + /** {@inheritDoc} */ + public Set> entrySet() { + return new ScopeEntrySet(); + } + + /** {@inheritDoc} */ + public Set keySet() { + return new RemovableKeySet(context); + } + + /** {@inheritDoc} */ + public Object put(String key, Object value) { + String strKey = key(key); + Object previous = context.getValue(strKey); + context.setValue(strKey, value); + return previous; + } + + /** {@inheritDoc} */ + public void putAll(Map map) { + for (String key : map.keySet()) { + context.setValue(key, map.get(key)); + } + } + + /** {@inheritDoc} */ + public Object remove(Object key) { + String strKey = key(key); + Object previous = context.getValue(strKey); + context.removeValue(strKey); + return (previous); + } + + /** + * Entry set implementation for {@link ScopeMap}. + */ + private class ScopeEntrySet extends ReadOnlyEnumerationMap.ReadOnlyEnumerationMapEntrySet { + + @Override + public boolean add(Map.Entry e) { + String key = e.getKey(); + Object value = e.getValue(); + Object oldValue = get(key); + if (oldValue == null || !oldValue.equals(value)) { + context.setValue(key, value); + return true; + } + return false; + } + + @Override + public boolean addAll( + Collection> c) { + boolean retValue = false; + for (Map.Entry entry : c) { + retValue |= add(entry); + } + return retValue; + } + + @Override + public void clear() { + ScopeMap.this.clear(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean remove(Object o) { + Map.Entry entry = (Map.Entry) o; + String key = entry.getKey(); + Object currentValue = context.getValue(key); + if (currentValue != null && currentValue.equals(entry.getValue())) { + context.removeValue(key); + return true; + } + return false; + } + + @SuppressWarnings("unchecked") + @Override + public boolean removeAll(Collection c) { + Collection> realCollection = (Collection>) c; + boolean retValue = false; + for (Map.Entry entry : realCollection) { + retValue |= remove(entry); + } + return retValue; + } + + @SuppressWarnings("unchecked") + @Override + public boolean retainAll(Collection c) { + Collection> realCollection = (Collection>) c; + boolean retValue = false; + Set keysToRemove = new LinkedHashSet<>(); + for (Enumeration keys = context.getKeys(); keys.hasMoreElements();) { + String key = keys.nextElement(); + Object value = context.getValue(key); + Map.Entry entry = new MapEntry<>(key, value, false); + if (!realCollection.contains(entry)) { + retValue = true; + keysToRemove.add(key); + } + } + for (String key : keysToRemove) { + context.removeValue(key); + } + return retValue; + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/package-info.java new file mode 100644 index 0000000000..e236964a8c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/package-info.java @@ -0,0 +1,34 @@ +/* + * 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. + */ +/** + * Special collections and maps for attributes (like HTTP request + * or session attributes). + * These can be used to access another object's attributes through + * a Map interface. + *
    + *
  • {@link org.apache.tiles.request.collection.ScopeMap} provides + * full get/put/remove access to the attributes. + *
  • {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap} + * provides get-only access. + *
  • {@link org.apache.tiles.request.collection.HeaderValuesMap} + * provides get-only access to a multi-valued map (typically, headers). + *
+ */ +package org.apache.tiles.request.collection; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/EnvironmentScopeMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/EnvironmentScopeMap.java new file mode 100644 index 0000000000..e55c38582f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/EnvironmentScopeMap.java @@ -0,0 +1,58 @@ +/* + * 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.apache.tiles.request.freemarker; + +import freemarker.core.Environment; +import freemarker.template.TemplateModelException; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.freemarker.extractor.EnvironmentScopeExtractor; + +import java.util.Set; + +/** + * Private implementation of Map for servlet request attributes. + */ +final class EnvironmentScopeMap extends ScopeMap { + + /** + * The request object to use. + */ + private final Environment request; + + /** + * Constructor. + * + * @param request The request object to use. + */ + public EnvironmentScopeMap(Environment request) { + super(new EnvironmentScopeExtractor(request)); + this.request = request; + } + + @SuppressWarnings("unchecked") + @Override + public Set keySet() { + try { + return request.getKnownVariableNames(); + } catch (TemplateModelException e) { + throw new FreemarkerRequestException( + "Cannot get known variable names", e); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequest.java new file mode 100644 index 0000000000..cd82fccb01 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequest.java @@ -0,0 +1,143 @@ +/* + * 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.apache.tiles.request.freemarker; + +import freemarker.core.Environment; +import freemarker.ext.servlet.HttpRequestHashModel; +import org.apache.tiles.request.AbstractViewRequest; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.DispatchRequest; +import org.apache.tiles.request.servlet.ServletRequest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * The FreeMarker-specific request context. + */ +public class FreemarkerRequest extends AbstractViewRequest { + + /** + * The natively available scopes. In fact, only "page". + */ + private final List scopes; + + /** + * The FreeMarker current environment. + */ + private final Environment env; + + /** + * The page scope map. + */ + private Map pageScope; + + /** + * Creates a new Freemarker request. + * + * @param applicationContext The application context. + * @param env The Freemarker environment object. + * @return A new request. + */ + public static FreemarkerRequest createServletFreemarkerRequest(ApplicationContext applicationContext, Environment env) { + HttpRequestHashModel requestModel = FreemarkerRequestUtil.getRequestHashModel(env); + HttpServletRequest request = requestModel.getRequest(); + HttpServletResponse response = requestModel.getResponse(); + DispatchRequest enclosedRequest = new ServletRequest(applicationContext, request, response); + return new FreemarkerRequest(enclosedRequest, env); + } + + /** + * Constructor. + * + * @param enclosedRequest + * The request that exposes non-FreeMarker specific properties + * @param env + * The FreeMarker environment. + */ + public FreemarkerRequest(DispatchRequest enclosedRequest, Environment env) { + super(enclosedRequest); + List scopes = new ArrayList<>(enclosedRequest.getAvailableScopes()); + scopes.add("page"); + this.scopes = Collections.unmodifiableList(scopes); + this.env = env; + } + + /** + * Returns the environment object. + * + * @return The environment. + */ + public Environment getEnvironment() { + return env; + } + + /** {@inheritDoc} */ + @Override + public Locale getRequestLocale() { + return env.getLocale(); + } + + /** + * Returns the page scope. + * + * @return The page scope. + */ + public Map getPageScope() { + if (pageScope == null) { + pageScope = new EnvironmentScopeMap(env); + } + return pageScope; + } + + @Override + public List getAvailableScopes() { + return scopes; + } + + /** {@inheritDoc} */ + @Override + public PrintWriter getPrintWriter() { + Writer writer = env.getOut(); + if (writer instanceof PrintWriter) { + return (PrintWriter) writer; + } + return new PrintWriter(writer); + } + + /** {@inheritDoc} */ + @Override + public Writer getWriter() { + return env.getOut(); + } + + @Override + public Map getContext(String scope) { + return "page".equals(scope) ? getPageScope() : super.getContext(scope); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestException.java new file mode 100644 index 0000000000..a03ae300e2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestException.java @@ -0,0 +1,37 @@ +/* + * 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.apache.tiles.request.freemarker; + +import org.apache.tiles.request.RequestException; + +/** + * Thrown when a Freemarker request fails. + */ +public class FreemarkerRequestException extends RequestException { + + /** + * Constructor. + * + * @param message The detail message. + * @param cause The cause to be wrapped. + */ + public FreemarkerRequestException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtil.java new file mode 100644 index 0000000000..6c43f231ea --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtil.java @@ -0,0 +1,82 @@ +/* + * 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.apache.tiles.request.freemarker; + +import freemarker.core.Environment; +import freemarker.ext.servlet.FreemarkerServlet; +import freemarker.ext.servlet.HttpRequestHashModel; +import freemarker.ext.servlet.ServletContextHashModel; +import freemarker.template.TemplateModelException; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.servlet.ServletUtil; + +/** + * Utilities to work with Freemarker requests. + */ +public final class FreemarkerRequestUtil { + + /** + * Constructor. + */ + private FreemarkerRequestUtil() { + } + + /** + * Returns the HTTP request hash model. + * + * @param env The current FreeMarker environment. + * @return The request hash model. + */ + public static HttpRequestHashModel getRequestHashModel(Environment env) { + try { + return (HttpRequestHashModel) env.getDataModel().get(FreemarkerServlet.KEY_REQUEST); + } catch (TemplateModelException e) { + throw new NotAvailableFreemarkerServletException("Exception got when obtaining the request hash model", e); + } + } + + /** + * Returns the servlet context hash model. + * + * @param env The current FreeMarker environment. + * @return The servlet context hash model. + */ + public static ServletContextHashModel getServletContextHashModel(Environment env) { + try { + return (ServletContextHashModel) env.getDataModel().get(FreemarkerServlet.KEY_APPLICATION); + } catch (TemplateModelException e) { + throw new NotAvailableFreemarkerServletException("Exception got when obtaining the application hash model", e); + } + } + + /** + * Returns the application context. It must be + * first saved creating an {@link ApplicationContext} and using + * {@link org.apache.tiles.request.ApplicationAccess#register(ApplicationContext)}. + * + * @param env The Freemarker environment. + * @return The + */ + public static ApplicationContext getApplicationContext(Environment env) { + return ServletUtil.getApplicationContext( + getServletContextHashModel(env).getServlet().getServletContext() + ); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletException.java new file mode 100644 index 0000000000..c34b911684 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletException.java @@ -0,0 +1,37 @@ +/* + * 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.apache.tiles.request.freemarker; + +import org.apache.tiles.request.NotAvailableFeatureException; + +/** + * Thrown when the Freemarker servlet is not available. + */ +public class NotAvailableFreemarkerServletException extends NotAvailableFeatureException { + + /** + * Constructor. + * + * @param message The detail message. + * @param e The cause to be wrapped. + */ + public NotAvailableFreemarkerServletException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagException.java new file mode 100644 index 0000000000..9ba13c8822 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagException.java @@ -0,0 +1,36 @@ +/* + * 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.apache.tiles.request.freemarker.autotag; + +/** + * Thrown when a Freemarker problem under Autotag runtime part happens. + */ +public class FreemarkerAutotagException extends RuntimeException { + + /** + * Constructor. + * + * @param message The message of the exception. + * @param cause The cause. + */ + public FreemarkerAutotagException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntime.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntime.java new file mode 100644 index 0000000000..9fe1a7de60 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntime.java @@ -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.apache.tiles.request.freemarker.autotag; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateModel; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.freemarker.FreemarkerRequest; +import org.apache.tiles.request.freemarker.FreemarkerRequestUtil; + +import java.util.Map; + +/** + * A Runtime for implementing a Freemarker Template Directive. + */ +public class FreemarkerAutotagRuntime implements AutotagRuntime, TemplateDirectiveModel { + + private Environment env; + private TemplateDirectiveBody body; + private Map params; + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override + public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) { + this.env = env; + this.body = body; + this.params = params; + } + + /** {@inheritDoc} */ + @Override + public Request createRequest() { + return FreemarkerRequest.createServletFreemarkerRequest(FreemarkerRequestUtil.getApplicationContext(env), env); + } + + /** {@inheritDoc} */ + @Override + public ModelBody createModelBody() { + return new FreemarkerModelBody(env.getOut(), body); + } + + /** {@inheritDoc} */ + @Override + public T getParameter(String name, Class type, T defaultValue) { + return FreemarkerUtil.getAsObject(params.get(name), type, defaultValue); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBody.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBody.java new file mode 100644 index 0000000000..85f52b7e30 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBody.java @@ -0,0 +1,62 @@ +/* + * 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.apache.tiles.request.freemarker.autotag; + +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateException; +import org.apache.tiles.autotag.core.runtime.AbstractModelBody; + +import java.io.IOException; +import java.io.Writer; + +/** + * Body implementation of a Freemarker model body. + */ +public class FreemarkerModelBody extends AbstractModelBody { + + /** + * The real body. + */ + private final TemplateDirectiveBody templateDirectiveBody; + + /** + * Constructor. + * + * @param defaultWriter The default writer. + * @param templateDirectiveBody The real body. + */ + public FreemarkerModelBody(Writer defaultWriter, TemplateDirectiveBody templateDirectiveBody) { + super(defaultWriter); + this.templateDirectiveBody = templateDirectiveBody; + } + + @Override + public void evaluate(Writer writer) throws IOException { + if (templateDirectiveBody == null) { + return; + } + + try { + templateDirectiveBody.render(writer); + } catch (TemplateException e) { + throw new IOException("TemplateException when rendering body", e); + } + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtil.java new file mode 100644 index 0000000000..37362edc3c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtil.java @@ -0,0 +1,60 @@ +/* + * 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.apache.tiles.request.freemarker.autotag; + +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; +import freemarker.template.utility.DeepUnwrap; + +/** + * Utilities for FreeMarker usage in Tiles. + */ +public final class FreemarkerUtil { + + /** + * Private constructor to avoid instantiation. + */ + private FreemarkerUtil() { + } + + /** + * Unwraps a TemplateModel to extract an object. + * + * @param model The TemplateModel to unwrap. + * @param defaultValue The default value, as specified in the template + * model, or null if not specified. + * @return The unwrapped object. + */ + public static T getAsObject(TemplateModel model, Class type, T defaultValue) { + try { + T retValue = defaultValue; + if (model != null) { + @SuppressWarnings("unchecked") + T value = (T) DeepUnwrap.unwrap(model); + if (value != null) { + retValue = value; + } + } + return retValue; + } catch (TemplateModelException e) { + throw new FreemarkerAutotagException("Cannot unwrap a model", e); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/package-info.java new file mode 100644 index 0000000000..af78d7b2d4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Runtime part of Autotag support for Freemarker. + */ +package org.apache.tiles.request.freemarker.autotag; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractor.java new file mode 100644 index 0000000000..e7ce577d66 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractor.java @@ -0,0 +1,87 @@ +/* + * 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.apache.tiles.request.freemarker.extractor; + +import freemarker.core.Environment; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; +import freemarker.template.utility.DeepUnwrap; +import org.apache.tiles.request.attribute.AttributeExtractor; +import org.apache.tiles.request.freemarker.FreemarkerRequestException; + +import java.util.Collections; +import java.util.Enumeration; + +/** + * Extract attributes from {@link Environment} objects as a scope. + */ +public class EnvironmentScopeExtractor implements AttributeExtractor { + + /** + * The environment. + */ + private final Environment request; + + /** + * Constructor. + * + * @param request The environment. + */ + public EnvironmentScopeExtractor(Environment request) { + this.request = request; + } + + @Override + public void removeValue(String name) { + request.setVariable(name, null); + } + + @SuppressWarnings("unchecked") + @Override + public Enumeration getKeys() { + try { + return Collections. enumeration(request.getKnownVariableNames()); + } catch (TemplateModelException e) { + throw new FreemarkerRequestException("Cannot iterate variable names correctly", e); + } + } + + @Override + public Object getValue(String key) { + try { + TemplateModel variable = request.getVariable(key); + if (variable != null) { + return DeepUnwrap.unwrap(variable); + } + return null; + } catch (TemplateModelException e) { + throw new FreemarkerRequestException("Cannot get attribute with name '" + key + "'", e); + } + } + + @Override + public void setValue(String key, Object value) { + try { + TemplateModel model = request.getObjectWrapper().wrap(value); + request.setVariable(key, model); + } catch (TemplateModelException e) { + throw new FreemarkerRequestException("Error when wrapping an object setting the '" + key + "' attribute", e); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/package-info.java new file mode 100644 index 0000000000..8e94691d6f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Extractors to get information from Freemarker objects. + */ +package org.apache.tiles.request.freemarker.extractor; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/package-info.java new file mode 100644 index 0000000000..234a67c5ba --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Support for Freemarker's Environment as a request. + */ +package org.apache.tiles.request.freemarker; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableFactory.java new file mode 100644 index 0000000000..18642640d4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableFactory.java @@ -0,0 +1,34 @@ +/* + * 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.apache.tiles.request.freemarker.servlet; + +import freemarker.template.TemplateModel; + +/** + * It is an object that can create a shared variable, as a template model. + */ +public interface SharedVariableFactory { + + /** + * Creates a new shared variable. + * + * @return The shared variable. + */ + TemplateModel create(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/WebappClassTemplateLoader.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/WebappClassTemplateLoader.java new file mode 100644 index 0000000000..5103903a52 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/WebappClassTemplateLoader.java @@ -0,0 +1,81 @@ +/* + * 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.apache.tiles.request.freemarker.servlet; + +import freemarker.cache.ClassTemplateLoader; +import freemarker.cache.TemplateLoader; +import freemarker.cache.WebappTemplateLoader; + +import javax.servlet.ServletContext; +import java.io.IOException; +import java.io.Reader; + +/** + * Delegates loading templates using a {@link WebappTemplateLoader} and, if not + * found, a {@link ClassTemplateLoader}. The resources are loaded from the + * webapp root and from the classpath root. + */ +public class WebappClassTemplateLoader implements TemplateLoader { + + /** + * The webapp template loader. + */ + private final WebappTemplateLoader webappTemplateLoader; + + /** + * The webapp template loader. + */ + private final ClassTemplateLoader classTemplateLoader; + + /** + * Constructor. + * + * @param servletContext The servlet context. + */ + public WebappClassTemplateLoader(ServletContext servletContext) { + webappTemplateLoader = new WebappTemplateLoader(servletContext); + classTemplateLoader = new ClassTemplateLoader(getClass(), "/"); + } + + /** {@inheritDoc} */ + public Object findTemplateSource(String name) throws IOException { + Object retValue = webappTemplateLoader.findTemplateSource(name); + if (retValue == null) { + retValue = classTemplateLoader.findTemplateSource(name); + } + return retValue; + } + + /** {@inheritDoc} */ + public void closeTemplateSource(Object templateSource) throws IOException { + webappTemplateLoader.closeTemplateSource(templateSource); + } + + /** {@inheritDoc} */ + public long getLastModified(Object templateSource) { + return webappTemplateLoader.getLastModified(templateSource); + } + + /** {@inheritDoc} */ + public Reader getReader(Object templateSource, String encoding) + throws IOException { + return webappTemplateLoader.getReader(templateSource, encoding); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/package-info.java new file mode 100644 index 0000000000..c93d7b0c7c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Servlets for easy addition of shared variables. + */ +package org.apache.tiles.request.freemarker.servlet; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspPrintWriterAdapter.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspPrintWriterAdapter.java new file mode 100644 index 0000000000..a7b2e26296 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspPrintWriterAdapter.java @@ -0,0 +1,432 @@ +/* + * 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.apache.tiles.request.jsp; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.servlet.jsp.JspWriter; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * Adapts a {@link JspWriter} to a {@link PrintWriter}, swallowing {@link IOException}. + */ +public class JspPrintWriterAdapter extends PrintWriter { + + /** + * The JSP writer. + */ + private final JspWriter writer; + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(JspPrintWriterAdapter.class); + + /** + * Constructor. + * + * @param writer The JSP writer. + */ + public JspPrintWriterAdapter(JspWriter writer) { + super(writer); + this.writer = writer; + } + + /** + * {@inheritDoc} + */ + @Override + public PrintWriter append(char c) { + try { + writer.append(c); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public PrintWriter append(CharSequence csq, int start, int end) { + try { + writer.append(csq, start, end); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public PrintWriter append(CharSequence csq) { + try { + writer.append(csq); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public void close() { + try { + writer.close(); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void flush() { + try { + writer.flush(); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(boolean b) { + try { + writer.print(b); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(char c) { + try { + writer.print(c); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(char[] s) { + try { + writer.print(s); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(double d) { + try { + writer.print(d); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(float f) { + try { + writer.print(f); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(int i) { + try { + writer.print(i); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(long l) { + try { + writer.print(l); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(Object obj) { + try { + writer.print(obj); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(String s) { + try { + writer.print(s); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println() { + try { + writer.println(); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(boolean x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(char x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(char[] x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(double x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(float x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(int x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(long x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(Object x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(String x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void write(char[] buf, int off, int len) { + try { + writer.write(buf, off, len); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void write(char[] buf) { + try { + writer.write(buf); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void write(int c) { + try { + writer.write(c); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void write(String s, int off, int len) { + try { + writer.write(s, off, len); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void write(String s) { + try { + writer.write(s); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspRequest.java new file mode 100644 index 0000000000..7e94e331e1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspRequest.java @@ -0,0 +1,199 @@ +/* + * 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.apache.tiles.request.jsp; + +import org.apache.tiles.request.AbstractViewRequest; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.DispatchRequest; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.jsp.extractor.ScopeExtractor; +import org.apache.tiles.request.jsp.extractor.SessionScopeExtractor; +import org.apache.tiles.request.servlet.ServletRequest; +import org.apache.tiles.request.servlet.ServletUtil; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.jsp.PageContext; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Context implementation used for executing tiles within a jsp tag library. + */ +public class JspRequest extends AbstractViewRequest { + + /** + * The native available scopes. + */ + private static final List SCOPES = Collections.unmodifiableList(Arrays.asList("page", REQUEST_SCOPE, "session", APPLICATION_SCOPE)); + + /** + * The current page context. + */ + private final PageContext pageContext; + + /** + *

The lazily instantiated Map of page scope + * attributes.

+ */ + private Map pageScope = null; + + /** + *

The lazily instantiated Map of request scope + * attributes.

+ */ + private Map requestScope = null; + + /** + *

The lazily instantiated Map of session scope + * attributes.

+ */ + private Map sessionScope = null; + + /** + *

The lazily instantiated Map of application scope + * attributes.

+ */ + private Map applicationScope = null; + + /** + * Creates a JSP request. + * + * @param applicationContext The application context. + * @param pageContext The page context. + * @return A new JSP request. + */ + public static JspRequest createServletJspRequest(ApplicationContext applicationContext, PageContext pageContext) { + return new JspRequest(new ServletRequest( + applicationContext, (HttpServletRequest) pageContext + .getRequest(), (HttpServletResponse) pageContext + .getResponse()), pageContext); + } + + /** + * Constructor. + * + * @param enclosedRequest The request that is wrapped here. + * @param pageContext The page context to use. + */ + public JspRequest(DispatchRequest enclosedRequest, + PageContext pageContext) { + super(enclosedRequest); + this.pageContext = pageContext; + } + + @Override + public List getAvailableScopes() { + return SCOPES; + } + + /** {@inheritDoc} */ + @Override + protected void doInclude(String path) throws IOException { + try { + pageContext.include(path, false); + } catch (ServletException e) { + throw ServletUtil.wrapServletException(e, "JSPException including path '" + + path + "'."); + } + } + + /** {@inheritDoc} */ + @Override + public PrintWriter getPrintWriter() { + return new JspPrintWriterAdapter(pageContext.getOut()); + } + + /** {@inheritDoc} */ + @Override + public Writer getWriter() { + return pageContext.getOut(); + } + + /** + * Returns the page scope. + * + * @return The page scope. + */ + public Map getPageScope() { + if ((pageScope == null) && (pageContext != null)) { + pageScope = new ScopeMap(new ScopeExtractor(pageContext, + PageContext.PAGE_SCOPE)); + } + return (pageScope); + } + + /** + * Returns the request scope. + * + * @return The request scope. + */ + public Map getRequestScope() { + if ((requestScope == null) && (pageContext != null)) { + requestScope = new ScopeMap(new ScopeExtractor(pageContext, + PageContext.REQUEST_SCOPE)); + } + return (requestScope); + } + + /** + * Returns the session scope. + * + * @return The session scope. + */ + public Map getSessionScope() { + if ((sessionScope == null) && (pageContext != null)) { + sessionScope = new ScopeMap(new SessionScopeExtractor(pageContext)); + } + return (sessionScope); + } + + /** + * Returns the application scope. + * + * @return The application scope. + */ + public Map getApplicationScope() { + if ((applicationScope == null) && (pageContext != null)) { + applicationScope = new ScopeMap(new ScopeExtractor(pageContext, + PageContext.APPLICATION_SCOPE)); + } + return (applicationScope); + } + + @Override + public Map getContext(String scope) { + if("page".equals(scope)){ + return getPageScope(); + }else if(REQUEST_SCOPE.equals(scope)){ + return getRequestScope(); + }else if("session".equals(scope)){ + return getSessionScope(); + }else if(APPLICATION_SCOPE.equals(scope)){ + return getApplicationScope(); + } + throw new IllegalArgumentException(scope + " does not exist. Call getAvailableScopes() first to check."); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspUtil.java new file mode 100644 index 0000000000..0a79145a04 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspUtil.java @@ -0,0 +1,52 @@ +/* + * 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.apache.tiles.request.jsp; + +import org.apache.tiles.request.ApplicationAccess; +import org.apache.tiles.request.ApplicationContext; + +import javax.servlet.jsp.JspContext; +import javax.servlet.jsp.PageContext; + +/** + * JSP utilities for JSP requests and related. + */ +public final class JspUtil { + + /** + * Constructor. + */ + private JspUtil() { + } + + /** + * Returns the application context. It must be + * first saved creating an {@link ApplicationContext} and using + * {@link ApplicationAccess#register(ApplicationContext)}. + * + * @param jspContext The JSP context. + * @return The application context. + */ + public static ApplicationContext getApplicationContext(JspContext jspContext) { + return (ApplicationContext) jspContext.getAttribute( + ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE, + PageContext.APPLICATION_SCOPE + ); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntime.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntime.java new file mode 100644 index 0000000000..ac15efa7e8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntime.java @@ -0,0 +1,69 @@ +/* + * 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.apache.tiles.request.jsp.autotag; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.jsp.JspRequest; + +import javax.servlet.jsp.JspContext; +import javax.servlet.jsp.PageContext; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +/** + * A Runtime for implementing JSP tag libraries. + */ +public class JspAutotagRuntime extends SimpleTagSupport implements AutotagRuntime { + + /** + * {@inheritDoc} + */ + @Override + public void doTag() { + // do nothing like the parent implementation, + // but don't throw exceptions either + } + + /** + * {@inheritDoc} + */ + @Override + public Request createRequest() { + JspContext pageContext = getJspContext(); + return JspRequest.createServletJspRequest(org.apache.tiles.request.jsp.JspUtil.getApplicationContext(pageContext), + (PageContext) pageContext); + } + + /** + * {@inheritDoc} + */ + @Override + public ModelBody createModelBody() { + return new JspModelBody(getJspBody(), getJspContext()); + } + + /** + * {@inheritDoc} + */ + @Override + public T getParameter(String name, Class type, T defaultValue) { + throw new UnsupportedOperationException("the parameters are injected into the tag itself, no need to fetch them"); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspModelBody.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspModelBody.java new file mode 100644 index 0000000000..ad97215759 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspModelBody.java @@ -0,0 +1,63 @@ +/* + * 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.apache.tiles.request.jsp.autotag; + +import org.apache.tiles.autotag.core.runtime.AbstractModelBody; + +import javax.servlet.jsp.JspContext; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.JspFragment; +import java.io.IOException; +import java.io.Writer; + +/** + * The body abstraction in a JSP tag. + */ +public class JspModelBody extends AbstractModelBody { + + /** + * The real body. + */ + private final JspFragment jspFragment; + + /** + * Constructor. + * + * @param jspFragment The real body. + * @param jspContext The page context. + */ + public JspModelBody(JspFragment jspFragment, JspContext jspContext) { + super(jspContext.getOut()); + this.jspFragment = jspFragment; + } + + @Override + public void evaluate(Writer writer) throws IOException { + if (jspFragment == null) { + return; + } + + try { + jspFragment.invoke(writer); + } catch (JspException e) { + throw new IOException("JspException when evaluating the body", e); + } + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/package-info.java new file mode 100644 index 0000000000..ce77fc4271 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Runtime part of Autotag support for JavaServer pages. + */ +package org.apache.tiles.request.jsp.autotag; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/ScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/ScopeExtractor.java new file mode 100644 index 0000000000..e3485226a5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/ScopeExtractor.java @@ -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.apache.tiles.request.jsp.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.servlet.jsp.JspContext; +import java.util.Enumeration; + +/** + * Extracts attributes from a numbered scope from {@link JspContext}. + */ +public class ScopeExtractor implements AttributeExtractor { + + /** + * The JSP context. + */ + private final JspContext context; + + /** + * The scope number to use. + */ + private final int scope; + + /** + * Constructor. + * + * @param context The JSP context. + * @param scope The scope number. + */ + public ScopeExtractor(JspContext context, int scope) { + this.context = context; + this.scope = scope; + } + + @Override + public void removeValue(String name) { + context.removeAttribute(name, scope); + } + + @Override + public Enumeration getKeys() { + return context.getAttributeNamesInScope(scope); + } + + @Override + public Object getValue(String key) { + return context.getAttribute(key, scope); + } + + @Override + public void setValue(String key, Object value) { + context.setAttribute(key, value, scope); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractor.java new file mode 100644 index 0000000000..73eec8df11 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractor.java @@ -0,0 +1,76 @@ +/* + * 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.apache.tiles.request.jsp.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.servlet.jsp.PageContext; +import java.util.Enumeration; + +/** + * Extracts attributes from session scope from {@link PageContext}. + */ +public class SessionScopeExtractor implements AttributeExtractor { + + /** + * The page context. + */ + private final PageContext context; + + /** + * Constructor. + * + * @param context The page context. + */ + public SessionScopeExtractor(PageContext context) { + this.context = context; + } + + @Override + public void removeValue(String name) { + if (context.getSession() == null) { + return; + } + context.removeAttribute(name, PageContext.SESSION_SCOPE); + } + + @Override + public Enumeration getKeys() { + if (context.getSession() == null) { + return null; + } + return context.getAttributeNamesInScope(PageContext.SESSION_SCOPE); + } + + @Override + public Object getValue(String key) { + if (context.getSession() == null) { + return null; + } + return context.getAttribute(key, PageContext.SESSION_SCOPE); + } + + @Override + public void setValue(String key, Object value) { + if (context.getSession() == null) { + return; + } + context.setAttribute(key, value, PageContext.SESSION_SCOPE); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/package-info.java new file mode 100644 index 0000000000..0e2d9cbbc5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Extractors to get scopes from {@link javax.servlet.jsp.PageContext}. + */ +package org.apache.tiles.request.jsp.extractor; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/package-info.java new file mode 100644 index 0000000000..edf2b21283 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Support of Tiles request in a JSP environment. + */ +package org.apache.tiles.request.jsp; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/locale/LocaleUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/LocaleUtil.java new file mode 100644 index 0000000000..0b36504802 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/LocaleUtil.java @@ -0,0 +1,58 @@ +/* + * 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.apache.tiles.request.locale; + +import java.util.Locale; + +/** + * Utilities for locale manipulation. + */ +public final class LocaleUtil { + + /** + * Private constructor to avoid instantiation. + */ + private LocaleUtil() { + } + + /** + *

+ * Returns the "parent" locale of a given locale. If the original locale is only language-based, + * the {@link Locale#ROOT} object is returned. + *

+ * + * @param locale The original locale. + * @return The parent locale. + */ + public static Locale getParentLocale(Locale locale) { + Locale retValue = null; + String language = locale.getLanguage(); + String country = locale.getCountry(); + String variant = locale.getVariant(); + if (!"".equals(variant)) { + retValue = new Locale(language, country); + } else if (!"".equals(country)) { + retValue = new Locale(language); + } else if (!"".equals(language)) { + retValue = Locale.ROOT; + } + + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java new file mode 100644 index 0000000000..85c44745b1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java @@ -0,0 +1,235 @@ +/* + * 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.apache.tiles.request.locale; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.request.ApplicationResource; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +/** + * An ApplicationResource whose localization is managed by postfixing the file name. + * The various localizations are file sitting next to each other, with the locale identified in the postfix. + *

+ * For instance: + *

+ * /WEB-INF/tiles.xml
+ * /WEB-INF/tiles_fr.xml
+ * /WEB-INF/tiles_it.xml
+ * /WEB-INF/tiles_it_IT.xml
+ * 
+ * + * Two PostfixedApplicationResources are equals if they share the same localized path and the same class. + */ +public abstract class PostfixedApplicationResource implements ApplicationResource { + + private static final Logger LOG = LogManager.getLogger(PostfixedApplicationResource.class); + + /** The path without its suffix and its locale postfix. */ + private String pathPrefix; + /** The suffix. */ + private final String suffix; + /** The Locale. */ + private final Locale locale; + + /** + * Create a new PostfixedApplicationResource for the specified path. + * @param localePath the path including localization. + */ + protected PostfixedApplicationResource(String localePath) { + int prefixIndex = localePath.indexOf('_', localePath.lastIndexOf("/")); + int suffixIndex = localePath.lastIndexOf('.'); + if (suffixIndex < 0) { + suffix = ""; + suffixIndex = localePath.length(); + } else { + suffix = localePath.substring(suffixIndex); + } + if (prefixIndex < 0) { + pathPrefix = localePath.substring(0, suffixIndex); + locale = Locale.ROOT; + } else { + pathPrefix = localePath.substring(0, prefixIndex); + String localeString = localePath.substring(prefixIndex + 1, suffixIndex); + Locale found = localeFrom(localeString); + locale = validateLocale(found); + if (Locale.ROOT.equals(locale)) { + pathPrefix = localePath.substring(0, suffixIndex); + + LOG.warn("No supported matching language for locale \"" + localeString + "\". Using " + + getPath() + " as a non-localized resource path. see TILES-571"); + + } else if (!localeString.equalsIgnoreCase(getPostfix(locale).substring(1))) { + LOG.warn("For resource " + localePath + + " the closest supported matching locale to \"" + localeString + "\" is \"" + locale + + "\". Using " + getPath() + " as resource path. see TILES-571"); + } + } + } + + /** + * Create a new PostfixedApplicationResource for the specified path. + * @param path the path excluding localization. + * @param locale the Locale. + */ + protected PostfixedApplicationResource(String path, Locale locale) { + int suffixIndex = path.lastIndexOf('.'); + if (suffixIndex < 0) { + suffix = ""; + pathPrefix = path; + } else { + pathPrefix = path.substring(0, suffixIndex); + suffix = path.substring(suffixIndex); + } + this.locale = locale; + } + + /** {@inheritDoc} */ + @Override + public final String getLocalePath() { + return getLocalePath(locale); + } + + /** {@inheritDoc} */ + @Override + public final String getPath() { + return pathPrefix + suffix; + } + + /** {@inheritDoc} */ + @Override + public final String getLocalePath(Locale newLocale) { + return pathPrefix + getPostfix(newLocale) + suffix; + } + + /** + * Get the postfix for that Locale. + * @param locale a locale. + * @return the matching postfix. + */ + private static String getPostfix(Locale locale) { + if (locale == null) { + return ""; + } + + StringBuilder builder = new StringBuilder(); + String language = locale.getLanguage(); + String country = locale.getCountry(); + String variant = locale.getVariant(); + if (!"".equals(language)) { + builder.append("_"); + builder.append(language); + if (!"".equals(country)) { + builder.append("_"); + builder.append(country); + if (!"".equals(variant)) { + builder.append("_"); + builder.append(variant); + } + } + } + return builder.toString(); + } + + /** {@inheritDoc} */ + @Override + public final Locale getLocale() { + return locale; + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((locale == null) ? 0 : locale.hashCode()); + result = prime * result + ((pathPrefix == null) ? 0 : pathPrefix.hashCode()); + result = prime * result + ((suffix == null) ? 0 : suffix.hashCode()); + return result; + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PostfixedApplicationResource other = (PostfixedApplicationResource) obj; + if (locale == null) { + if (other.locale != null) + return false; + } else if (!locale.equals(other.locale)) + return false; + if (pathPrefix == null) { + if (other.pathPrefix != null) + return false; + } else if (!pathPrefix.equals(other.pathPrefix)) + return false; + if (suffix == null) { + return other.suffix == null; + } else return suffix.equals(other.suffix); + } + + private static Locale localeFrom(String localeString) { + Locale result; + int countryIndex = localeString.indexOf('_'); + if (countryIndex < 0) { + result = new Locale(localeString); + } else { + int variantIndex = localeString.indexOf('_', countryIndex + 1); + if (variantIndex < 0) { + result = new Locale( + localeString.substring(0, countryIndex), + localeString.substring(countryIndex + 1)); + } else { + result = new Locale( + localeString.substring(0, countryIndex), + localeString.substring(countryIndex + 1, variantIndex), + localeString.substring(variantIndex + 1)); + } + } + return result; + } + + private static final Set availableLocales = new HashSet<>(Arrays.asList(Locale.getAvailableLocales())); + + private static Locale validateLocale(Locale locale) { + Locale withoutVariant = locale.getVariant().isEmpty() + ? locale + : new Locale(locale.getLanguage(), locale.getCountry()); + + Locale result = locale; + if (!availableLocales.contains(withoutVariant)) { + if (!result.getCountry().isEmpty()) { + result = new Locale(result.getLanguage()); + } + if (!availableLocales.contains(result)) { + result = Locale.ROOT; + } + } + return result; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/locale/URLApplicationResource.java b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/URLApplicationResource.java new file mode 100644 index 0000000000..a4e71a818f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/URLApplicationResource.java @@ -0,0 +1,213 @@ +/* + * 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.apache.tiles.request.locale; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.JarURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +/** + * A {@link PostfixedApplicationResource} that can be accessed through a URL. + */ + +public class URLApplicationResource extends PostfixedApplicationResource { + /** + * System parameter to specify additional remote protocols. If an url has a remote protocol, then any + * {@link IOException} will be thrown directly. If an url has a local protocol, then any {@link IOException} + * will be caught and transformed into a {@link FileNotFoundException}. + */ + static final String REMOTE_PROTOCOLS_PROPERTY = "tiles.remoteProtocols"; + + private static final Logger LOG = LogManager.getLogger(URLApplicationResource.class); + + private static final Set REMOTE_PROTOCOLS; + + static { + REMOTE_PROTOCOLS = initRemoteProtocols(); + } + + /** + * Creates an unmodifiable set of remote protocols which are used in {@link URL} objects, see {@link URL#getProtocol()}. + * AN url with a remote protocol establishes a network connection when its {@link URL#openConnection()} is being called. + * The set will always contain the built-in remote protocols below: + * + * It's possible, that your environment provides additional remote protocols because of following reasons: + *
    + *
  • your application server adds more remote protocols, see its documentation for further details.
  • + *
  • your application supplies custom remote protocols trough its own {@link java.net.URLStreamHandlerFactory} + * (see following excellent explanation + * for getting an idea how to do this)
  • + *
+ * If you need to use such extra remote protocols in Tiles, you may enhance the set via system property {@code tiles.remoteProtocols}. Suppose + * you need to add your custom remote protocols "foo" and "bar". To do so, add following parameter to the command line (use ";" as separator): + *
+     *     -Dtiles.remoteProtocols=foo;bar
+     * 
+ * The resulting set will then contain the built-in protocols plus "foo" and "bar". + * + * @return Unmodifiable set of remote protocols, never {@code null} + */ + static Set initRemoteProtocols() { + Set remoteProtocols = new HashSet<>(); + remoteProtocols.add("ftp"); + remoteProtocols.add("http"); + remoteProtocols.add("https"); + + String protocolsProp = System.getProperty(REMOTE_PROTOCOLS_PROPERTY); + if (protocolsProp != null) { + for (String protocol : protocolsProp.split(";")) { + remoteProtocols.add(protocol.trim()); + } + } + return Collections.unmodifiableSet(remoteProtocols); + } + + private boolean isLocal(URL url) { + return !REMOTE_PROTOCOLS.contains(url.getProtocol()); + } + + /** + * the URL where the contents can be found. + */ + private final URL url; + /** + * if the URL matches a file, this is the file. + */ + private File file; + /** + * if the URL points to a local resource + */ + private final boolean local; + + /** + * Creates a URLApplicationResource for the specified path that can be accessed through the specified URL. + * + * @param localePath the path including localization. + * @param url the URL where the contents can be found. + */ + public URLApplicationResource(String localePath, URL url) { + super(localePath); + this.url = url; + if ("file".equals(url.getProtocol())) { + file = getFile(url); + } + local = isLocal(url); + } + + /** + * Creates a URLApplicationResource for the specified path that can be accessed through the specified URL. + * + * @param path the path excluding localization. + * @param locale the Locale. + * @param url the URL where the contents can be found. + */ + public URLApplicationResource(String path, Locale locale, URL url) { + super(path, locale); + this.url = url; + if ("file".equals(url.getProtocol())) { + file = getFile(url); + } + local = isLocal(url); + } + + private URLConnection openConnection() throws IOException { + try { + return url.openConnection(); + } catch (IOException e) { + // If the url points to a local resource, but it cannot be + // opened, then the resource actually does not exist. In this + // case throw a FileNotFoundException + if (local) { + FileNotFoundException fne = new FileNotFoundException(url.toString()); + fne.initCause(e); + throw fne; + } + throw e; + } + } + + private File getFile(URL url) { + try { + return new File(new URI(url.toExternalForm()).getSchemeSpecificPart()); + } catch (URISyntaxException e) { + LOG.debug("Cannot translate URL to file name, expect a performance impact", e); + return null; + } + } + + /** + * {@inheritDoc} + */ + @Override + public InputStream getInputStream() throws IOException { + if (file != null) { + if (file.exists()) { + return Files.newInputStream(file.toPath()); + } else { + throw new FileNotFoundException("File does not exist: " + file); + } + } else { + return openConnection().getInputStream(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public long getLastModified() throws IOException { + if (file != null) { + return file.lastModified(); + } else { + URLConnection connection = openConnection(); + if (connection instanceof JarURLConnection) { + return ((JarURLConnection) connection).getJarEntry().getTime(); + } else { + return connection.getLastModified(); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return "Resource " + getLocalePath() + " at " + url.toString(); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/CannotInstantiateObjectException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/CannotInstantiateObjectException.java new file mode 100644 index 0000000000..7b922fd8f3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/CannotInstantiateObjectException.java @@ -0,0 +1,38 @@ +/* + * 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.apache.tiles.request.reflect; + +import org.apache.tiles.request.RequestException; + +/** + * Indicates that an object cannot be instantiated. + */ +public class CannotInstantiateObjectException extends RequestException { + + /** + * Constructor. + * + * @param message The detail message. + * @param e The exception to be wrapped. + */ + public CannotInstantiateObjectException(String message, Throwable e) { + super(message, e); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/ClassUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/ClassUtil.java new file mode 100644 index 0000000000..8211b3ac62 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/ClassUtil.java @@ -0,0 +1,123 @@ +/* + * 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.apache.tiles.request.reflect; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.util.Map; + +/** + * Utilities to work with dynamic class loading and instantiation. + */ +public final class ClassUtil { + + private static final Logger LOG = LogManager.getLogger(ClassUtil.class); + + /** + * Constructor, private to avoid instantiation. + */ + private ClassUtil() { + } + + /** + * Returns the class and casts it to the correct subclass.
+ * It tries to use the thread's current classloader first and, if it does + * not succeed, uses the classloader of ClassUtil. + * + * @param The subclass to use. + * @param className The name of the class to load. + * @param baseClass The base class to subclass to. + * @return The loaded class. + * @throws ClassNotFoundException If the class has not been found. + */ + public static Class getClass(String className, Class baseClass) throws ClassNotFoundException { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = ClassUtil.class.getClassLoader(); + } + return Class.forName(className, true, classLoader).asSubclass(baseClass); + } + + /** + * Returns an instance of the given class name, by calling the default + * constructor. + * + * @param className The class name to load and to instantiate. + * @return The new instance of the class name. + * @throws CannotInstantiateObjectException If something goes wrong during + * instantiation. + */ + public static Object instantiate(String className) { + return instantiate(className, false); + } + + /** + * Returns an instance of the given class name, by calling the default + * constructor. + * + * @param className The class name to load and to instantiate. + * @param returnNull If true, if the class is not found it + * returns true, otherwise it throws a + * TilesException. + * @return The new instance of the class name. + * @throws CannotInstantiateObjectException If something goes wrong during instantiation. + */ + public static Object instantiate(String className, boolean returnNull) { + try { + Class namedClass = getClass(className, Object.class); + return namedClass.newInstance(); + } catch (ClassNotFoundException e) { + if (returnNull) { + return null; + } + throw new CannotInstantiateObjectException("Unable to resolve factory class: '" + className + "'", e); + } catch (IllegalAccessException e) { + throw new CannotInstantiateObjectException("Unable to access factory class: '" + className + "'", e); + } catch (InstantiationException e) { + throw new CannotInstantiateObjectException("Unable to instantiate factory class: '" + className + "'. Make sure that this class has a default constructor", e); + } + } + + /** + * Collects bean infos from a class and filling a list. + * + * @param clazz The class to be inspected. + * @param name2descriptor The map in the form: name of the property -> descriptor. + */ + public static void collectBeanInfo(Class clazz, Map name2descriptor) { + BeanInfo info = null; + try { + info = Introspector.getBeanInfo(clazz); + } catch (Exception ex) { + LOG.debug("Cannot inspect class " + clazz, ex); + } + if (info == null) { + return; + } + for (PropertyDescriptor pd : info.getPropertyDescriptors()) { + pd.setValue("type", pd.getPropertyType()); + pd.setValue("resolvableAtDesignTime", Boolean.TRUE); + name2descriptor.put(pd.getName(), pd); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/package-info.java new file mode 100644 index 0000000000..c7b0d3cdce --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Utilities to work with dynamic class loading and instantiation. + */ +package org.apache.tiles.request.reflect; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/BasicRendererFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/BasicRendererFactory.java new file mode 100644 index 0000000000..eb6b00fdfe --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/BasicRendererFactory.java @@ -0,0 +1,79 @@ +/* + * 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.apache.tiles.request.render; + +import java.util.HashMap; +import java.util.Map; + +/** + * Basic renderer factory implementation. + */ +public class BasicRendererFactory implements RendererFactory { + + /** + * The renderer name/renderer map. + */ + protected Map renderers; + + /** + * The default renderer. + */ + protected Renderer defaultRenderer; + + /** + * Constructor. + */ + public BasicRendererFactory() { + renderers = new HashMap<>(); + } + + /** {@inheritDoc} */ + public Renderer getRenderer(String name) { + Renderer retValue; + if (name != null) { + retValue = renderers.get(name); + if (retValue == null) { + throw new NoSuchRendererException("Cannot find a renderer named '" + name + "'"); + } + } else { + retValue = defaultRenderer; + } + + return retValue; + } + + /** + * Sets the default renderer. + * + * @param renderer The default renderer. + */ + public void setDefaultRenderer(Renderer renderer) { + this.defaultRenderer = renderer; + } + + /** + * Registers a renderer. + * + * @param name The name of the renderer. + * @param renderer The renderer to register. + */ + public void registerRenderer(String name, Renderer renderer) { + renderers.put(name, renderer); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/CannotRenderException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/CannotRenderException.java new file mode 100644 index 0000000000..d2c5e39f82 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/CannotRenderException.java @@ -0,0 +1,46 @@ +/* + * 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.apache.tiles.request.render; + + +/** + * Indicates that something went wrong during the rendering process. + */ +public class CannotRenderException extends RenderException { + + /** + * Constructor. + * + * @param message The detail message. + */ + public CannotRenderException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param message The detail message. + * @param e The exception to be wrapped. + */ + public CannotRenderException(String message, Throwable e) { + super(message, e); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/ChainedDelegateRenderer.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/ChainedDelegateRenderer.java new file mode 100644 index 0000000000..ff0bdc136b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/ChainedDelegateRenderer.java @@ -0,0 +1,80 @@ +/* + * 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.apache.tiles.request.render; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tiles.request.Request; + +/** + * Renders an attribute that has no associated renderer using delegation to other renderers. + */ +public class ChainedDelegateRenderer implements Renderer { + + /** + * The list of chained renderers. + */ + private final List renderers; + + /** + * Constructor. + */ + public ChainedDelegateRenderer() { + renderers = new ArrayList<>(); + } + + /** + * Adds an attribute renderer to the list. The first inserted this way, the + * first is checked when rendering. + * + * @param renderer The renderer to add. + */ + public void addAttributeRenderer(Renderer renderer) { + renderers.add(renderer); + } + + + @Override + public void render(String value, Request request) throws IOException { + if (value == null) { + throw new NullPointerException("The attribute value is null"); + } + + for (Renderer renderer : renderers) { + if (renderer.isRenderable(value, request)) { + renderer.render(value, request); + return; + } + } + + throw new CannotRenderException("Cannot renderer value '" + value + "'"); + } + + /** {@inheritDoc} */ + public boolean isRenderable(String value, Request request) { + for (Renderer renderer : renderers) { + if (renderer.isRenderable(value, request)) { + return true; + } + } + return false; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/DispatchRenderer.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/DispatchRenderer.java new file mode 100644 index 0000000000..b1db6a09e4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/DispatchRenderer.java @@ -0,0 +1,61 @@ +/* + * 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.apache.tiles.request.render; + +import java.io.IOException; + +import org.apache.tiles.request.Request; +import org.apache.tiles.request.DispatchRequest; +import org.apache.tiles.request.RequestWrapper; + +/** + * Renders an attribute that contains a reference to a template. + */ +public class DispatchRenderer implements Renderer { + + /** {@inheritDoc} */ + @Override + public void render(String path, Request request) throws IOException { + if (path == null) { + throw new CannotRenderException("Cannot dispatch a null path"); + } + DispatchRequest dispatchRequest = getDispatchRequest(request); + if (dispatchRequest == null) { + throw new CannotRenderException("Cannot dispatch outside of a web environment"); + } + + dispatchRequest.dispatch(path); + } + + /** {@inheritDoc} */ + public boolean isRenderable(String path, Request request) { + return path != null && getDispatchRequest(request) != null && path.startsWith("/"); + } + + private DispatchRequest getDispatchRequest(Request request) { + Request result = request; + while (!(result instanceof DispatchRequest) && result instanceof RequestWrapper) { + result = ((RequestWrapper) result).getWrappedRequest(); + } + if (!(result instanceof DispatchRequest)) { + result = null; + } + return (DispatchRequest) result; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/NoSuchRendererException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/NoSuchRendererException.java new file mode 100644 index 0000000000..f3a71983f8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/NoSuchRendererException.java @@ -0,0 +1,35 @@ +/* + * 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.apache.tiles.request.render; + +/** + * It is raised when a named renderer has not been found with that name. + */ +public class NoSuchRendererException extends RenderException { + + /** + * Constructor. + * + * @param message The detail message. + */ + public NoSuchRendererException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/RenderException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/RenderException.java new file mode 100644 index 0000000000..f99ee6024a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/RenderException.java @@ -0,0 +1,46 @@ +/* + * 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.apache.tiles.request.render; + +import org.apache.tiles.request.RequestException; + +/** + * Thrown when rendering fails. + */ +public class RenderException extends RequestException { + + /** + * Constructor. + * + * @param message The message of the exception. + */ + public RenderException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param message The message of the exception. + * @param cause The cause. + */ + public RenderException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/Renderer.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/Renderer.java new file mode 100644 index 0000000000..0768372409 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/Renderer.java @@ -0,0 +1,48 @@ +/* + * 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.apache.tiles.request.render; + +import org.apache.tiles.request.Request; + +import java.io.IOException; + +/** + * An object that can render a path, depending on the request passed as a parameter. + */ +public interface Renderer { + + /** + * Renders a path. + * + * @param path The path to render. + * @param request The Tiles request context. + * @throws IOException If something goes wrong during rendition. + */ + void render(String path, Request request) throws IOException; + + /** + * Checks if this renderer can render a path. Note that this does not mean + * it is the best renderer available, but checks only its capability. + * + * @param path The path to be rendered. + * @param request The request context. + * @return true if this renderer can render the attribute. + */ + boolean isRenderable(String path, Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/RendererFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/RendererFactory.java new file mode 100644 index 0000000000..7119d6455b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/RendererFactory.java @@ -0,0 +1,41 @@ +/* + * 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.apache.tiles.request.render; + +/** + *

+ * Factory interface used to create/retrieve instances of the {@link Renderer} interface. + *

+ * + *

+ * This factory provides an extension point into the default tiles + * implementation. Implementors wishing to provide per request initialization of + * the AttributeRenderer (for instance) may provide a custom renderer. + *

+ */ +public interface RendererFactory { + + /** + * Returns a renderer by its name. + * + * @param name The name of the renderer. + * @return The renderer. + */ + Renderer getRenderer(String name); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/StringRenderer.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/StringRenderer.java new file mode 100644 index 0000000000..309546a2f1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/StringRenderer.java @@ -0,0 +1,43 @@ +/* + * 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.apache.tiles.request.render; + +import java.io.IOException; + +import org.apache.tiles.request.Request; + +/** + * Renders an attribute that contains a string. + */ +public class StringRenderer implements Renderer { + + /** {@inheritDoc} */ + @Override + public void render(String value, Request request) throws IOException { + if (value == null) { + throw new CannotRenderException("Cannot render a null string"); + } + request.getWriter().write(value); + } + + /** {@inheritDoc} */ + public boolean isRenderable(String value, Request request) { + return value != null; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponse.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponse.java new file mode 100644 index 0000000000..492530e7ec --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponse.java @@ -0,0 +1,58 @@ +/* + * $Id: ExternalWriterHttpServletResponse.java 1306435 2012-03-28 15:39:11Z nlebas $ + * + * 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.apache.tiles.request.servlet; + +import java.io.PrintWriter; + +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +/** + * Wraps an HTTP response and overrides its print writer. + * + * @version $Rev: 1306435 $ $Date: 2012-03-29 02:39:11 +1100 (Thu, 29 Mar 2012) $ + */ +public class ExternalWriterHttpServletResponse extends + HttpServletResponseWrapper { + + /** + * The print writer to use, instead of the response's one. + */ + private PrintWriter writer; + + /** + * Constructor. + * + * @param response The response to wrap. + * @param writer The print writer to use, instead of the response's one. + */ + public ExternalWriterHttpServletResponse(HttpServletResponse response, PrintWriter writer) { + super(response); + this.writer = writer; + } + + /** {@inheritDoc} */ + @Override + public PrintWriter getWriter() { + return writer; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/NotAServletEnvironmentException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/NotAServletEnvironmentException.java new file mode 100644 index 0000000000..ce4bf5471f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/NotAServletEnvironmentException.java @@ -0,0 +1,36 @@ +/* + * 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.apache.tiles.request.servlet; + +/** + * Exception that indicates that a resource could not be used because it is not + * in a servlet environment. + */ +public class NotAServletEnvironmentException extends RuntimeException { + + /** + * Constructor. + * + * @param message The detail message. + */ + public NotAServletEnvironmentException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletApplicationContext.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletApplicationContext.java new file mode 100644 index 0000000000..27f2b0e635 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletApplicationContext.java @@ -0,0 +1,127 @@ +/* + * 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.apache.tiles.request.servlet; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.locale.URLApplicationResource; +import org.apache.tiles.request.servlet.extractor.ApplicationScopeExtractor; +import org.apache.tiles.request.servlet.extractor.InitParameterExtractor; + +import javax.servlet.ServletContext; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Locale; +import java.util.Map; + +/** + * Servlet-based implementation of the TilesApplicationContext interface. + */ +public class ServletApplicationContext implements ApplicationContext { + + /** + * The servlet context to use. + */ + private final ServletContext servletContext; + + /** + *

The lazily instantiated Map of application scope + * attributes.

+ */ + private Map applicationScope = null; + + /** + *

The lazily instantiated Map of context initialization + * parameters.

+ */ + private Map initParam = null; + + /** + * Creates a new instance of ServletTilesApplicationContext. + * + * @param servletContext The servlet context to use. + */ + public ServletApplicationContext(ServletContext servletContext) { + this.servletContext = servletContext; + } + + /** {@inheritDoc} */ + public Object getContext() { + return servletContext; + } + + /** {@inheritDoc} */ + public Map getApplicationScope() { + + if ((applicationScope == null) && (servletContext != null)) { + applicationScope = new ScopeMap(new ApplicationScopeExtractor(servletContext)); + } + return (applicationScope); + + } + + /** {@inheritDoc} */ + public Map getInitParams() { + + if ((initParam == null) && (servletContext != null)) { + initParam = new ReadOnlyEnumerationMap<>(new InitParameterExtractor(servletContext)); + } + return (initParam); + + } + + /** {@inheritDoc} */ + public ApplicationResource getResource(String localePath) { + try { + URL url = servletContext.getResource(localePath); + if (url != null) { + return new URLApplicationResource(localePath, url); + } else { + return null; + } + } catch (MalformedURLException e) { + return null; + } + } + + /** {@inheritDoc} */ + public ApplicationResource getResource(ApplicationResource base, Locale locale) { + try { + URL url = servletContext.getResource(base.getLocalePath(locale)); + if (url != null) { + return new URLApplicationResource(base.getPath(), locale, url); + } else { + return null; + } + } catch (MalformedURLException e) { + return null; + } + } + + /** {@inheritDoc} */ + public Collection getResources(String path) { + ArrayList resources = new ArrayList<>(); + resources.add(getResource(path)); + return resources; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletRequest.java new file mode 100644 index 0000000000..a21a025d4d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletRequest.java @@ -0,0 +1,343 @@ +/* + * 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.apache.tiles.request.servlet; + +import org.apache.tiles.request.AbstractClientRequest; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.attribute.Addable; +import org.apache.tiles.request.collection.HeaderValuesMap; +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.servlet.extractor.HeaderExtractor; +import org.apache.tiles.request.servlet.extractor.ParameterExtractor; +import org.apache.tiles.request.servlet.extractor.RequestScopeExtractor; +import org.apache.tiles.request.servlet.extractor.SessionScopeExtractor; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * Servlet-based implementation of the TilesApplicationContext interface. + */ +public class ServletRequest extends AbstractClientRequest { + + /** + * The native available scopes: request, session and application. + */ + private static final List SCOPES = Collections.unmodifiableList(Arrays.asList(REQUEST_SCOPE, "session", APPLICATION_SCOPE)); + + /** + * The request object to use. + */ + private final HttpServletRequest request; + + /** + * The response object to use. + */ + private final HttpServletResponse response; + + /** + * The response output stream, lazily initialized. + */ + private OutputStream outputStream; + + /** + * The response writer, lazily initialized. + */ + private PrintWriter writer; + + /** + *

The lazily instantiated Map of header name-value + * combinations (immutable).

+ */ + private Map header = null; + + /** + *

The lazily instantiated Map of header name-value + * combinations (write-only).

+ */ + private Addable responseHeaders = null; + + + /** + *

The lazily instantiated Map of header name-values + * combinations (immutable).

+ */ + private Map headerValues = null; + + + /** + *

The lazily instantiated Map of request + * parameter name-value.

+ */ + private Map param = null; + + + /** + *

The lazily instantiated Map of request scope + * attributes.

+ */ + private Map requestScope = null; + + /** + *

The lazily instantiated Map of session scope + * attributes.

+ */ + private Map sessionScope = null; + + + /** + * Creates a new instance of ServletTilesRequestContext. + * + * @param applicationContext The application context. + * @param request The request object. + * @param response The response object. + */ + public ServletRequest(ApplicationContext applicationContext, HttpServletRequest request, HttpServletResponse response) { + super(applicationContext); + this.request = request; + this.response = response; + } + + /** + * {@inheritDoc} + */ + public Map getHeader() { + + if ((header == null) && (request != null)) { + header = new ReadOnlyEnumerationMap<>(new HeaderExtractor(request, null)); + } + return (header); + + } + + /** + * {@inheritDoc} + */ + public Addable getResponseHeaders() { + + if ((responseHeaders == null) && (response != null)) { + responseHeaders = new HeaderExtractor(null, response); + } + return (responseHeaders); + + } + + /** + * {@inheritDoc} + */ + public Map getHeaderValues() { + + if ((headerValues == null) && (request != null)) { + headerValues = new HeaderValuesMap(new HeaderExtractor(request, response)); + } + return (headerValues); + + } + + + /** + * {@inheritDoc} + */ + public Map getParam() { + + if ((param == null) && (request != null)) { + param = new ReadOnlyEnumerationMap<>(new ParameterExtractor(request)); + } + return (param); + + } + + + /** + * {@inheritDoc} + */ + public Map getParamValues() { + return request.getParameterMap(); + } + + @Override + public Map getContext(String scope) { + if (REQUEST_SCOPE.equals(scope)) { + return getRequestScope(); + } else if ("session".equals(scope)) { + return getSessionScope(); + } else if (APPLICATION_SCOPE.equals(scope)) { + return getApplicationScope(); + } + throw new IllegalArgumentException(scope + " does not exist. Call getAvailableScopes() first to check."); + } + + /** + * {@inheritDoc} + */ + public Map getRequestScope() { + + if ((requestScope == null) && (request != null)) { + requestScope = new ScopeMap(new RequestScopeExtractor(request)); + } + return (requestScope); + + } + + + /** + * {@inheritDoc} + */ + public Map getSessionScope() { + + if ((sessionScope == null) && (request != null)) { + sessionScope = new ScopeMap(new SessionScopeExtractor(request)); + } + return (sessionScope); + + } + + @Override + public List getAvailableScopes() { + return SCOPES; + } + + /** + * {@inheritDoc} + */ + public void doForward(String path) throws IOException { + if (response.isCommitted()) { + doInclude(path); + } else { + forward(path); + } + } + + + /** + * {@inheritDoc} + */ + public void doInclude(String path) throws IOException { + RequestDispatcher rd = request.getRequestDispatcher(path); + + if (rd == null) { + throw new IOException("No request dispatcher returned for path '" + + path + "'"); + } + + try { + rd.include(request, response); + } catch (ServletException ex) { + throw ServletUtil.wrapServletException(ex, "ServletException including path '" + + path + "'."); + } + } + + /** + * Forwards to a path. + * + * @param path The path to forward to. + * @throws IOException If something goes wrong during the operation. + */ + private void forward(String path) throws IOException { + RequestDispatcher rd = request.getRequestDispatcher(path); + + if (rd == null) { + throw new IOException("No request dispatcher returned for path '" + + path + "'"); + } + + try { + rd.forward(request, response); + } catch (ServletException ex) { + throw ServletUtil.wrapServletException(ex, "ServletException including path '" + + path + "'."); + } + } + + /** + * {@inheritDoc} + */ + public OutputStream getOutputStream() throws IOException { + if (outputStream == null) { + outputStream = response.getOutputStream(); + } + return outputStream; + } + + /** + * {@inheritDoc} + */ + public Writer getWriter() throws IOException { + return getPrintWriter(); + } + + /** + * {@inheritDoc} + */ + public PrintWriter getPrintWriter() throws IOException { + if (writer == null) { + writer = response.getWriter(); + } + return writer; + } + + /** + * {@inheritDoc} + */ + public boolean isResponseCommitted() { + return response.isCommitted(); + } + + /** + * {@inheritDoc} + */ + public void setContentType(String contentType) { + response.setContentType(contentType); + } + + /** + * {@inheritDoc} + */ + public Locale getRequestLocale() { + return request.getLocale(); + } + + public HttpServletRequest getRequest() { + return request; + } + + public HttpServletResponse getResponse() { + return response; + } + + /** + * {@inheritDoc} + */ + public boolean isUserInRole(String role) { + return request.isUserInRole(role); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletUtil.java new file mode 100644 index 0000000000..0646774b08 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletUtil.java @@ -0,0 +1,117 @@ +/* + * 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.apache.tiles.request.servlet; + +import org.apache.tiles.request.ApplicationAccess; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.RequestWrapper; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import java.io.IOException; + +/** + * Utilities for Tiles request servlet support. + */ +public final class ServletUtil { + + /** + * Constructor. + */ + private ServletUtil() { + } + + /** + * Wraps a ServletException to create an IOException with the root cause if present. + * + * @param ex The exception to wrap. + * @param message The message of the exception. + * @return The wrapped exception. + */ + public static IOException wrapServletException(ServletException ex, + String message) { + IOException retValue; + Throwable rootCause = ex.getRootCause(); + if (rootCause != null) { + // Replace the ServletException with an IOException, with the root + // cause of the first as the cause of the latter. + retValue = new IOException(message, rootCause); + } else { + retValue = new IOException(message, ex); + } + + return retValue; + } + + /** + * Returns the application context getting it from the servlet context. It must be + * first saved creating a {@link ServletApplicationContext} and using + * {@link ApplicationAccess#register(ApplicationContext)}. + * + * @param servletContext The servlet context. + * @return The application context, if found, null otherwise. + */ + public static ApplicationContext getApplicationContext(ServletContext servletContext) { + return (ApplicationContext) servletContext + .getAttribute(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE); + } + + /** + * Opens a TilesRequestContext until it finds a ServletTilesRequestContext. + * + * @param request The request to open. + * @return The servlet-based request context. + * @throws NotAServletEnvironmentException If a servlet-based request + * context could not be found. + */ + public static ServletRequest getServletRequest(Request request) { + Request currentRequest = request; + while (true) { + if (currentRequest == null) { + throw new NotAServletEnvironmentException("Last Tiles request context is null"); + } + + if (currentRequest instanceof ServletRequest) { + return (ServletRequest) currentRequest; + } + if (!(currentRequest instanceof RequestWrapper)) { + throw new NotAServletEnvironmentException("Not a Servlet environment, not supported"); + } + currentRequest = ((RequestWrapper) currentRequest).getWrappedRequest(); + } + } + + /** + * Gets a servlet context from a TilesApplicationContext. + * + * @param applicationContext The application context to analyze. + * @return The servlet context. + * @throws NotAServletEnvironmentException If the application context is not + * servlet-based. + */ + public static ServletContext getServletContext(ApplicationContext applicationContext) { + if (applicationContext instanceof ServletApplicationContext) { + return (ServletContext) applicationContext.getContext(); + } + + throw new NotAServletEnvironmentException("Not a Servlet-based environment"); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractor.java new file mode 100644 index 0000000000..52af00a9c5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractor.java @@ -0,0 +1,64 @@ +/* + * 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.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.servlet.ServletContext; +import java.util.Enumeration; + +/** + * Extract attributes from application scope. + */ +public class ApplicationScopeExtractor implements AttributeExtractor { + + /** + * The servlet context. + */ + private final ServletContext context; + + /** + * Constructor. + * + * @param context The servlet context. + */ + public ApplicationScopeExtractor(ServletContext context) { + this.context = context; + } + + @Override + public void setValue(String name, Object value) { + context.setAttribute(name, value); + } + + @Override + public void removeValue(String name) { + context.removeAttribute(name); + } + + @Override + public Enumeration getKeys() { + return context.getAttributeNames(); + } + + @Override + public Object getValue(String key) { + return context.getAttribute(key); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/HeaderExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/HeaderExtractor.java new file mode 100644 index 0000000000..e7c3662381 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/HeaderExtractor.java @@ -0,0 +1,72 @@ +/* + * 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.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Enumeration; + +/** + * Extract header values from an HTTP request. + */ +public class HeaderExtractor implements EnumeratedValuesExtractor { + + /** + * The request. + */ + private final HttpServletRequest request; + + /** + * The response. + */ + private final HttpServletResponse response; + + /** + * Constructor. + * + * @param request The request. + * @param response The response. + */ + public HeaderExtractor(HttpServletRequest request, HttpServletResponse response) { + this.request = request; + this.response = response; + } + + @Override + public Enumeration getKeys() { + return request.getHeaderNames(); + } + + @Override + public String getValue(String key) { + return request.getHeader(key); + } + + @Override + public Enumeration getValues(String key) { + return request.getHeaders(key); + } + + @Override + public void setValue(String key, String value) { + response.setHeader(key, value); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractor.java new file mode 100644 index 0000000000..6c67aaed9c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractor.java @@ -0,0 +1,55 @@ +/* + * 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.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.HasKeys; + +import javax.servlet.ServletContext; +import java.util.Enumeration; + +/** + * Extract initialization parameters from the servlet context. + */ +public class InitParameterExtractor implements HasKeys { + + /** + * The servlet context. + */ + private final ServletContext context; + + /** + * Constructor. + * + * @param context The servlet context. + */ + public InitParameterExtractor(ServletContext context) { + this.context = context; + } + + @Override + public Enumeration getKeys() { + return context.getInitParameterNames(); + } + + @Override + public String getValue(String key) { + return context.getInitParameter(key); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ParameterExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ParameterExtractor.java new file mode 100644 index 0000000000..6925d253f9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ParameterExtractor.java @@ -0,0 +1,54 @@ +/* + * 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.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.HasKeys; + +import javax.servlet.http.HttpServletRequest; +import java.util.Enumeration; + +/** + * Extract parameters from the request. + */ +public class ParameterExtractor implements HasKeys { + + /** + * The servlet request. + */ + private final HttpServletRequest request; + + /** + * Constructor. + * + * @param request The servlet request. + */ + public ParameterExtractor(HttpServletRequest request) { + this.request = request; + } + + @Override + public Enumeration getKeys() { + return request.getParameterNames(); + } + + @Override + public String getValue(String key) { + return request.getParameter(key); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractor.java new file mode 100644 index 0000000000..8bb3682e8d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractor.java @@ -0,0 +1,64 @@ +/* + * 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.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.servlet.http.HttpServletRequest; +import java.util.Enumeration; + +/** + * Extracts attributes from request scope. + */ +public class RequestScopeExtractor implements AttributeExtractor { + + /** + * The servlet request. + */ + private final HttpServletRequest request; + + /** + * Constructor. + * + * @param request The servlet request. + */ + public RequestScopeExtractor(HttpServletRequest request) { + this.request = request; + } + + @Override + public void setValue(String name, Object value) { + request.setAttribute(name, value); + } + + @Override + public void removeValue(String name) { + request.removeAttribute(name); + } + + @Override + public Enumeration getKeys() { + return request.getAttributeNames(); + } + + @Override + public Object getValue(String key) { + return request.getAttribute(key); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractor.java new file mode 100644 index 0000000000..3753d9f2b4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractor.java @@ -0,0 +1,77 @@ +/* + * 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.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.Collections; +import java.util.Enumeration; + +/** + * Extract attributes from session scope. + */ +public class SessionScopeExtractor implements AttributeExtractor { + + /** + * The servlet request. + */ + private final HttpServletRequest request; + + /** + * Constructor. + * + * @param request The servlet request. + */ + public SessionScopeExtractor(HttpServletRequest request) { + this.request = request; + } + + @Override + public void setValue(String name, Object value) { + request.getSession().setAttribute(name, value); + } + + @Override + public void removeValue(String name) { + HttpSession session = request.getSession(false); + if (session != null) { + session.removeAttribute(name); + } + } + + @Override + public Enumeration getKeys() { + HttpSession session = request.getSession(false); + if (session != null) { + return session.getAttributeNames(); + } + return Collections.enumeration(Collections.emptySet()); + } + + @Override + public Object getValue(String key) { + HttpSession session = request.getSession(false); + if (session != null) { + return session.getAttribute(key); + } + return null; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/package-info.java new file mode 100644 index 0000000000..0df9334396 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Extractors to get attributes and other info from servlet requests and contexts. + */ +package org.apache.tiles.request.servlet.extractor; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/package-info.java new file mode 100644 index 0000000000..331e1f1fc1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Tiles request support for Servlet technology. + */ +package org.apache.tiles.request.servlet; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityRequest.java new file mode 100644 index 0000000000..328d67c9e6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityRequest.java @@ -0,0 +1,169 @@ +/* + * 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.apache.tiles.request.velocity; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tiles.request.AbstractViewRequest; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.DispatchRequest; +import org.apache.tiles.request.servlet.ExternalWriterHttpServletResponse; +import org.apache.tiles.request.servlet.ServletRequest; +import org.apache.tiles.request.servlet.ServletUtil; +import org.apache.velocity.context.Context; + +/** + * The implementation of the Tiles request context specific for Velocity. + */ +public class VelocityRequest extends AbstractViewRequest { + + /** + * The native available scopes, in fact only "page". + */ + private final List scopes; + + /** + * The Velocity current context. + */ + private final Context ctx; + + /** + * The writer to use to render the response. It may be null, if not necessary. + */ + private Writer writer; + + /** + * The map of the page scope. + */ + private Map pageScope; + + /** + * Factory method to create a Velocity request. + * + * @param applicationContext The application context. + * @param request The request. + * @param response The response. + * @param velocityContext The Velocity context. + * @param writer The writer to write into. + * @return The request. + */ + public static VelocityRequest createVelocityRequest(ApplicationContext applicationContext, + HttpServletRequest request, HttpServletResponse response, Context velocityContext, Writer writer) { + DispatchRequest servletRequest = new ServletRequest(applicationContext, request, response); + VelocityRequest velocityRequest = new VelocityRequest(servletRequest, velocityContext, writer); + return velocityRequest; + } + + /** + * Constructor. + * + * @param enclosedRequest The request that exposes non-Velocity specific + * properties + * @param ctx The Velocity current context. + * @param writer The writer to use to render the response. It may be + * null, if not necessary. + */ + public VelocityRequest(DispatchRequest enclosedRequest, Context ctx, Writer writer) { + super(enclosedRequest); + List scopes = new ArrayList(); + scopes.addAll(enclosedRequest.getAvailableScopes()); + scopes.add("page"); + this.scopes = Collections.unmodifiableList(scopes); + this.ctx = ctx; + this.writer = writer; + } + + @Override + public List getAvailableScopes() { + return scopes; + } + + /** {@inheritDoc} */ + @Override + protected void doInclude(String path) throws IOException { + ServletRequest servletRequest = org.apache.tiles.request.servlet.ServletUtil.getServletRequest(this); + HttpServletRequest request = servletRequest.getRequest(); + HttpServletResponse response = servletRequest.getResponse(); + RequestDispatcher rd = request.getRequestDispatcher(path); + + if (rd == null) { + throw new IOException("No request dispatcher returned for path '" + path + "'"); + } + + PrintWriter printWriter = getPrintWriter(); + try { + rd.include(request, new ExternalWriterHttpServletResponse(response, printWriter)); + } catch (ServletException ex) { + throw ServletUtil.wrapServletException(ex, "ServletException including path '" + path + "'."); + } + } + + /** {@inheritDoc} */ + @Override + public PrintWriter getPrintWriter() { + if (writer == null) { + throw new IllegalStateException( + "A writer-less Tiles request has been created, cannot return a PrintWriter"); + } + if (writer instanceof PrintWriter) { + return (PrintWriter) writer; + } + return new PrintWriter(writer); + } + + /** {@inheritDoc} */ + @Override + public Writer getWriter() { + if (writer == null) { + throw new IllegalStateException( + "A writer-less Tiles request has been created, cannot return a PrintWriter"); + } + return writer; + } + + /** + * Returns the page scope. + * + * @return The page scope. + */ + public Map getPageScope() { + if (pageScope == null) { + pageScope = new VelocityScopeMap(ctx); + } + return pageScope; + } + + @Override + public Map getContext(String scope) { + return "page".equals(scope) ? getPageScope() : super.getContext(scope); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityScopeMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityScopeMap.java new file mode 100644 index 0000000000..36e7c21be3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityScopeMap.java @@ -0,0 +1,87 @@ +/* + * 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.apache.tiles.request.velocity; + +import static org.apache.tiles.request.collection.CollectionUtil.key; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.velocity.extractor.VelocityScopeExtractor; +import org.apache.velocity.context.Context; + +/** + *

+ * Private implementation of Map for servlet request attributes. + *

+ * + */ + +final class VelocityScopeMap extends ScopeMap { + + /** + * The request object to use. + */ + private Context request = null; + + /** + * Constructor. + * + * @param request The request object to use. + */ + public VelocityScopeMap(Context request) { + super(new VelocityScopeExtractor(request)); + this.request = request; + } + + @Override + public Object remove(Object key) { + return request.remove(key(key)); + } + + @Override + public Object put(String key, Object value) { + return request.put(key, value); + } + + /** {@inheritDoc} */ + public boolean containsKey(Object key) { + return request.containsKey(key(key)); + } + + /** {@inheritDoc} */ + public boolean isEmpty() { + return size() < 1; + } + + /** {@inheritDoc} */ + public Set keySet() { + Set set = new HashSet(); + for (Object key : request.getKeys()) { + set.add((String) key); + } + return (set); + } + + /** {@inheritDoc} */ + public int size() { + return request.getKeys().length; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntime.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntime.java new file mode 100644 index 0000000000..32e00e745d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntime.java @@ -0,0 +1,102 @@ +/* + * 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.apache.tiles.request.velocity.autotag; + +import java.io.Writer; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.servlet.ServletUtil; +import org.apache.tiles.request.velocity.VelocityRequest; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.ASTBlock; +import org.apache.velocity.runtime.parser.node.ASTMap; +import org.apache.velocity.runtime.parser.node.Node; +import org.apache.velocity.tools.view.ViewContext; + +/** + * A Runtime for implementing Velocity Directives. + */ +public class VelocityAutotagRuntime extends Directive implements AutotagRuntime { + private InternalContextAdapter context; + private Writer writer; + private Node node; + private Map params; + + @Override + public Request createRequest() { + ViewContext viewContext = (ViewContext) context.getInternalUserContext(); + HttpServletRequest request = viewContext.getRequest(); + HttpServletResponse response = viewContext.getResponse(); + ServletContext servletContext = viewContext.getServletContext(); + return VelocityRequest.createVelocityRequest(ServletUtil.getApplicationContext(servletContext), request, + response, context, writer); + } + + /** {@inheritDoc} */ + @Override + public ModelBody createModelBody() { + ASTBlock block = (ASTBlock) node.jjtGetChild(1); + return new VelocityModelBody(context, block, writer); + } + + /** {@inheritDoc} */ + @Override + @SuppressWarnings("unchecked") + public T getParameter(String name, Class type, T defaultValue) { + if (params == null) { + ASTMap astMap = (ASTMap) node.jjtGetChild(0); + params = (Map) astMap.value(context); + } + T result = (T) params.get(name); + if (result == null) { + result = defaultValue; + } + return result; + } + + /** {@inheritDoc} */ + @Override + public String getName() { + return null; + } + + /** {@inheritDoc} */ + @Override + public int getType() { + return 0; + } + + /** {@inheritDoc} */ + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) { + this.context = context; + this.writer = writer; + this.node = node; + return false; + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityModelBody.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityModelBody.java new file mode 100644 index 0000000000..1022175f60 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityModelBody.java @@ -0,0 +1,61 @@ +/* + * 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.apache.tiles.request.velocity.autotag; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.AbstractModelBody; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.parser.node.ASTBlock; + +/** + * Body abstraction for a Velocity directive body. + */ +public class VelocityModelBody extends AbstractModelBody { + + /** + * The real body. + */ + private ASTBlock body; + + /** + * The Velocity context. + */ + private InternalContextAdapter context; + + /** + * Constructor. + * + * @param context The Velocity context. + * @param body The real body. + * @param defaultWriter The default writer. + */ + public VelocityModelBody(InternalContextAdapter context, ASTBlock body, Writer defaultWriter) { + super(defaultWriter); + this.context = context; + this.body = body; + } + + @Override + public void evaluate(Writer writer) throws IOException { + body.render(context, writer); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityUtil.java new file mode 100644 index 0000000000..bca1938366 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityUtil.java @@ -0,0 +1,67 @@ +/* + * 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.apache.tiles.request.velocity.autotag; + +import java.util.Map; + +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.parser.node.ASTMap; +import org.apache.velocity.runtime.parser.node.Node; + +/** + * Utilities for Velocity usage in Tiles. + */ +public final class VelocityUtil { + + /** + * Private constructor to avoid instantiation. + */ + private VelocityUtil() { + } + + /** + * Extracts the parameters from the directives, by getting the child at position + * 0 supposing it is a map. + * + * @param context The Velocity context. + * @param node The node to use. + * @return The extracted parameters. + */ + @SuppressWarnings("unchecked") + public static Map getParameters(InternalContextAdapter context, Node node) { + ASTMap astMap = (ASTMap) node.jjtGetChild(0); + Map params = (Map) astMap.value(context); + return params; + } + + /** + * Returns the "value" parameter if it is not null, otherwise returns + * "defaultValue". + * + * @param value The value to return, if it is not null. + * @param defaultValue The value to return, if value is null. + * @return The value, defaulted if necessary. + */ + public static Object getObject(Object value, Object defaultValue) { + if (value == null) { + value = defaultValue; + } + return value; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/package-info.java new file mode 100644 index 0000000000..456abb2380 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Runtime part of Autotag support for Velocity. + */ +package org.apache.tiles.request.velocity.autotag; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractor.java new file mode 100644 index 0000000000..1481c3844c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractor.java @@ -0,0 +1,99 @@ +/* + * 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.apache.tiles.request.velocity.extractor; + +import java.util.Enumeration; + +import org.apache.tiles.request.attribute.AttributeExtractor; +import org.apache.velocity.context.Context; + +/** + * Extracts attributes from Velocity context.. + */ +public class VelocityScopeExtractor implements AttributeExtractor { + + /** + * The Velocity context. + */ + private Context context; + + /** + * Constructor. + * + * @param context The Velocity context. + */ + public VelocityScopeExtractor(Context context) { + this.context = context; + } + + @Override + public void removeValue(String name) { + context.remove(name); + } + + @Override + public Enumeration getKeys() { + return new KeyEnumeration(context.getKeys()); + } + + @Override + public Object getValue(String key) { + return context.get(key); + } + + @Override + public void setValue(String key, Object value) { + context.put(key, value); + } + + /** + * Enumerates an array. + */ + private static class KeyEnumeration implements Enumeration { + + /** + * The current index. + */ + private int index = 0; + + /** + * The array to enumerate. + */ + private Object[] keys; + + /** + * Constructor. + * + * @param keys The array to enumerate. + */ + public KeyEnumeration(Object[] keys) { + this.keys = keys; + } + + @Override + public boolean hasMoreElements() { + return index < keys.length; + } + + @Override + public String nextElement() { + return (String) keys[index++]; + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/package-info.java new file mode 100644 index 0000000000..d0c099c580 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Extractors to get info about Velocity-specific objects. + */ +package org.apache.tiles.request.velocity.extractor; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/package-info.java new file mode 100644 index 0000000000..2a3e45f0a5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Tiles request support for Velocity. + */ +package org.apache.tiles.request.velocity; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfig.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfig.java new file mode 100644 index 0000000000..9810ce3d98 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfig.java @@ -0,0 +1,77 @@ +/* + * 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.apache.tiles.request.velocity.render; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletContext; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.servlet.ServletUtil; +import org.apache.velocity.tools.view.JeeConfig; + +/** + * Implements JeeConfig to use parameters set through + */ +public class ApplicationContextJeeConfig implements JeeConfig { + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * The initialization parameters for VelocityView. + */ + private Map params; + + /** + * Constructor. + * + * @param applicationContext The application context. + * @param params Configuration parameters. + */ + public ApplicationContextJeeConfig(ApplicationContext applicationContext, Map params) { + this.applicationContext = applicationContext; + this.params = new HashMap(params); + } + + public String getInitParameter(String name) { + return params.get(name); + } + + public String findInitParameter(String key) { + return params.get(key); + } + + public Enumeration getInitParameterNames() { + return Collections.enumeration(params.keySet()); + } + + public String getName() { + return "Application Context JEE Config"; + } + + public ServletContext getServletContext() { + return ServletUtil.getServletContext(applicationContext); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRenderer.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRenderer.java new file mode 100644 index 0000000000..780a285695 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRenderer.java @@ -0,0 +1,75 @@ +/* + * 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.apache.tiles.request.velocity.render; + +import java.io.IOException; + +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.CannotRenderException; +import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.servlet.ServletRequest; +import org.apache.tiles.request.servlet.ServletUtil; +import org.apache.velocity.Template; +import org.apache.velocity.context.Context; +import org.apache.velocity.tools.view.VelocityView; + +/** + * Attribute renderer for rendering Velocity templates as attributes. It is + * available only to Servlet-based environment. It uses VelocityView to render + * the response. To initialize it correctly, call #setParameter(String, String) + * for all the parameters that you want to set, and then call #commit(). + */ +public class VelocityRenderer implements Renderer { + + /** + * The VelocityView object to use. + */ + private VelocityView velocityView; + + /** + * Constructor. + * + * @param velocityView The Velocity view manager. + */ + public VelocityRenderer(VelocityView velocityView) { + this.velocityView = velocityView; + } + + @Override + public void render(String path, Request request) throws IOException { + if (path == null) { + throw new CannotRenderException("Cannot dispatch a null path"); + } + + ServletRequest servletRequest = ServletUtil.getServletRequest(request); + // then get a context + Context context = velocityView.createContext(servletRequest.getRequest(), servletRequest.getResponse()); + + // get the template + Template template = velocityView.getTemplate((String) path); + + // merge the template and context into the writer + velocityView.merge(template, context, request.getWriter()); + } + + public boolean isRenderable(String path, Request request) { + return path != null && path.startsWith("/") && path.endsWith(".vm"); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRendererBuilder.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRendererBuilder.java new file mode 100644 index 0000000000..6f028ea01e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRendererBuilder.java @@ -0,0 +1,91 @@ +/* + * $Id: VelocityRendererBuilder.java 1066512 2011-02-02 16:13:31Z apetrelli $ + * + * 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.apache.tiles.request.velocity.render; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.velocity.tools.view.VelocityView; + +/** + * Builds a VelocityRenderer. + */ +public final class VelocityRendererBuilder { + + /** + * The initialization parameters for VelocityView. + */ + private Map params = new HashMap(); + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * Constructor. + */ + private VelocityRendererBuilder() { + } + + /** + * Returns a new instance of the builder. + * + * @return A new builder. + */ + public static VelocityRendererBuilder createInstance() { + return new VelocityRendererBuilder(); + } + + /** + * Sets a parameter for the internal servlet. + * + * @param key The name of the parameter. + * @param value The value of the parameter. + * @return This builder. + */ + public VelocityRendererBuilder setParameter(String key, String value) { + params.put(key, value); + return this; + } + + /** + * Sets the application context. + * + * @param applicationContext The application context. + * @return This builder. + */ + public VelocityRendererBuilder setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + return this; + } + + /** + * Creates the Velocity renderer. + * + * @return The Velocity renderer. + */ + public VelocityRenderer build() { + VelocityView velocityView = new VelocityView(new ApplicationContextJeeConfig(applicationContext, params)); + return new VelocityRenderer(velocityView); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/package-info.java new file mode 100644 index 0000000000..bb0b2d39d1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Renderering support for Velocity. + */ +package org.apache.tiles.request.velocity.render; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/AddAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/AddAttributeModel.java new file mode 100644 index 0000000000..2ccb42348d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/AddAttributeModel.java @@ -0,0 +1,124 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Add an element to the surrounding list. Equivalent to 'putAttribute', + * but for list element. + *

+ * + *

+ * Add an element to the surrounding list. This tag can only be used inside + * 'putListAttribute' or 'addListAttribute' tags. Value can come from a direct + * assignment (value="aValue") + *

+ * + * @since 2.2.0 + */ +public class AddAttributeModel { + + /** + * Executes the operation. + * + * @param value The value of the attribute. Use this parameter, or + * expression, or body. + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param type The type (renderer) of the attribute. + * @param request The request. + * @param modelBody The body. + * @throws IOException If the body cannot be correctly evaluated. + * @since 2.2.0 + */ + public void execute( + Object value, + String expression, + String role, + String type, + Request request, + ModelBody modelBody + ) throws IOException { + Attribute attribute = new Attribute(); + Deque composeStack = ComposeStackUtil.getComposeStack(request); + composeStack.push(attribute); + String body = modelBody.evaluateAsString(); + attribute = (Attribute) composeStack.pop(); + addAttributeToList(attribute, composeStack, value, expression, body, role, type); + } + + /** + * Adds the attribute to the containing list attribute. + * + * @param attribute The attribute to add to the list attribute. + * @param composeStack The composing stack. + * @param value The value of the attribute. Use this parameter, or + * expression, or body. + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + * @param body The body of the tag. Use this parameter, or value, or + * expression. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param type The type (renderer) of the attribute. + * @since 2.2.0 + */ + private void addAttributeToList( + Attribute attribute, + Deque composeStack, + Object value, + String expression, + String body, + String role, + String type + ) { + ListAttribute listAttribute = (ListAttribute) ComposeStackUtil.findAncestorWithClass(composeStack, ListAttribute.class); + + if (listAttribute == null) { + throw new NullPointerException("There is no ListAttribute in the stack"); + } + if (value != null) { + attribute.setValue(value); + } else if (attribute.getValue() == null && body != null) { + attribute.setValue(body); + } + if (expression != null) { + attribute.setExpressionObject(Expression + .createExpressionFromDescribedExpression(expression)); + } + if (role != null) { + attribute.setRole(role); + } + if (type != null) { + attribute.setRenderer(type); + } + listAttribute.add(attribute); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/AddListAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/AddListAttributeModel.java new file mode 100644 index 0000000000..09e7433c17 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/AddListAttributeModel.java @@ -0,0 +1,60 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Declare a list that will be pass as an attribute. + *

+ *

+ * Declare a list that will be pass as an attribute . List elements are added + * using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used + * inside 'insertTemplate', 'insertDefinition' or 'definition' tag. + *

+ * @since 2.2.0 + */ +public class AddListAttributeModel { + + /** + * Executes the model. + * + * @param role The comma-separated list of roles that can use the list attribute. + * @param request The request. + * @param modelBody The body. + * @throws IOException If the body cannot be evaluated. + */ + public void execute(String role, Request request, ModelBody modelBody) throws IOException { + Deque composeStack = ComposeStackUtil.getComposeStack(request); + ListAttribute listAttribute = new ListAttribute(); + listAttribute.setRole(role); + composeStack.push(listAttribute); + modelBody.evaluateWithoutWriting(); + listAttribute = (ListAttribute) composeStack.pop(); + ListAttribute parent = (ListAttribute) composeStack.peek(); + assert parent != null; + parent.add(listAttribute); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/AttributeResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/template/AttributeResolver.java new file mode 100644 index 0000000000..786e258f8f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/AttributeResolver.java @@ -0,0 +1,58 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; + +/** + * Resolves an attribute, depending on the given parameters. + * + * @since 2.2.0 + */ +public interface AttributeResolver { + + /** + * Computes the attribute. + * + * @param container The Tiles container to use. + * @param attribute The attribute to return immediately, if not null. + * @param name The name of the attribute. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param ignore If true if the computed attribute is null, this problem will be ignored. + * @param defaultValue The default value of the attribute. To use only if the attribute was not computed. + * @param defaultValueRole The default comma-separated list of roles. To use only if the attribute was not computed. + * @param defaultValueType The default type of the attribute. To use only if the attribute was not computed. + * @param request TODO + * @return The computed attribute. + * @since 2.2.0 + */ + Attribute computeAttribute( + TilesContainer container, + Attribute attribute, + String name, + String role, + boolean ignore, + Object defaultValue, + String defaultValueRole, + String defaultValueType, + Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/ComposeStackUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/template/ComposeStackUtil.java new file mode 100644 index 0000000000..0b255e58e6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/ComposeStackUtil.java @@ -0,0 +1,83 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.request.Request; + +import java.util.Deque; +import java.util.LinkedList; +import java.util.Map; + +/** + * Utilities to work with compose stacks. + * + * @since 3.0.0 + */ +public final class ComposeStackUtil { + + /** + * The name of the attribute that holds to compose stack. + */ + public static final String COMPOSE_STACK_ATTRIBUTE_NAME = "org.apache.tiles.template.COMPOSE_STACK"; + + /** + * Private constructor to avoid instantiation. + */ + private ComposeStackUtil() { + + } + + /** + * Finds the first ancestor in the stack, that is assignable to the given class. + * + * @param composeStack To compose stack to evaluate. + * @param clazz The class to check. + * @return The first ancestor that is assignable to the class, or null if not found. + * @since 3.0.0 + */ + public static Object findAncestorWithClass(Deque composeStack, Class clazz) { + for (Object obj : composeStack) { + if (clazz.isAssignableFrom(obj.getClass())) { + return obj; + } + } + + return null; + } + + /** + * Returns the current compose stack, or creates a new one if not present. + * + * @param request The request. + * @return The compose stack. + * @since 3.0.0 + */ + @SuppressWarnings("unchecked") + public static Deque getComposeStack(Request request) { + Map requestScope = request.getContext("request"); + Deque composeStack = (Deque) requestScope + .get(COMPOSE_STACK_ATTRIBUTE_NAME); + if (composeStack == null) { + composeStack = new LinkedList<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + } + return composeStack; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/DefaultAttributeResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/template/DefaultAttributeResolver.java new file mode 100644 index 0000000000..c1ee10ae1e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/DefaultAttributeResolver.java @@ -0,0 +1,85 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; + +/** + * The default implementation of AttributeResolver. + * + * @since 2.2.0 + */ +public class DefaultAttributeResolver implements AttributeResolver { + + /** + * {@inheritDoc} + */ + public Attribute computeAttribute( + TilesContainer container, + Attribute attribute, + String name, + String role, + boolean ignore, + Object defaultValue, + String defaultValueRole, + String defaultValueType, + Request request + ) { + if (attribute == null) { + AttributeContext evaluatingContext = container + .getAttributeContext(request); + attribute = evaluatingContext.getAttribute(name); + if (attribute == null) { + attribute = computeDefaultAttribute(defaultValue, + defaultValueRole, defaultValueType); + if (attribute == null && !ignore) { + throw new NoSuchAttributeException("Attribute '" + name + "' not found."); + } + } + } + if (attribute != null && role != null && !"".equals(role.trim())) { + attribute = new Attribute(attribute); + attribute.setRole(role); + } + return attribute; + } + + /** + * Computes the default attribute. + * + * @param defaultValue The default value of the attribute. + * @param defaultValueRole The default role of tha attribute. + * @param defaultValueType The default type of the attribute. + * @return The default attribute. + */ + private Attribute computeDefaultAttribute(Object defaultValue, String defaultValueRole, String defaultValueType) { + Attribute attribute = null; + if (defaultValue != null) { + if (defaultValue instanceof Attribute) { + attribute = (Attribute) defaultValue; + } else if (defaultValue instanceof String) { + attribute = new Attribute(defaultValue, null, defaultValueRole, defaultValueType); + } + } + return attribute; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/DefinitionModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/DefinitionModel.java new file mode 100644 index 0000000000..7302d2ea14 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/DefinitionModel.java @@ -0,0 +1,139 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.api.mgmt.MutableTilesContainer; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Create a definition at runtime. + *

+ *

+ * Create a new definition at runtime. Newly created definition will be + * available across the entire request. + *

+ * + * @since 2.2.0 + */ +public class DefinitionModel { + + /** + * Executes the operation. + * + * @param name The name of the definition to create. If not specified, an + * anonymous definition will be created. + * @param template The template of this definition. + * @param role A comma-separated list of roles. If present, the definition + * will be rendered only if the current user belongs to one of the roles. + * @param extendsParam The definition name that this definition extends. + * @param preparer The preparer to use to invoke before the definition is + * rendered. + * @param request The request. + * @param modelBody The body. + * @throws IOException If something goes wrong. + * @since 2.2.0 + */ + public void execute( + String name, + String template, + String role, + @Parameter(name = "extends") String extendsParam, + String preparer, + Request request, + ModelBody modelBody + ) throws IOException { + Deque composeStack = ComposeStackUtil.getComposeStack(request); + Definition definition = createDefinition(name, template, role, extendsParam, preparer); + composeStack.push(definition); + modelBody.evaluateWithoutWriting(); + MutableTilesContainer container = (MutableTilesContainer) TilesAccess.getCurrentContainer(request); + definition = (Definition) composeStack.pop(); + registerDefinition(definition, container, composeStack, request); + } + + /** + * Creates the definition to store. + * + * @param name The name of the definition to create. If not specified, an + * anonymous definition will be created. + * @param template The template of this definition. + * @param role A comma-separated list of roles. If present, the definition + * will be rendered only if the current user belongs to one of the roles. + * @param extendsParam The definition name that this definition extends. + * @param preparer The preparer to use to invoke before the definition is + * rendered. + * @return The created definition. + */ + private Definition createDefinition( + String name, + String template, + String role, + String extendsParam, + String preparer + ) { + Definition definition = new Definition(); + definition.setName(name); + Attribute templateAttribute = Attribute.createTemplateAttribute(template); + templateAttribute.setRole(role); + definition.setTemplateAttribute(templateAttribute); + definition.setExtends(extendsParam); + definition.setPreparer(preparer); + return definition; + } + + /** + * Registers a definition in the container. + * + * @param definition The definition to register. + * @param container The container into which the definition will be + * registered. + * @param composeStack The compose stack, + * @param request The request. + */ + private void registerDefinition( + Definition definition, + MutableTilesContainer container, + Deque composeStack, + Request request + ) { + container.register(definition, request); + + if (composeStack.isEmpty()) { + return; + } + + Object obj = composeStack.peek(); + if (obj instanceof Attribute) { + Attribute attribute = (Attribute) obj; + attribute.setValue(definition.getName()); + if (attribute.getRenderer() == null) { + attribute.setRenderer("definition"); + } + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/GetAsStringModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/GetAsStringModel.java new file mode 100644 index 0000000000..1bf1de7424 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/GetAsStringModel.java @@ -0,0 +1,224 @@ +/* + * 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.apache.tiles.template; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.io.Writer; +import java.util.Deque; + +/** + *

+ * Render the value of the specified template attribute to the current + * Writer + *

+ * + *

+ * Retrieve the value of the specified template attribute property, and render + * it to the current Writer as a String. The usual toString() conversions is + * applied on found value. + *

+ * + * @since 2.2.0 + */ +public class GetAsStringModel { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(GetAsStringModel.class); + + /** + * The attribute resolver to use. + */ + private final AttributeResolver attributeResolver; + + /** + * Constructor that uses the defaut attribute resolver. + * + * @since 3.0.0 + */ + public GetAsStringModel() { + this(new DefaultAttributeResolver()); + } + + /** + * Constructor. + * + * @param attributeResolver The attribute resolver to use. + * @since 2.2.0 + */ + public GetAsStringModel(AttributeResolver attributeResolver) { + this.attributeResolver = attributeResolver; + } + + /** + * Executes the operation. + * + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param preparer The preparer to invoke before rendering the attribute. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param defaultValue The default value of the attribute. To use only if + * the attribute was not computed. + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + * @param defaultValueType The default type of the attribute. To use only if + * the attribute was not computed. + * @param name The name of the attribute. + * @param value The attribute to use immediately, if not null. + * @param request The request. + * @param modelBody The body. + * @throws IOException If an I/O error happens during rendering. + * @since 2.2.0 + */ + public void execute( + boolean ignore, + String preparer, + String role, + Object defaultValue, + String defaultValueRole, + String defaultValueType, + @Parameter(required = true) String name, + Attribute value, + Request request, + ModelBody modelBody + ) throws IOException { + TilesContainer container = TilesAccess.getCurrentContainer(request); + Deque composeStack = ComposeStackUtil.getComposeStack(request); + Attribute attribute = resolveAttribute( + container, + ignore, + preparer, + role, + defaultValue, + defaultValueRole, + defaultValueType, + name, + value, + request + ); + if (attribute != null) { + composeStack.push(attribute); + } + modelBody.evaluateWithoutWriting(); + container = TilesAccess.getCurrentContainer(request); + Writer writer = request.getWriter(); + if (attribute != null) { + attribute = (Attribute) composeStack.pop(); + } + renderAttribute(attribute, container, writer, ignore, request); + } + + /** + * Resolves the attribute. and starts the context. + * + * @param container The Tiles container to use. + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param preparer The preparer to invoke before rendering the attribute. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param defaultValue The default value of the attribute. To use only if + * the attribute was not computed. + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + * @param defaultValueType The default type of the attribute. To use only if + * the attribute was not computed. + * @param name The name of the attribute. + * @param value The attribute to use immediately, if not null. + * @param request The request. + * @return The resolved attribute. + */ + private Attribute resolveAttribute( + TilesContainer container, + boolean ignore, + String preparer, + String role, + Object defaultValue, + String defaultValueRole, + String defaultValueType, + String name, + Attribute value, + Request request + ) { + if (preparer != null) { + container.prepare(preparer, request); + } + Attribute attribute = attributeResolver.computeAttribute( + container, + value, + name, + role, + ignore, + defaultValue, + defaultValueRole, + defaultValueType, + request + ); + container.startContext(request); + return attribute; + } + + /** + * Renders the attribute as a string. + * + * @param attribute The attribute to use, previously resolved. + * @param container The Tiles container to use. + * @param writer The writer into which the attribute will be written. + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param request The request. + * @throws IOException If an I/O error happens during rendering. + */ + private void renderAttribute( + Attribute attribute, + TilesContainer container, + Writer writer, + boolean ignore, + Request request + ) throws IOException { + try { + if (attribute == null && ignore) { + return; + } + Object value = container.evaluate(attribute, request); + if (value != null) { + writer.write(value.toString()); + } + } catch (IOException | RuntimeException e) { + if (!ignore) { + throw e; + } else if (LOG.isDebugEnabled()) { + LOG.debug("Ignoring exception", e); + } + } finally { + container.endContext(request); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/ImportAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/ImportAttributeModel.java new file mode 100644 index 0000000000..ecf07bf7e9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/ImportAttributeModel.java @@ -0,0 +1,194 @@ +/* + * 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.apache.tiles.template; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.Request; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + *

+ * Import attribute(s) in specified context. + *

+ *

+ * Import attribute(s) to requested scope. Attribute name and scope are + * optional. If not specified, all attributes are imported in page scope. Once + * imported, an attribute can be used as any other beans from jsp contexts. + *

+ * + * @since 2.2.0 + */ +public class ImportAttributeModel { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(ImportAttributeModel.class); + + /** + * Executes the model. + * + * @param name The name of the attribute to import. If it is + * null, all the attributes will be imported. + * @param scope The scope into which the attribute(s) will be imported. If + * null, the import will go in page scope. + * @param toName The name of the attribute into which the attribute will be + * imported. To be used in conjunction to name. If + * null, the value of name will be used. + * @param ignore If true, if the attribute is not present, the + * problem will be ignored. + * @param request The request. + */ + public void execute( + String name, + String scope, + String toName, + boolean ignore, + Request request + ) { + Map attributes = getImportedAttributes(name, toName, ignore, request); + if (scope == null) { + scope = request.getAvailableScopes().get(0); + } + request.getContext(scope).putAll(attributes); + } + + /** + * Retuns a Map that contains the attributes to be imported. The importing + * code must be done by the caller. + * + * @param name The attribute to import. If null, all the attributes will be + * imported. + * @param toName The destination name of the attribute to import. Valid only + * if name is specified. + * @param ignore If true and the attribute is not found, or an + * exception happens, the problem will be ignored. + * @param request The request. + * @return A Map of the attributes to be imported: the key is the name of an + * attribute, the value is the value of that attribute. + * @since 2.2.0 + */ + private Map getImportedAttributes(String name, String toName, boolean ignore, Request request) { + TilesContainer container = TilesAccess.getCurrentContainer(request); + Map retValue = new HashMap<>(); + AttributeContext attributeContext = container.getAttributeContext(request); + // Some tags allow for unspecified attributes. This + // implies that the tag should use all the attributes. + if (name != null) { + importSingleAttribute(container, attributeContext, name, toName, ignore, retValue, request); + } else { + importAttributes(attributeContext.getCascadedAttributeNames(), container, attributeContext, retValue, ignore, request); + importAttributes(attributeContext.getLocalAttributeNames(), container, attributeContext, retValue, ignore, request); + } + return retValue; + } + + /** + * Imports a single attribute. + * + * @param container The Tiles container to use. + * @param attributeContext The context from which the attributes will be + * got. + * @param name The name of the attribute. + * @param toName The name of the destination attribute. If null, + * name will be used. + * @param ignore If true and the attribute is not found, or an + * exception happens, the problem will be ignored. + * @param attributes The map of the attributes to fill. + * @param request The request. + */ + private void importSingleAttribute( + TilesContainer container, + AttributeContext attributeContext, + String name, String toName, + boolean ignore, + Map attributes, + Request request + ) { + Attribute attr = attributeContext.getAttribute(name); + if (attr != null) { + try { + Object attributeValue = container.evaluate(attr, + request); + if (attributeValue == null) { + if (!ignore) { + throw new NoSuchAttributeException("Error importing attributes. " + "Attribute '" + name + "' has a null value "); + } + } else { + if (toName != null) { + attributes.put(toName, attributeValue); + } else { + attributes.put(name, attributeValue); + } + } + } catch (RuntimeException e) { + if (!ignore) { + throw e; + } else if (LOG.isDebugEnabled()) { + LOG.debug("Ignoring Tiles Exception", e); + } + } + } else if (!ignore) { + throw new NoSuchAttributeException("Error importing attributes. " + "Attribute '" + name + "' is null"); + } + } + + /** + * Imports all the attributes. + * + * @param names The names of the attributes to be imported. + * @param container The Tiles container to use. + * @param attributeContext The context from which the attributes will be + * got. + * @param attributes The map of the attributes to fill. + * @param ignore If true and the attribute is not found, or an + * exception happens, the problem will be ignored. + * @param request The request. + */ + private void importAttributes( + Collection names, + TilesContainer container, + AttributeContext attributeContext, + Map attributes, + boolean ignore, + Request request + ) { + if (names == null || names.isEmpty()) { + return; + } + + for (String name : names) { + if (name == null && !ignore) { + throw new NoSuchAttributeException("Error importing attributes. Attribute with null key found."); + } else if (name == null) { + continue; + } + + importSingleAttribute(container, attributeContext, name, name, ignore, attributes, request); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/InsertAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertAttributeModel.java new file mode 100644 index 0000000000..4c2ea7ef10 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertAttributeModel.java @@ -0,0 +1,204 @@ +/* + * 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.apache.tiles.template; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Inserts the value of an attribute into the page. + *

+ *

+ * This tag can be flexibly used to insert the value of an attribute into a + * page. As in other usages in Tiles, every attribute can be determined to have + * a "type", either set explicitly when it was defined, or "computed". If the + * type is not explicit, then if the attribute value is a valid definition, it + * will be inserted as such. Otherwise, if it begins with a "/" character, it + * will be treated as a "template". Finally, if it has not otherwise been + * assigned a type, it will be treated as a String and included without any + * special handling. + *

+ * + *

+ * Example : + *

+ * + *
+ * <code>
+ *           <tiles:insertAttribute name="body" />
+ *         </code>
+ * 
+ * @since 2.2.0 + */ +public class InsertAttributeModel { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(InsertAttributeModel.class); + + /** + * The attribute resolver to use. + */ + private final AttributeResolver attributeResolver; + + /** + * Constructor that uses the defaut attribute resolver. + * + * @since 3.0.0 + */ + public InsertAttributeModel() { + this(new DefaultAttributeResolver()); + } + + /** + * Constructor. + * + * @param attributeResolver The attribute resolver to use. + * @since 2.2.0 + */ + public InsertAttributeModel(AttributeResolver attributeResolver) { + this.attributeResolver = attributeResolver; + } + + /** + * Executes the operation. + * + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param preparer The preparer to invoke before rendering the attribute. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param defaultValue The default value of the attribute. To use only if + * the attribute was not computed. + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + * @param defaultValueType The default type of the attribute. To use only if + * the attribute was not computed. + * @param name The name of the attribute. + * @param value The attribute to use immediately, if not null. + * @param flush If true, the response will be flushed after the insert. + * @param request The request. + * @param modelBody The body. + * @throws IOException If an I/O error happens during rendering. + * @since 2.2.0 + */ + public void execute( + boolean ignore, + String preparer, + String role, + Object defaultValue, + String defaultValueRole, + String defaultValueType, + String name, + Attribute value, + boolean flush, + Request request, + ModelBody modelBody + ) throws IOException { + TilesContainer container = TilesAccess.getCurrentContainer(request); + Deque composeStack = ComposeStackUtil.getComposeStack(request); + Attribute attribute = resolveAttribute(container, ignore, preparer, + role, defaultValue, defaultValueRole, defaultValueType, name, + value, request); + if (attribute != null) { + composeStack.push(attribute); + } + modelBody.evaluateWithoutWriting(); + container = TilesAccess.getCurrentContainer(request); + if (attribute != null) { + attribute = (Attribute) composeStack.pop(); + } + renderAttribute(container, ignore, attribute, request); + if (flush) { + request.getWriter().flush(); + } + } + + /** + * Resolves the attribute. and starts the context. + * + * @param container The Tiles container to use. + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param preparer The preparer to invoke before rendering the attribute. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param defaultValue The default value of the attribute. To use only if + * the attribute was not computed. + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + * @param defaultValueType The default type of the attribute. To use only if + * the attribute was not computed. + * @param name The name of the attribute. + * @param value The attribute to use immediately, if not null. + * @param request The request. + * @return The resolved attribute. + */ + private Attribute resolveAttribute(TilesContainer container, + boolean ignore, String preparer, String role, Object defaultValue, + String defaultValueRole, String defaultValueType, String name, + Attribute value, Request request) { + if (preparer != null) { + container.prepare(preparer, request); + } + Attribute attribute = attributeResolver.computeAttribute(container, + value, name, role, ignore, defaultValue, defaultValueRole, + defaultValueType, request); + container.startContext(request); + return attribute; + } + + /** + * Renders the attribute as a string. + * + * @param container The Tiles container to use. + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param attribute The attribute to use, previously resolved. + * @param request The request. + * @throws IOException If an I/O error happens during rendering. + */ + private void renderAttribute(TilesContainer container, boolean ignore, + Attribute attribute, Request request) throws IOException { + try { + if (attribute == null && ignore) { + return; + } + container.render(attribute, request); + } catch (IOException | RuntimeException e) { + if (!ignore) { + throw e; + } else if (LOG.isDebugEnabled()) { + LOG.debug("Ignoring exception", e); + } + } finally { + container.endContext(request); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/InsertDefinitionModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertDefinitionModel.java new file mode 100644 index 0000000000..a34bb37602 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertDefinitionModel.java @@ -0,0 +1,147 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; + +/** + *

+ * Insert a definition. + *

+ *

+ * Insert a definition with the possibility to override and specify parameters + * (called attributes). A definition can be seen as a (partially or totally) + * filled template that can override or complete attribute values. + * <tiles:insertDefinition> allows to define these attributes + * and pass them to the inserted jsp page, called template. Attributes are + * defined using nested tag <tiles:putAttribute> or + * <tiles:putListAttribute>. + *

+ *

+ * You must specify name tag attribute, for inserting a definition + * from definitions factory. + *

+ *

+ * Example : + *

+ * + *
+ * <code>
+ *           <tiles:insertDefinition name=".my.tiles.defininition flush="true">
+ *              <tiles:putAttribute name="title" value="My first page" />
+ *              <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *              <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *              <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *              <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *           </tiles:insertDefinition>
+ *         </code>
+ * 
+ * @since 2.2.0 + */ +public class InsertDefinitionModel { + + /** + * Executes the operation. + * + * @param definitionName The name of the definition to render. + * @param template If specified, this template will be used instead of the + * one used by the definition. + * @param templateType The type of the template attribute. + * @param templateExpression The expression to evaluate to get the value of the template. + * @param role A comma-separated list of roles. If present, the definition + * will be rendered only if the current user belongs to one of the roles. + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified in the + * definition itself. + * @param flush If true, the response will be flushed after the insert. + * @param request The request. + * @param modelBody The body. + * @throws IOException If something goes wrong. + * @since 2.2.0 + */ + public void execute( + @Parameter(name = "name", required = true) String definitionName, + String template, + String templateType, + String templateExpression, + String role, + String preparer, + boolean flush, + Request request, + ModelBody modelBody + ) throws IOException { + TilesContainer container = TilesAccess.getCurrentContainer(request); + container.startContext(request); + modelBody.evaluateWithoutWriting(); + container = TilesAccess.getCurrentContainer(request); + renderDefinition(container, definitionName, template, templateType, templateExpression, role, preparer, flush, request); + } + + /** + * Renders a definition. + * + * @param container The container to use. + * @param definitionName The name of the definition to render. + * @param template If specified, this template will be used instead of the + * one used by the definition. + * @param templateType The type of the template attribute. + * @param templateExpression The expression to evaluate to get the value of the template. + * @param role A comma-separated list of roles. If present, the definition + * will be rendered only if the current user belongs to one of the roles. + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified in the + * definition itself. + * @param flush If true, the response will be flushed after the insert. + * @param request The request. + * @throws IOException If something goes wrong. + */ + private void renderDefinition( + TilesContainer container, + String definitionName, + String template, + String templateType, + String templateExpression, + String role, + String preparer, + boolean flush, + Request request + ) throws IOException { + try { + AttributeContext attributeContext = container.getAttributeContext(request); + Attribute templateAttribute = Attribute.createTemplateAttribute(template, templateExpression, templateType, role); + attributeContext.setPreparer(preparer); + attributeContext.setTemplateAttribute(templateAttribute); + container.render(definitionName, request); + if (flush) { + request.getWriter().flush(); + } + } finally { + container.endContext(request); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/InsertTemplateModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertTemplateModel.java new file mode 100644 index 0000000000..0856e24d80 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertTemplateModel.java @@ -0,0 +1,141 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; + +/** + *

+ * Insert a template. + *

+ *

+ * Insert a template with the possibility to pass parameters (called + * attributes). A template can be seen as a procedure that can take parameters + * or attributes. <tiles:insertTemplate> allows to define + * these attributes and pass them to the inserted jsp page, called template. + * Attributes are defined using nested tag + * <tiles:putAttribute> or + * <tiles:putListAttribute>. + *

+ *

+ * You must specify template attribute, for inserting a template + *

+ * + *

+ * Example : + *

+ * + *
+ * <code>
+ *           <tiles:insertTemplate template="/basic/myLayout.jsp" flush="true">
+ *              <tiles:putAttribute name="title" value="My first page" />
+ *              <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *              <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *              <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *              <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *           </tiles:insertTemplate>
+ *         </code>
+ * 
+ * + * @since 2.2.0 + */ +public class InsertTemplateModel { + + /** + * Executes the operation. + * + * @param template The template to render. + * @param templateType The type of the template attribute. + * @param templateExpression The expression to evaluate to get the value of the template. + * @param role A comma-separated list of roles. If present, the template + * will be rendered only if the current user belongs to one of the roles. + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified in the + * definition itself. + * @param flush If true, the response will be flushed after the insert. + * @param request The request. + * @param modelBody The body. + * @throws IOException If something goes wrong. + * @since 2.2.0 + */ + public void execute( + @Parameter(required = true) String template, + String templateType, + String templateExpression, + String role, + String preparer, + boolean flush, + Request request, + ModelBody modelBody + ) throws IOException { + TilesContainer container = TilesAccess.getCurrentContainer(request); + container.startContext(request); + modelBody.evaluateWithoutWriting(); + container = TilesAccess.getCurrentContainer(request); + renderTemplate(container, template, templateType, templateExpression, role, preparer, flush, request); + } + + /** + * Renders a template. + * + * @param container The container to use. + * @param template The template to render. + * @param templateType The type of the template attribute. + * @param templateExpression The expression to evaluate to get the value of the template. + * @param role A comma-separated list of roles. If present, the template + * will be rendered only if the current user belongs to one of the roles. + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified in the + * definition itself. + * @param flush If true, the response will be flushed after the insert. + * @param request The request. + * @throws IOException If something goes wrong. + */ + private void renderTemplate( + TilesContainer container, + String template, + String templateType, + String templateExpression, + String role, + String preparer, + boolean flush, + Request request + ) throws IOException { + try { + AttributeContext attributeContext = container.getAttributeContext(request); + Attribute templateAttribute = Attribute.createTemplateAttribute(template, templateExpression, templateType, role); + attributeContext.setPreparer(preparer); + attributeContext.setTemplateAttribute(templateAttribute); + container.renderContext(request); + if (flush) { + request.getWriter().flush(); + } + } finally { + container.endContext(request); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/NoSuchAttributeException.java b/plugins/tiles/src/main/java/org/apache/tiles/template/NoSuchAttributeException.java new file mode 100644 index 0000000000..5de6b0f18f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/NoSuchAttributeException.java @@ -0,0 +1,40 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.TilesException; + +/** + * Indicates that a named attribute has not been found. + * + * @since 2.2.0 + */ +public class NoSuchAttributeException extends TilesException { + + /** + * Constructor. + * + * @param message The detail message. + * @since 2.2.0 + */ + public NoSuchAttributeException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/PutAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/PutAttributeModel.java new file mode 100644 index 0000000000..9391f14bf1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/PutAttributeModel.java @@ -0,0 +1,165 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Put an attribute in enclosing attribute container tag. + *

+ *

+ * Enclosing attribute container tag can be : + *

    + *
  • <initContainer>
  • + *
  • <definition>
  • + *
  • <insertAttribute>
  • + *
  • <insertDefinition>
  • + *
  • <putListAttribute>
  • + *
+ * (or any other tag which implements the PutAttributeTagParent + * interface. Exception is thrown if no appropriate tag can be found. + *

+ *

+ * Put tag can have following atributes : + *

    + *
  • name : Name of the attribute
  • + *
  • value : value to put as attribute
  • + *
  • type : value type. Possible type are : string (value is used as direct + * string), template (value is used as a page url to insert), definition (value + * is used as a definition name to insert), object (value is used as it is)
  • + *
  • role : Role to check when 'insertAttribute' will be called.
  • + *
+ *

+ *

+ * Value can also come from tag body. Tag body is taken into account only if + * value is not set by one of the tag attributes. In this case Attribute type is + * "string", unless tag body define another type. + *

+ * + * @since 2.2.0 + */ +public class PutAttributeModel { + + /** + * Executes the operation. + * + * @param name The name of the attribute to put. + * @param value The value of the attribute. Use this parameter, or + * expression, or body. + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param type The type (renderer) of the attribute. + * @param cascade If true the attribute will be cascaded to all nested attributes. + * @param request The request. + * @param modelBody The body. + * @throws IOException If the body cannot be evaluated. + * @since 2.2.0 + */ + public void execute( + @Parameter(required = true) String name, + Object value, + String expression, + String role, + String type, + boolean cascade, + Request request, + ModelBody modelBody + ) throws IOException { + Deque composeStack = ComposeStackUtil.getComposeStack(request); + Attribute attribute = new Attribute(); + composeStack.push(attribute); + String currentBody = modelBody.evaluateAsString(); + TilesContainer container = TilesAccess.getCurrentContainer(request); + attribute = (Attribute) composeStack.pop(); + putAttributeInParent(attribute, container, composeStack, name, value, expression, currentBody, role, type, cascade, request); + } + + /** + * Determines the parent and puts the attribute inside it. + * + * @param attribute The attribute to put; + * @param container The Tiles container to use. + * @param composeStack The composing stack. + * @param name The name of the attribute to put. + * @param value The value of the attribute. Use this parameter, or + * expression, or body. + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + * @param body The body of the tag. Use this parameter, or value, or + * expression. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param type The type (renderer) of the attribute. + * @param cascade If true the attribute will be cascaded to all nested attributes. + * @param request The request. + */ + private void putAttributeInParent( + Attribute attribute, + TilesContainer container, + Deque composeStack, + String name, + Object value, + String expression, + String body, + String role, + String type, + boolean cascade, + Request request + ) { + AttributeContext attributeContext = null; + if (!composeStack.isEmpty()) { + Object obj = composeStack.peek(); + if (obj instanceof AttributeContext) { + attributeContext = (AttributeContext) obj; + } + } + if (attributeContext == null) { + attributeContext = container.getAttributeContext(request); + } + if (value != null) { + attribute.setValue(value); + } else if (attribute.getValue() == null && body != null) { + attribute.setValue(body); + } + if (expression != null) { + attribute.setExpressionObject(Expression.createExpressionFromDescribedExpression(expression)); + } + if (role != null) { + attribute.setRole(role); + } + if (type != null) { + attribute.setRenderer(type); + } + + attributeContext.putAttribute(name, attribute, cascade); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/PutListAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/PutListAttributeModel.java new file mode 100644 index 0000000000..30e858802d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/PutListAttributeModel.java @@ -0,0 +1,88 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Declare a list that will be pass as attribute to tile. + *

+ *

+ * Declare a list that will be pass as attribute to tile. List elements are + * added using the tags 'addAttribute' or 'addListAttribute'. This tag can only + * be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. + *

+ * + * @since 2.2.0 + */ +public class PutListAttributeModel { + + /** + * Executes the model. + * + * @param name The name of the attribute to put. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param inherit If true, the list attribute will use, as first elements, the + * list contained in the list attribute, put with the same name, of the containing definition. + * @param cascade If true the attribute will be cascaded to all nested attributes. + * @param request The request. + * @param modelBody The body. + * @throws IOException If the body cannot be evaluated. + */ + public void execute( + @Parameter(required = true) String name, + String role, + boolean inherit, + boolean cascade, + Request request, + ModelBody modelBody + ) throws IOException { + Deque composeStack = ComposeStackUtil.getComposeStack(request); + ListAttribute listAttribute = new ListAttribute(); + listAttribute.setRole(role); + listAttribute.setInherit(inherit); + composeStack.push(listAttribute); + modelBody.evaluateWithoutWriting(); + TilesContainer container = TilesAccess.getCurrentContainer(request); + listAttribute = (ListAttribute) composeStack.pop(); + AttributeContext attributeContext = null; + if (!composeStack.isEmpty()) { + Object obj = composeStack.peek(); + if (obj instanceof Definition) { + attributeContext = (AttributeContext) obj; + } + } + if (attributeContext == null) { + attributeContext = container.getAttributeContext(request); + } + attributeContext.putAttribute(name, listAttribute, cascade); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/SetCurrentContainerModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/SetCurrentContainerModel.java new file mode 100644 index 0000000000..80b7174ed4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/SetCurrentContainerModel.java @@ -0,0 +1,41 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.Request; + +/** + * Selects a container to be used as the "current" container. + * + * @since 3.0.0 + */ +public class SetCurrentContainerModel { + + /** + * Executes the model. + * + * @param containerKey The key of the container to be used as "current". If + * null, the default one will be used. + * @param request The request. + */ + public void execute(String containerKey, Request request) { + TilesAccess.setCurrentContainer(request, containerKey); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/template/package-info.java new file mode 100644 index 0000000000..828b7ac3de --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Tiles template classes, that enable to write support code for template languages (JSP, FreeMarker, Velocity). + */ +package org.apache.tiles.template; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/TilesVelocityException.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/TilesVelocityException.java new file mode 100644 index 0000000000..165bce3733 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/TilesVelocityException.java @@ -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.apache.tiles.velocity; + +import org.apache.tiles.api.TilesException; + +/** + * Exception connected to the usage of Velocity and Tiles. + * + * @since 2.2.0 + */ +public class TilesVelocityException extends TilesException { + + private static final long serialVersionUID = -7013866521398042363L; + + /** + * Constructor. + * + * @since 2.2.0 + */ + public TilesVelocityException() { + } + + /** + * Constructor. + * + * @param message The message of the exception. + * @since 2.2.0 + */ + public TilesVelocityException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param e The cause of the exception. + * @since 2.2.0 + */ + public TilesVelocityException(Throwable e) { + super(e); + } + + /** + * Constructor. + * + * @param message The message of the exception. + * @param e The cause of the exception. + * @since 2.2.0 + */ + public TilesVelocityException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/package-info.java new file mode 100644 index 0000000000..084432124b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Classes to support Velocity under a servlet environment in Tiles. + */ +package org.apache.tiles.velocity; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java new file mode 100644 index 0000000000..3628833bbc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java @@ -0,0 +1,119 @@ +/* + * 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.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tiles.velocity.TilesVelocityException; +import org.apache.velocity.context.Context; +import org.apache.velocity.exception.MethodInvocationException; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.exception.ResourceNotFoundException; +import org.apache.velocity.runtime.Renderable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Renderable that provides a default implementation of Renderable#toString() + * and allows access to parameters and context objects. + * + * @since 2.2.0 + */ +public abstract class AbstractDefaultToStringRenderable implements Renderable { + + /** + * The Velocity context. + * + * @since 2.2.0 + */ + protected final Context velocityContext; + + /** + * The parameters used in the current tool call. + * + * @since 2.2.0 + */ + protected final Map params; + + /** + * The HTTP response. + * + * @since 2.2.0 + */ + protected final HttpServletResponse response; + + /** + * The HTTP request. + * + * @since 2.2.0 + */ + protected final HttpServletRequest request; + + /** + * The logging object. + */ + private final Logger log = LoggerFactory.getLogger(getClass()); + + /** + * Constructor. + * + * @param velocityContext The Velocity context. + * @param params The parameters used in the current tool call. + * @param response The HTTP response. + * @param request The HTTP request. + * @since 2.2.0 + */ + public AbstractDefaultToStringRenderable(Context velocityContext, Map params, + HttpServletResponse response, HttpServletRequest request) { + this.velocityContext = velocityContext; + this.params = params; + this.response = response; + this.request = request; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + StringWriter writer = new StringWriter(); + try { + render(null, writer); + } catch (MethodInvocationException e) { + throw new TilesVelocityException("Cannot invoke method when rendering", e); + } catch (ParseErrorException e) { + throw new TilesVelocityException("Cannot parse when rendering", e); + } catch (ResourceNotFoundException e) { + throw new TilesVelocityException("Cannot find resource when rendering", e); + } catch (IOException e) { + throw new TilesVelocityException("I/O exception when rendering", e); + } finally { + try { + writer.close(); + } catch (IOException e) { + log.error("Error when closing a StringWriter, the impossible happened!", e); + } + } + return writer.toString(); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddAttributeDirective.java new file mode 100644 index 0000000000..49f6c31124 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddAttributeDirective.java @@ -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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Add an element to the surrounding list. Equivalent to 'putAttribute', but for + * list element. + *

+ * + *

+ * Add an element to the surrounding list. This tag can only be used inside + * 'putListAttribute' or 'addListAttribute' tags. Value can come from a direct + * assignment (value="aValue") + *

+ */ +public class AddAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.AddAttributeModel model = new org.apache.tiles.template.AddAttributeModel(); + + @Override + public String getName() { + return "tiles_addAttribute"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("value", java.lang.Object.class, null), + runtime.getParameter("expression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("type", java.lang.String.class, null), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddListAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddListAttributeDirective.java new file mode 100644 index 0000000000..b42b120b04 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddListAttributeDirective.java @@ -0,0 +1,73 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Declare a list that will be pass as an attribute. + *

+ *

+ * Declare a list that will be pass as an attribute . List elements are added + * using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used + * inside 'insertTemplate', 'insertDefinition' or 'definition' tag. + *

+ */ +public class AddListAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.AddListAttributeModel model = new org.apache.tiles.template.AddListAttributeModel(); + + @Override + public String getName() { + return "tiles_addListAttribute"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("role", java.lang.String.class, null), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ContextHolder.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ContextHolder.java new file mode 100644 index 0000000000..ad43f39419 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ContextHolder.java @@ -0,0 +1,154 @@ +/* + * 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.apache.tiles.velocity.template; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +/** + * An object that holds the current state of Velocity in a Servlet environment. + * + * @since 2.2.0 + */ +public class ContextHolder { + + /** + * The Velocity context. + */ + private Context velocityContext; + + /** + * The HTTP request. + */ + private HttpServletRequest request; + + /** + * The HTTP response. + */ + private HttpServletResponse response; + + /** + * The servlet context. + */ + private ServletContext application; + + /** + * Sets the current {@link HttpServletRequest}. This is required for this tool + * to operate and will throw a NullPointerException if this is not set or is set + * to {@code null}. + * + * @param request The HTTP request. + * @since 2.2.0 + */ + public void setRequest(HttpServletRequest request) { + if (request == null) { + throw new NullPointerException("request should not be null"); + } + this.request = request; + } + + /** + * Sets the current {@link HttpServletResponse}. This is required for this tool + * to operate and will throw a NullPointerException if this is not set or is set + * to {@code null}. + * + * @param response The HTTP response. + * @since 2.2.0 + */ + public void setResponse(HttpServletResponse response) { + if (response == null) { + throw new NullPointerException("response should not be null"); + } + this.response = response; + } + + /** + * Sets the {@link ServletContext}. This is required for this tool to operate + * and will throw a NullPointerException if this is not set or is set to + * {@code null}. + * + * @param application The Servlet context. + * @since 2.2.0 + */ + public void setServletContext(ServletContext application) { + if (application == null) { + throw new NullPointerException("servlet context should not be null"); + } + this.application = application; + } + + /** + * Sets the Velocity {@link Context}. This is required for this tool to operate + * and will throw a NullPointerException if this is not set or is set to + * {@code null}. + * + * @param context The Velocity context. + * @since 2.2.0 + */ + public void setVelocityContext(Context context) { + if (context == null) { + throw new NullPointerException("velocity context should not be null"); + } + this.velocityContext = context; + } + + /** + * Returns the HTTP request. + * + * @return The HTTP request. + * @since 2.2.0 + */ + protected HttpServletRequest getRequest() { + return request; + } + + /** + * Returns the HTTP response. + * + * @return The HTTP response. + * @since 2.2.0 + */ + protected HttpServletResponse getResponse() { + return response; + } + + /** + * Returns the Servlet context. + * + * @return The Servlet context.. + * @since 2.2.0 + */ + protected ServletContext getServletContext() { + return application; + } + + /** + * Returns the Velocity context.. + * + * @return The Velocity context. + * @since 2.2.0 + */ + protected Context getVelocityContext() { + return velocityContext; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/DefinitionDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/DefinitionDirective.java new file mode 100644 index 0000000000..90373e332a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/DefinitionDirective.java @@ -0,0 +1,76 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Create a definition at runtime. + *

+ *

+ * Create a new definition at runtime. Newly created definition will be + * available across the entire request. + *

+ */ +public class DefinitionDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.DefinitionModel model = new org.apache.tiles.template.DefinitionModel(); + + @Override + public String getName() { + return "tiles_definition"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("extends", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/GetAsStringDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/GetAsStringDirective.java new file mode 100644 index 0000000000..24109ab3fd --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/GetAsStringDirective.java @@ -0,0 +1,81 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Render the value of the specified template attribute to the current Writer + *

+ * + *

+ * Retrieve the value of the specified template attribute property, and render + * it to the current Writer as a String. The usual toString() conversions is + * applied on found value. + *

+ */ +public class GetAsStringDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.GetAsStringModel model = new org.apache.tiles.template.GetAsStringModel(); + + @Override + public String getName() { + return "tiles_getAsString"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("ignore", java.lang.Boolean.class, false), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("defaultValue", java.lang.Object.class, null), + runtime.getParameter("defaultValueRole", java.lang.String.class, null), + runtime.getParameter("defaultValueType", java.lang.String.class, null), + runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", org.apache.tiles.api.Attribute.class, null), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ImportAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ImportAttributeDirective.java new file mode 100644 index 0000000000..7fa6f4f9fb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ImportAttributeDirective.java @@ -0,0 +1,74 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Import attribute(s) in specified context. + *

+ *

+ * Import attribute(s) to requested scope. Attribute name and scope are + * optional. If not specified, all attributes are imported in page scope. Once + * imported, an attribute can be used as any other beans from jsp contexts. + *

+ */ +public class ImportAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.ImportAttributeModel model = new org.apache.tiles.template.ImportAttributeModel(); + + @Override + public String getName() { + return "tiles_importAttribute"; + } + + @Override + public int getType() { + return LINE; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("scope", java.lang.String.class, null), + runtime.getParameter("toName", java.lang.String.class, null), + runtime.getParameter("ignore", java.lang.Boolean.class, false), request + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertAttributeDirective.java new file mode 100644 index 0000000000..4a980cd1d0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertAttributeDirective.java @@ -0,0 +1,94 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Inserts the value of an attribute into the page. + *

+ *

+ * This tag can be flexibly used to insert the value of an attribute into a + * page. As in other usages in Tiles, every attribute can be determined to have + * a "type", either set explicitly when it was defined, or "computed". If the + * type is not explicit, then if the attribute value is a valid definition, it + * will be inserted as such. Otherwise, if it begins with a "/" character, it + * will be treated as a "template". Finally, if it has not otherwise been + * assigned a type, it will be treated as a String and included without any + * special handling. + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertAttribute name="body" />
+ * 
+ */ +public class InsertAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertAttributeModel model = new org.apache.tiles.template.InsertAttributeModel(); + + @Override + public String getName() { + return "tiles_insertAttribute"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("ignore", java.lang.Boolean.class, false), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("defaultValue", java.lang.Object.class, null), + runtime.getParameter("defaultValueRole", java.lang.String.class, null), + runtime.getParameter("defaultValueType", java.lang.String.class, null), + runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", org.apache.tiles.api.Attribute.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertDefinitionDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertDefinitionDirective.java new file mode 100644 index 0000000000..51a098882f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertDefinitionDirective.java @@ -0,0 +1,99 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Insert a definition. + *

+ *

+ * Insert a definition with the possibility to override and specify parameters + * (called attributes). A definition can be seen as a (partially or totally) + * filled template that can override or complete attribute values. + * <tiles:insertDefinition> allows to define these attributes and pass + * them to the inserted jsp page, called template. Attributes are defined using + * nested tag <tiles:putAttribute> or <tiles:putListAttribute>. + *

+ *

+ * You must specify name tag attribute, for inserting a definition from + * definitions factory. + *

+ *

+ * Example : + *

+ * + *
+ *     <tiles:insertDefinition name=".my.tiles.defininition flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertDefinition>
+ * 
+ */ +public class InsertDefinitionDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertDefinitionModel model = new org.apache.tiles.template.InsertDefinitionModel(); + + @Override + public String getName() { + return "tiles_insertDefinition"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("templateType", java.lang.String.class, null), + runtime.getParameter("templateExpression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertTemplateDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertTemplateDirective.java new file mode 100644 index 0000000000..1ce0e53df9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertTemplateDirective.java @@ -0,0 +1,98 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Insert a template. + *

+ *

+ * Insert a template with the possibility to pass parameters (called + * attributes). A template can be seen as a procedure that can take parameters + * or attributes. <tiles:insertTemplate> allows to define these attributes + * and pass them to the inserted jsp page, called template. Attributes are + * defined using nested tag <tiles:putAttribute> or + * <tiles:putListAttribute>. + *

+ *

+ * You must specify template attribute, for inserting a template + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertTemplate template="/basic/myLayout.jsp" flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertTemplate>
+ * 
+ */ +public class InsertTemplateDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertTemplateModel model = new org.apache.tiles.template.InsertTemplateModel(); + + @Override + public String getName() { + return "tiles_insertTemplate"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("templateType", java.lang.String.class, null), + runtime.getParameter("templateExpression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutAttributeDirective.java new file mode 100644 index 0000000000..acac9b1fa1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutAttributeDirective.java @@ -0,0 +1,101 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Put an attribute in enclosing attribute container tag. + *

+ *

+ * Enclosing attribute container tag can be : + *

    + *
  • <initContainer>
  • + *
  • <definition>
  • + *
  • <insertAttribute>
  • + *
  • <insertDefinition>
  • + *
  • <putListAttribute>
  • + *
+ * (or any other tag which implements the PutAttributeTagParent interface. + * Exception is thrown if no appropriate tag can be found. + *

+ *

+ * Put tag can have following atributes : + *

    + *
  • name : Name of the attribute
  • + *
  • value : value to put as attribute
  • + *
  • type : value type. Possible type are : string (value is used as direct + * string), template (value is used as a page url to insert), definition (value + * is used as a definition name to insert), object (value is used as it is)
  • + *
  • role : Role to check when 'insertAttribute' will be called.
  • + *
+ *

+ *

+ * Value can also come from tag body. Tag body is taken into account only if + * value is not set by one of the tag attributes. In this case Attribute type is + * "string", unless tag body define another type. + *

+ */ +public class PutAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.PutAttributeModel model = new org.apache.tiles.template.PutAttributeModel(); + + @Override + public String getName() { + return "tiles_putAttribute"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", java.lang.Object.class, null), + runtime.getParameter("expression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("type", java.lang.String.class, null), + runtime.getParameter("cascade", java.lang.Boolean.class, false), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutListAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutListAttributeDirective.java new file mode 100644 index 0000000000..c55dd92746 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutListAttributeDirective.java @@ -0,0 +1,76 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Declare a list that will be pass as attribute to tile. + *

+ *

+ * Declare a list that will be pass as attribute to tile. List elements are + * added using the tags 'addAttribute' or 'addListAttribute'. This tag can only + * be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. + *

+ */ +public class PutListAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.PutListAttributeModel model = new org.apache.tiles.template.PutListAttributeModel(); + + @Override + public String getName() { + return "tiles_putListAttribute"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("inherit", java.lang.Boolean.class, false), + runtime.getParameter("cascade", java.lang.Boolean.class, false), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/SetCurrentContainerDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/SetCurrentContainerDirective.java new file mode 100644 index 0000000000..d7ff03e80d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/SetCurrentContainerDirective.java @@ -0,0 +1,64 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + * Selects a container to be used as the "current" container. + */ +public class SetCurrentContainerDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.SetCurrentContainerModel model = new org.apache.tiles.template.SetCurrentContainerModel(); + + @Override + public String getName() { + return "tiles_setCurrentContainer"; + } + + @Override + public int getType() { + return LINE; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(runtime.getParameter("containerKey", java.lang.String.class, null), request + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/VelocityStyleTilesTool.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/VelocityStyleTilesTool.java new file mode 100644 index 0000000000..e9c3852ac6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/VelocityStyleTilesTool.java @@ -0,0 +1,224 @@ +/* + * 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.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import javax.servlet.ServletContext; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.servlet.ServletUtil; +import org.apache.tiles.request.velocity.VelocityRequest; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.Renderable; + +/** + * Tiles Tool to be used "the classic way". + * + * @since 2.2.0 + */ +public class VelocityStyleTilesTool extends ContextHolder { + + /** + * Returns an attribute. + * + * @param key The name of the attribute to get. + * @return The Attribute. + * @since 2.2.0 + */ + public Attribute get(String key) { + Request velocityRequest = createVelocityRequest(getServletContext(), null); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + AttributeContext attributeContext = container.getAttributeContext(velocityRequest); + Attribute attribute = attributeContext.getAttribute(key); + return attribute; + } + + /** + * Creates a new empty attribute. + * + * @return The created attribute. + * @since 2.2.0 + */ + public Attribute createAttribute() { + return new Attribute(); + } + + /** + * Creates an attribute that is a copy of the one passed as a parameter. + * + * @param attribute The attribute to copy. + * @return The copied attribute. + * @since 2.2.0 + */ + public Attribute clone(Attribute attribute) { + return new Attribute(attribute); + } + + /** + * Creates an attribute that represents a template. + * + * @param template The template. + * @return The attribute. + * @since 2.2.0 + */ + public Attribute createTemplateAttribute(String template) { + return Attribute.createTemplateAttribute(template); + } + + /** + * Renders an attribute. + * + * @param attribute The attribute to render. + * @return The renderable object, ready to be rendered. + * @since 2.2.0 + */ + public Renderable render(final Attribute attribute) { + return new AbstractDefaultToStringRenderable(getVelocityContext(), null, getResponse(), getRequest()) { + + public boolean render(InternalContextAdapter context, Writer writer) throws IOException { + Request velocityRequest = createVelocityRequest(getServletContext(), writer); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + container.render(attribute, velocityRequest); + return true; + } + + }; + } + + /** + * Renders a definition. It can be used in conjunction with + * {@link #startAttributeContext()} and {@link #endAttributeContext()} to + * customize appearance. + * + * @param definitionName The name of the definition to render. + * @return The renderable that renders the definition. + * @since 2.2.0 + */ + public Renderable renderDefinition(final String definitionName) { + return new AbstractDefaultToStringRenderable(getVelocityContext(), null, getResponse(), getRequest()) { + + public boolean render(InternalContextAdapter context, Writer writer) { + Request velocityRequest = createVelocityRequest(getServletContext(), writer); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + container.render(definitionName, velocityRequest); + return true; + } + + }; + } + + /** + * Renders the current attribute context. It can be used in conjunction with + * {@link #startAttributeContext()} and {@link #endAttributeContext()} to + * customize appearance. + * + * @return The renderable that renders the current attribute context. + * @since 2.2.0 + */ + public Renderable renderAttributeContext() { + return new AbstractDefaultToStringRenderable(getVelocityContext(), null, getResponse(), getRequest()) { + + public boolean render(InternalContextAdapter context, Writer writer) { + Request velocityRequest = createVelocityRequest(getServletContext(), writer); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + container.renderContext(velocityRequest); + return true; + } + + }; + } + + /** + * Starts the attribute context. Remember to call {@link #endAttributeContext()} + * when finished! + * + * @return The started attribute context, ready to be customized. + * @since 2.2.0 + */ + public AttributeContext startAttributeContext() { + Request velocityRequest = createVelocityRequest(getServletContext(), null); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + return container.startContext(velocityRequest); + } + + /** + * Ends the current attribute context. To be called after + * {@link #startAttributeContext()}. + * + * @return The tool itself. + * @since 2.2.0 + */ + public VelocityStyleTilesTool endAttributeContext() { + Request velocityRequest = createVelocityRequest(getServletContext(), null); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + container.endContext(velocityRequest); + return this; + } + + /** + * Returns the current attribute context. + * + * @return The current attribute context. + * @since 2.2.0 + */ + public AttributeContext getAttributeContext() { + Request velocityRequest = createVelocityRequest(getServletContext(), null); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + return container.getAttributeContext(velocityRequest); + } + + /** + * Sets the current container for the current request. + * + * @param containerKey The key of the container to set as "current" for the + * current request. + * @return The tool itself. + * @since 2.2.0 + */ + public VelocityStyleTilesTool setCurrentContainer(String containerKey) { + Request velocityRequest = createVelocityRequest(getServletContext(), null); + TilesAccess.setCurrentContainer(velocityRequest, containerKey); + return this; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return ""; + } + + /** + * Creates a Velocity request. + * + * @param servletContext The servlet context. + * @param writer The writer. + * @return The created request. + */ + protected Request createVelocityRequest(ServletContext servletContext, Writer writer) { + return VelocityRequest.createVelocityRequest(ServletUtil.getApplicationContext(servletContext), getRequest(), + getResponse(), getVelocityContext(), writer); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/package-info.java new file mode 100644 index 0000000000..eeb9e3a272 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * Classes that allow the use of "Tiles template" as a Velocity tool. + */ +package org.apache.tiles.velocity.template; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddAttributeTag.java new file mode 100644 index 0000000000..53c42cef20 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddAttributeTag.java @@ -0,0 +1,165 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Add an element to the surrounding list. Equivalent to 'putAttribute', but for + * list element. + *

+ * + *

+ * Add an element to the surrounding list. This tag can only be used inside + * 'putListAttribute' or 'addListAttribute' tags. Value can come from a direct + * assignment (value="aValue") + *

+ */ +public class AddAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.AddAttributeModel model = new org.apache.tiles.template.AddAttributeModel(); + + /** + * The value of the attribute. Use this parameter, or expression, or body. + */ + private java.lang.Object value; + + /** + * The expression to calculate the value from. Use this parameter, or value, or + * body. + */ + private java.lang.String expression; + + /** + * A comma-separated list of roles. If present, the attribute will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The type (renderer) of the attribute. + */ + private java.lang.String type; + + /** + * Getter for value property. + * + * @return The value of the attribute. Use this parameter, or expression, or + * body. + */ + public java.lang.Object getValue() { + return value; + } + + /** + * Setter for value property. + * + * @param value The value of the attribute. Use this parameter, or expression, + * or body. + */ + public void setValue(java.lang.Object value) { + this.value = value; + } + + /** + * Getter for expression property. + * + * @return The expression to calculate the value from. Use this parameter, or + * value, or body. + */ + public java.lang.String getExpression() { + return expression; + } + + /** + * Setter for expression property. + * + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + */ + public void setExpression(java.lang.String expression) { + this.expression = expression; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the attribute will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the attribute will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for type property. + * + * @return The type (renderer) of the attribute. + */ + public java.lang.String getType() { + return type; + } + + /** + * Setter for type property. + * + * @param type The type (renderer) of the attribute. + */ + public void setType(java.lang.String type) { + this.type = type; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(value, expression, role, type, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddListAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddListAttributeTag.java new file mode 100644 index 0000000000..0dc5c9fde8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddListAttributeTag.java @@ -0,0 +1,87 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Declare a list that will be pass as an attribute. + *

+ *

+ * Declare a list that will be pass as an attribute . List elements are added + * using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used + * inside 'insertTemplate', 'insertDefinition' or 'definition' tag. + *

+ */ +public class AddListAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.AddListAttributeModel model = new org.apache.tiles.template.AddListAttributeModel(); + + /** + * The comma-separated list of roles that can use the list attribute. + */ + private java.lang.String role; + + /** + * Getter for role property. + * + * @return The comma-separated list of roles that can use the list attribute. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role The comma-separated list of roles that can use the list + * attribute. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(role, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/DefinitionTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/DefinitionTag.java new file mode 100644 index 0000000000..eac32da5a7 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/DefinitionTag.java @@ -0,0 +1,184 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Create a definition at runtime. + *

+ *

+ * Create a new definition at runtime. Newly created definition will be + * available across the entire request. + *

+ */ +public class DefinitionTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.DefinitionModel model = new org.apache.tiles.template.DefinitionModel(); + + /** + * The name of the definition to create. If not specified, an anonymous + * definition will be created. + */ + private java.lang.String name; + + /** + * The template of this definition. + */ + private java.lang.String template; + + /** + * A comma-separated list of roles. If present, the definition will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The definition name that this definition extends. + */ + private java.lang.String extendsParam; + + /** + * The preparer to use to invoke before the definition is rendered. + */ + private java.lang.String preparer; + + /** + * Getter for name property. + * + * @return The name of the definition to create. If not specified, an anonymous + * definition will be created. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the definition to create. If not specified, an + * anonymous definition will be created. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for template property. + * + * @return The template of this definition. + */ + public java.lang.String getTemplate() { + return template; + } + + /** + * Setter for template property. + * + * @param template The template of this definition. + */ + public void setTemplate(java.lang.String template) { + this.template = template; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the definition will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the definition will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for extends property. + * + * @return The definition name that this definition extends. + */ + public java.lang.String getExtends() { + return extendsParam; + } + + /** + * Setter for extends property. + * + * @param extendsParam The definition name that this definition extends. + */ + public void setExtends(java.lang.String extendsParam) { + this.extendsParam = extendsParam; + } + + /** + * Getter for preparer property. + * + * @return The preparer to use to invoke before the definition is rendered. + */ + public java.lang.String getPreparer() { + return preparer; + } + + /** + * Setter for preparer property. + * + * @param preparer The preparer to use to invoke before the definition is + * rendered. + */ + public void setPreparer(java.lang.String preparer) { + this.preparer = preparer; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(name, template, role, extendsParam, preparer, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/GetAsStringTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/GetAsStringTag.java new file mode 100644 index 0000000000..e34a1efc1d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/GetAsStringTag.java @@ -0,0 +1,264 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Render the value of the specified template attribute to the current Writer + *

+ * + *

+ * Retrieve the value of the specified template attribute property, and render + * it to the current Writer as a String. The usual toString() conversions is + * applied on found value. + *

+ */ +public class GetAsStringTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.GetAsStringModel model = new org.apache.tiles.template.GetAsStringModel(); + + /** + * If true, if an exception happens during rendering, of if the attribute is + * null, the problem will be ignored. + */ + private boolean ignore; + + /** + * The preparer to invoke before rendering the attribute. + */ + private java.lang.String preparer; + + /** + * A comma-separated list of roles. If present, the attribute will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The default value of the attribute. To use only if the attribute was not + * computed. + */ + private java.lang.Object defaultValue; + + /** + * The default comma-separated list of roles. To use only if the attribute was + * not computed. + */ + private java.lang.String defaultValueRole; + + /** + * The default type of the attribute. To use only if the attribute was not + * computed. + */ + private java.lang.String defaultValueType; + + /** + * The name of the attribute. + */ + private java.lang.String name; + + /** + * The attribute to use immediately, if not null. + */ + private org.apache.tiles.api.Attribute value; + + /** + * Getter for ignore property. + * + * @return If true, if an exception happens during rendering, of if the + * attribute is null, the problem will be ignored. + */ + public boolean isIgnore() { + return ignore; + } + + /** + * Setter for ignore property. + * + * @param ignore If true, if an exception happens during rendering, of if the + * attribute is null, the problem will be ignored. + */ + public void setIgnore(boolean ignore) { + this.ignore = ignore; + } + + /** + * Getter for preparer property. + * + * @return The preparer to invoke before rendering the attribute. + */ + public java.lang.String getPreparer() { + return preparer; + } + + /** + * Setter for preparer property. + * + * @param preparer The preparer to invoke before rendering the attribute. + */ + public void setPreparer(java.lang.String preparer) { + this.preparer = preparer; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the attribute will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the attribute will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for defaultValue property. + * + * @return The default value of the attribute. To use only if the attribute was + * not computed. + */ + public java.lang.Object getDefaultValue() { + return defaultValue; + } + + /** + * Setter for defaultValue property. + * + * @param defaultValue The default value of the attribute. To use only if the + * attribute was not computed. + */ + public void setDefaultValue(java.lang.Object defaultValue) { + this.defaultValue = defaultValue; + } + + /** + * Getter for defaultValueRole property. + * + * @return The default comma-separated list of roles. To use only if the + * attribute was not computed. + */ + public java.lang.String getDefaultValueRole() { + return defaultValueRole; + } + + /** + * Setter for defaultValueRole property. + * + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + */ + public void setDefaultValueRole(java.lang.String defaultValueRole) { + this.defaultValueRole = defaultValueRole; + } + + /** + * Getter for defaultValueType property. + * + * @return The default type of the attribute. To use only if the attribute was + * not computed. + */ + public java.lang.String getDefaultValueType() { + return defaultValueType; + } + + /** + * Setter for defaultValueType property. + * + * @param defaultValueType The default type of the attribute. To use only if the + * attribute was not computed. + */ + public void setDefaultValueType(java.lang.String defaultValueType) { + this.defaultValueType = defaultValueType; + } + + /** + * Getter for name property. + * + * @return The name of the attribute. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the attribute. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for value property. + * + * @return The attribute to use immediately, if not null. + */ + public org.apache.tiles.api.Attribute getValue() { + return value; + } + + /** + * Setter for value property. + * + * @param value The attribute to use immediately, if not null. + */ + public void setValue(org.apache.tiles.api.Attribute value) { + this.value = value; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(ignore, preparer, role, defaultValue, defaultValueRole, defaultValueType, name, value, request, + modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/ImportAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/ImportAttributeTag.java new file mode 100644 index 0000000000..56ca370e4b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/ImportAttributeTag.java @@ -0,0 +1,166 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Import attribute(s) in specified context. + *

+ *

+ * Import attribute(s) to requested scope. Attribute name and scope are + * optional. If not specified, all attributes are imported in page scope. Once + * imported, an attribute can be used as any other beans from jsp contexts. + *

+ */ +public class ImportAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.ImportAttributeModel model = new org.apache.tiles.template.ImportAttributeModel(); + + /** + * The name of the attribute to import. If it is null, all the attributes will + * be imported. + */ + private java.lang.String name; + + /** + * The scope into which the attribute(s) will be imported. If null, the import + * will go in page scope. + */ + private java.lang.String scope; + + /** + * The name of the attribute into which the attribute will be imported. To be + * used in conjunction to name. If null, the value of name will be used. + */ + private java.lang.String toName; + + /** + * If true, if the attribute is not present, the problem will be ignored. + */ + private boolean ignore; + + /** + * Getter for name property. + * + * @return The name of the attribute to import. If it is null, all the + * attributes will be imported. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the attribute to import. If it is null, all the + * attributes will be imported. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for scope property. + * + * @return The scope into which the attribute(s) will be imported. If null, the + * import will go in page scope. + */ + public java.lang.String getScope() { + return scope; + } + + /** + * Setter for scope property. + * + * @param scope The scope into which the attribute(s) will be imported. If null, + * the import will go in page scope. + */ + public void setScope(java.lang.String scope) { + this.scope = scope; + } + + /** + * Getter for toName property. + * + * @return The name of the attribute into which the attribute will be imported. + * To be used in conjunction to name. If null, the value of name will be + * used. + */ + public java.lang.String getToName() { + return toName; + } + + /** + * Setter for toName property. + * + * @param toName The name of the attribute into which the attribute will be + * imported. To be used in conjunction to name. If null, the value + * of name will be used. + */ + public void setToName(java.lang.String toName) { + this.toName = toName; + } + + /** + * Getter for ignore property. + * + * @return If true, if the attribute is not present, the problem will be + * ignored. + */ + public boolean isIgnore() { + return ignore; + } + + /** + * Setter for ignore property. + * + * @param ignore If true, if the attribute is not present, the problem will be + * ignored. + */ + public void setIgnore(boolean ignore) { + this.ignore = ignore; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(name, scope, toName, ignore, request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertAttributeTag.java new file mode 100644 index 0000000000..be288e8646 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertAttributeTag.java @@ -0,0 +1,299 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Inserts the value of an attribute into the page. + *

+ *

+ * This tag can be flexibly used to insert the value of an attribute into a + * page. As in other usages in Tiles, every attribute can be determined to have + * a "type", either set explicitly when it was defined, or "computed". If the + * type is not explicit, then if the attribute value is a valid definition, it + * will be inserted as such. Otherwise, if it begins with a "/" character, it + * will be treated as a "template". Finally, if it has not otherwise been + * assigned a type, it will be treated as a String and included without any + * special handling. + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertAttribute name="body" />
+ * 
+ */ +public class InsertAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertAttributeModel model = new org.apache.tiles.template.InsertAttributeModel(); + + /** + * If true, if an exception happens during rendering, of if the attribute is + * null, the problem will be ignored. + */ + private boolean ignore; + + /** + * The preparer to invoke before rendering the attribute. + */ + private java.lang.String preparer; + + /** + * A comma-separated list of roles. If present, the attribute will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The default value of the attribute. To use only if the attribute was not + * computed. + */ + private java.lang.Object defaultValue; + + /** + * The default comma-separated list of roles. To use only if the attribute was + * not computed. + */ + private java.lang.String defaultValueRole; + + /** + * The default type of the attribute. To use only if the attribute was not + * computed. + */ + private java.lang.String defaultValueType; + + /** + * The name of the attribute. + */ + private java.lang.String name; + + /** + * The attribute to use immediately, if not null. + */ + private org.apache.tiles.api.Attribute value; + + /** + * If true, the response will be flushed after the insert. + */ + private boolean flush; + + /** + * Getter for ignore property. + * + * @return If true, if an exception happens during rendering, of if the + * attribute is null, the problem will be ignored. + */ + public boolean isIgnore() { + return ignore; + } + + /** + * Setter for ignore property. + * + * @param ignore If true, if an exception happens during rendering, of if the + * attribute is null, the problem will be ignored. + */ + public void setIgnore(boolean ignore) { + this.ignore = ignore; + } + + /** + * Getter for preparer property. + * + * @return The preparer to invoke before rendering the attribute. + */ + public java.lang.String getPreparer() { + return preparer; + } + + /** + * Setter for preparer property. + * + * @param preparer The preparer to invoke before rendering the attribute. + */ + public void setPreparer(java.lang.String preparer) { + this.preparer = preparer; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the attribute will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the attribute will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for defaultValue property. + * + * @return The default value of the attribute. To use only if the attribute was + * not computed. + */ + public java.lang.Object getDefaultValue() { + return defaultValue; + } + + /** + * Setter for defaultValue property. + * + * @param defaultValue The default value of the attribute. To use only if the + * attribute was not computed. + */ + public void setDefaultValue(java.lang.Object defaultValue) { + this.defaultValue = defaultValue; + } + + /** + * Getter for defaultValueRole property. + * + * @return The default comma-separated list of roles. To use only if the + * attribute was not computed. + */ + public java.lang.String getDefaultValueRole() { + return defaultValueRole; + } + + /** + * Setter for defaultValueRole property. + * + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + */ + public void setDefaultValueRole(java.lang.String defaultValueRole) { + this.defaultValueRole = defaultValueRole; + } + + /** + * Getter for defaultValueType property. + * + * @return The default type of the attribute. To use only if the attribute was + * not computed. + */ + public java.lang.String getDefaultValueType() { + return defaultValueType; + } + + /** + * Setter for defaultValueType property. + * + * @param defaultValueType The default type of the attribute. To use only if the + * attribute was not computed. + */ + public void setDefaultValueType(java.lang.String defaultValueType) { + this.defaultValueType = defaultValueType; + } + + /** + * Getter for name property. + * + * @return The name of the attribute. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the attribute. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for value property. + * + * @return The attribute to use immediately, if not null. + */ + public org.apache.tiles.api.Attribute getValue() { + return value; + } + + /** + * Setter for value property. + * + * @param value The attribute to use immediately, if not null. + */ + public void setValue(org.apache.tiles.api.Attribute value) { + this.value = value; + } + + /** + * Getter for flush property. + * + * @return If true, the response will be flushed after the insert. + */ + public boolean isFlush() { + return flush; + } + + /** + * Setter for flush property. + * + * @param flush If true, the response will be flushed after the insert. + */ + public void setFlush(boolean flush) { + this.flush = flush; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(ignore, preparer, role, defaultValue, defaultValueRole, defaultValueType, name, value, flush, + request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertDefinitionTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertDefinitionTag.java new file mode 100644 index 0000000000..0beec1aa11 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertDefinitionTag.java @@ -0,0 +1,257 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Insert a definition. + *

+ *

+ * Insert a definition with the possibility to override and specify parameters + * (called attributes). A definition can be seen as a (partially or totally) + * filled template that can override or complete attribute values. + * <tiles:insertDefinition> allows to define these attributes and pass + * them to the inserted jsp page, called template. Attributes are defined using + * nested tag <tiles:putAttribute> or <tiles:putListAttribute>. + *

+ *

+ * You must specify name tag attribute, for inserting a definition from + * definitions factory. + *

+ *

+ * Example : + *

+ * + *
+ *     <tiles:insertDefinition name=".my.tiles.defininition flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertDefinition>
+ * 
+ */ +public class InsertDefinitionTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertDefinitionModel model = new org.apache.tiles.template.InsertDefinitionModel(); + + /** + * The name of the definition to render. + */ + private java.lang.String definitionName; + + /** + * If specified, this template will be used instead of the one used by the + * definition. + */ + private java.lang.String template; + + /** + * The type of the template attribute. + */ + private java.lang.String templateType; + + /** + * The expression to evaluate to get the value of the template. + */ + private java.lang.String templateExpression; + + /** + * A comma-separated list of roles. If present, the definition will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The preparer to use to invoke before the definition is rendered. If + * specified, it overrides the preparer specified in the definition itself. + */ + private java.lang.String preparer; + + /** + * If true, the response will be flushed after the insert. + */ + private boolean flush; + + /** + * Getter for name property. + * + * @return The name of the definition to render. + */ + public java.lang.String getName() { + return definitionName; + } + + /** + * Setter for name property. + * + * @param definitionName The name of the definition to render. + */ + public void setName(java.lang.String definitionName) { + this.definitionName = definitionName; + } + + /** + * Getter for template property. + * + * @return If specified, this template will be used instead of the one used by + * the definition. + */ + public java.lang.String getTemplate() { + return template; + } + + /** + * Setter for template property. + * + * @param template If specified, this template will be used instead of the one + * used by the definition. + */ + public void setTemplate(java.lang.String template) { + this.template = template; + } + + /** + * Getter for templateType property. + * + * @return The type of the template attribute. + */ + public java.lang.String getTemplateType() { + return templateType; + } + + /** + * Setter for templateType property. + * + * @param templateType The type of the template attribute. + */ + public void setTemplateType(java.lang.String templateType) { + this.templateType = templateType; + } + + /** + * Getter for templateExpression property. + * + * @return The expression to evaluate to get the value of the template. + */ + public java.lang.String getTemplateExpression() { + return templateExpression; + } + + /** + * Setter for templateExpression property. + * + * @param templateExpression The expression to evaluate to get the value of the + * template. + */ + public void setTemplateExpression(java.lang.String templateExpression) { + this.templateExpression = templateExpression; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the definition will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the definition will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for preparer property. + * + * @return The preparer to use to invoke before the definition is rendered. If + * specified, it overrides the preparer specified in the definition + * itself. + */ + public java.lang.String getPreparer() { + return preparer; + } + + /** + * Setter for preparer property. + * + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified + * in the definition itself. + */ + public void setPreparer(java.lang.String preparer) { + this.preparer = preparer; + } + + /** + * Getter for flush property. + * + * @return If true, the response will be flushed after the insert. + */ + public boolean isFlush() { + return flush; + } + + /** + * Setter for flush property. + * + * @param flush If true, the response will be flushed after the insert. + */ + public void setFlush(boolean flush) { + this.flush = flush; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(definitionName, template, templateType, templateExpression, role, preparer, flush, request, + modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertTemplateTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertTemplateTag.java new file mode 100644 index 0000000000..afe633881a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertTemplateTag.java @@ -0,0 +1,230 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Insert a template. + *

+ *

+ * Insert a template with the possibility to pass parameters (called + * attributes). A template can be seen as a procedure that can take parameters + * or attributes. <tiles:insertTemplate> allows to define these attributes + * and pass them to the inserted jsp page, called template. Attributes are + * defined using nested tag <tiles:putAttribute> or + * <tiles:putListAttribute>. + *

+ *

+ * You must specify template attribute, for inserting a template + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertTemplate template="/basic/myLayout.jsp" flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertTemplate>
+ * 
+ */ +public class InsertTemplateTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertTemplateModel model = new org.apache.tiles.template.InsertTemplateModel(); + + /** + * The template to render. + */ + private java.lang.String template; + + /** + * The type of the template attribute. + */ + private java.lang.String templateType; + + /** + * The expression to evaluate to get the value of the template. + */ + private java.lang.String templateExpression; + + /** + * A comma-separated list of roles. If present, the template will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The preparer to use to invoke before the definition is rendered. If + * specified, it overrides the preparer specified in the definition itself. + */ + private java.lang.String preparer; + + /** + * If true, the response will be flushed after the insert. + */ + private boolean flush; + + /** + * Getter for template property. + * + * @return The template to render. + */ + public java.lang.String getTemplate() { + return template; + } + + /** + * Setter for template property. + * + * @param template The template to render. + */ + public void setTemplate(java.lang.String template) { + this.template = template; + } + + /** + * Getter for templateType property. + * + * @return The type of the template attribute. + */ + public java.lang.String getTemplateType() { + return templateType; + } + + /** + * Setter for templateType property. + * + * @param templateType The type of the template attribute. + */ + public void setTemplateType(java.lang.String templateType) { + this.templateType = templateType; + } + + /** + * Getter for templateExpression property. + * + * @return The expression to evaluate to get the value of the template. + */ + public java.lang.String getTemplateExpression() { + return templateExpression; + } + + /** + * Setter for templateExpression property. + * + * @param templateExpression The expression to evaluate to get the value of the + * template. + */ + public void setTemplateExpression(java.lang.String templateExpression) { + this.templateExpression = templateExpression; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the template will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the template will be + * rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for preparer property. + * + * @return The preparer to use to invoke before the definition is rendered. If + * specified, it overrides the preparer specified in the definition + * itself. + */ + public java.lang.String getPreparer() { + return preparer; + } + + /** + * Setter for preparer property. + * + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified + * in the definition itself. + */ + public void setPreparer(java.lang.String preparer) { + this.preparer = preparer; + } + + /** + * Getter for flush property. + * + * @return If true, the response will be flushed after the insert. + */ + public boolean isFlush() { + return flush; + } + + /** + * Setter for flush property. + * + * @param flush If true, the response will be flushed after the insert. + */ + public void setFlush(boolean flush) { + this.flush = flush; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(template, templateType, templateExpression, role, preparer, flush, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutAttributeTag.java new file mode 100644 index 0000000000..c4fa7c91c6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutAttributeTag.java @@ -0,0 +1,233 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Put an attribute in enclosing attribute container tag. + *

+ *

+ * Enclosing attribute container tag can be : + *

    + *
  • <initContainer>
  • + *
  • <definition>
  • + *
  • <insertAttribute>
  • + *
  • <insertDefinition>
  • + *
  • <putListAttribute>
  • + *
+ * (or any other tag which implements the PutAttributeTagParent interface. + * Exception is thrown if no appropriate tag can be found. + *

+ *

+ * Put tag can have following atributes : + *

    + *
  • name : Name of the attribute
  • + *
  • value : value to put as attribute
  • + *
  • type : value type. Possible type are : string (value is used as direct + * string), template (value is used as a page url to insert), definition (value + * is used as a definition name to insert), object (value is used as it is)
  • + *
  • role : Role to check when 'insertAttribute' will be called.
  • + *
+ *

+ *

+ * Value can also come from tag body. Tag body is taken into account only if + * value is not set by one of the tag attributes. In this case Attribute type is + * "string", unless tag body define another type. + *

+ */ +public class PutAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.PutAttributeModel model = new org.apache.tiles.template.PutAttributeModel(); + + /** + * The name of the attribute to put. + */ + private java.lang.String name; + + /** + * The value of the attribute. Use this parameter, or expression, or body. + */ + private java.lang.Object value; + + /** + * The expression to calculate the value from. Use this parameter, or value, or + * body. + */ + private java.lang.String expression; + + /** + * A comma-separated list of roles. If present, the attribute will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The type (renderer) of the attribute. + */ + private java.lang.String type; + + /** + * If true the attribute will be cascaded to all nested attributes. + */ + private boolean cascade; + + /** + * Getter for name property. + * + * @return The name of the attribute to put. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the attribute to put. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for value property. + * + * @return The value of the attribute. Use this parameter, or expression, or + * body. + */ + public java.lang.Object getValue() { + return value; + } + + /** + * Setter for value property. + * + * @param value The value of the attribute. Use this parameter, or expression, + * or body. + */ + public void setValue(java.lang.Object value) { + this.value = value; + } + + /** + * Getter for expression property. + * + * @return The expression to calculate the value from. Use this parameter, or + * value, or body. + */ + public java.lang.String getExpression() { + return expression; + } + + /** + * Setter for expression property. + * + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + */ + public void setExpression(java.lang.String expression) { + this.expression = expression; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the attribute will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the attribute will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for type property. + * + * @return The type (renderer) of the attribute. + */ + public java.lang.String getType() { + return type; + } + + /** + * Setter for type property. + * + * @param type The type (renderer) of the attribute. + */ + public void setType(java.lang.String type) { + this.type = type; + } + + /** + * Getter for cascade property. + * + * @return If true the attribute will be cascaded to all nested attributes. + */ + public boolean isCascade() { + return cascade; + } + + /** + * Setter for cascade property. + * + * @param cascade If true the attribute will be cascaded to all nested + * attributes. + */ + public void setCascade(boolean cascade) { + this.cascade = cascade; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(name, value, expression, role, type, cascade, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutListAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutListAttributeTag.java new file mode 100644 index 0000000000..1e96972c7d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutListAttributeTag.java @@ -0,0 +1,164 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Declare a list that will be pass as attribute to tile. + *

+ *

+ * Declare a list that will be pass as attribute to tile. List elements are + * added using the tags 'addAttribute' or 'addListAttribute'. This tag can only + * be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. + *

+ */ +public class PutListAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.PutListAttributeModel model = new org.apache.tiles.template.PutListAttributeModel(); + + /** + * The name of the attribute to put. + */ + private java.lang.String name; + + /** + * A comma-separated list of roles. If present, the attribute will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * If true, the list attribute will use, as first elements, the list contained + * in the list attribute, put with the same name, of the containing definition. + */ + private boolean inherit; + + /** + * If true the attribute will be cascaded to all nested attributes. + */ + private boolean cascade; + + /** + * Getter for name property. + * + * @return The name of the attribute to put. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the attribute to put. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the attribute will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the attribute will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for inherit property. + * + * @return If true, the list attribute will use, as first elements, the list + * contained in the list attribute, put with the same name, of the + * containing definition. + */ + public boolean isInherit() { + return inherit; + } + + /** + * Setter for inherit property. + * + * @param inherit If true, the list attribute will use, as first elements, the + * list contained in the list attribute, put with the same name, + * of the containing definition. + */ + public void setInherit(boolean inherit) { + this.inherit = inherit; + } + + /** + * Getter for cascade property. + * + * @return If true the attribute will be cascaded to all nested attributes. + */ + public boolean isCascade() { + return cascade; + } + + /** + * Setter for cascade property. + * + * @param cascade If true the attribute will be cascaded to all nested + * attributes. + */ + public void setCascade(boolean cascade) { + this.cascade = cascade; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(name, role, inherit, cascade, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/SetCurrentContainerTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/SetCurrentContainerTag.java new file mode 100644 index 0000000000..370f3b4185 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/SetCurrentContainerTag.java @@ -0,0 +1,80 @@ +/* + * 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. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + * Selects a container to be used as the "current" container. + */ +public class SetCurrentContainerTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.SetCurrentContainerModel model = new org.apache.tiles.template.SetCurrentContainerModel(); + + /** + * The key of the container to be used as "current". If null, the default one + * will be used. + */ + private java.lang.String containerKey; + + /** + * Getter for containerKey property. + * + * @return The key of the container to be used as "current". If null, the + * default one will be used. + */ + public java.lang.String getContainerKey() { + return containerKey; + } + + /** + * Setter for containerKey property. + * + * @param containerKey The key of the container to be used as "current". If + * null, the default one will be used. + */ + public void setContainerKey(java.lang.String containerKey) { + this.containerKey = containerKey; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(containerKey, request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/UseAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/UseAttributeTag.java new file mode 100644 index 0000000000..e2740e56cd --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/UseAttributeTag.java @@ -0,0 +1,214 @@ +/* + * 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.apache.tiles.web.jsp.taglib; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.jsp.autotag.JspAutotagRuntime; +import org.apache.tiles.template.ImportAttributeModel; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; +import javax.servlet.jsp.tagext.TagData; +import javax.servlet.jsp.tagext.TagExtraInfo; +import javax.servlet.jsp.tagext.VariableInfo; +import java.io.IOException; + +/** + * Exposes am attribute as a scripting variable within the page. + * + * @since Tiles 1.0 + */ +public class UseAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private final ImportAttributeModel model = new ImportAttributeModel(); + + /** + * The id of the imported scripting variable. + */ + private String id; + + /** + * The scope name. + */ + private String scopeName = null; + + /** + * The name of the attribute. + */ + private String name = null; + + /** + * Flag that, if true, ignores exceptions. + */ + private boolean ignore = false; + + /** + * Class name of object. + */ + private String classname = null; + + /** + * Returns the id of the imported scripting variable. + * + * @return The id of the imported scripting variable. + * @since 2.2.0 + */ + public String getId() { + return id; + } + + /** + * Sets the id of the imported scripting variable. + * + * @param id The id of the imported scripting variable. + * @since 2.2.0 + */ + public void setId(String id) { + this.id = id; + } + + /** + * Set the scope. + * + * @param scope Scope. + */ + public void setScope(String scope) { + this.scopeName = scope; + } + + /** + * Get scope. + * + * @return Scope. + */ + public String getScope() { + return scopeName; + } + + /** + * Get the name. + * + * @return Name. + */ + public String getName() { + return name; + } + + /** + * Set the name. + * + * @param name The new name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Set ignore flag. + * + * @param ignore default: false: Exception is thrown when attribute is not + * found, set to true to ignore missing attributes silently + */ + public void setIgnore(boolean ignore) { + this.ignore = ignore; + } + + /** + * Get ignore flag. + * + * @return default: false: Exception is thrown when attribute is not found, set + * to true to ignore missing attributes silently + */ + public boolean isIgnore() { + return ignore; + } + + /** + * Get class name. + * + * @return class name + */ + public String getClassname() { + return classname; + + } + + /** + * Set the class name. + * + * @param name The new class name. + */ + public void setClassname(String name) { + this.classname = name; + } + + /** + * {@inheritDoc} + */ + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new JspAutotagRuntime(); + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + Request request = runtime.createRequest(); + model.execute(name, scopeName, id, ignore, request); + } + + /** + * Returns the scripting variable to use. + * + * @return The scripting variable. + */ + public String getScriptingVariable() { + return id == null ? getName() : id; + } + + /** + * Implementation of TagExtraInfo which identifies the scripting object(s) to be + * made visible. + */ + public static class Tei extends TagExtraInfo { + + /** + * {@inheritDoc} + */ + @Override + public VariableInfo[] getVariableInfo(TagData data) { + String classname = data.getAttributeString("classname"); + if (classname == null) { + classname = "java.lang.Object"; + } + + String id = data.getAttributeString("id"); + if (id == null) { + id = data.getAttributeString("name"); + } + + return new VariableInfo[] { new VariableInfo(id, classname, true, VariableInfo.AT_END) }; + + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/package-info.java new file mode 100644 index 0000000000..0c9e72cd0d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +/** + * The "tiles-jsp" tag library contains tags that are useful to create + * templates, subpages other reusable view parts using the "tiles-core" package. + */ +package org.apache.tiles.web.jsp.taglib; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/startup/AbstractTilesListener.java b/plugins/tiles/src/main/java/org/apache/tiles/web/startup/AbstractTilesListener.java new file mode 100644 index 0000000000..465431b06a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/startup/AbstractTilesListener.java @@ -0,0 +1,69 @@ +/* + * 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.apache.tiles.web.startup; + +import org.apache.tiles.core.startup.TilesInitializer; +import org.apache.tiles.request.servlet.ServletApplicationContext; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +/** + * Listener for the initialization of the Tiles container. + */ +public abstract class AbstractTilesListener implements ServletContextListener { + + /** + * The initializer object. + * + * @since 2.1.2 + */ + protected TilesInitializer initializer; + + /** + * Initialize the TilesContainer and place it + * into service. + * + * @param event The intercepted event. + */ + public void contextInitialized(ServletContextEvent event) { + ServletContext servletContext = event.getServletContext(); + initializer = createTilesInitializer(); + initializer.initialize(new ServletApplicationContext(servletContext)); + } + + /** + * Destroys the initializer. + * + * @param event The intercepted event. + */ + public void contextDestroyed(ServletContextEvent event) { + initializer.destroy(); + } + + /** + * Creates a new instance of {@link TilesInitializer}. Implement it to use a + * different initializer. + * + * @return The Tiles servlet-based initializer. + * @since 2.2.0 + */ + protected abstract TilesInitializer createTilesInitializer(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/startup/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/web/startup/package-info.java new file mode 100644 index 0000000000..6dc2fd3d2c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/startup/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Classes to start the Tiles engine up in a web environment. + */ +package org.apache.tiles.web.startup; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/util/AttributeContextMutator.java b/plugins/tiles/src/main/java/org/apache/tiles/web/util/AttributeContextMutator.java new file mode 100644 index 0000000000..aa99ca0998 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/util/AttributeContextMutator.java @@ -0,0 +1,42 @@ +/* + * 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.apache.tiles.web.util; + +import org.apache.tiles.api.AttributeContext; + +import javax.servlet.ServletRequest; + +/** + * It represents an object able to manipulate a AttributeContext. + * In other words, it is able to add, replace and remove attributes from the + * AttributeContext. + * + * @since Tiles 2.0 + */ +public interface AttributeContextMutator { + + /** + * Mutate a AttributeContext. + * + * @param context The attribute context to mutate. + * @param request The current servlet request. + */ + void mutate(AttributeContext context, ServletRequest request); + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/util/TilesDispatchServlet.java b/plugins/tiles/src/main/java/org/apache/tiles/web/util/TilesDispatchServlet.java new file mode 100644 index 0000000000..d456848c89 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/util/TilesDispatchServlet.java @@ -0,0 +1,148 @@ +/* + * 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.apache.tiles.web.util; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.reflect.ClassUtil; +import org.apache.tiles.request.servlet.ServletRequest; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Tiles dispatching servlet. Used to invoke + * a definition directly. + */ +public class TilesDispatchServlet extends HttpServlet { + + /** + * Init parameter to define the key of the container to use. + * + * @since 2.1.2 + */ + public static final String CONTAINER_KEY_INIT_PARAMETER = + "org.apache.tiles.web.util.TilesDispatchServlet.CONTAINER_KEY"; + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(TilesDispatchServlet.class); + + /** + * The key under which the container is stored. + */ + private String containerKey; + + /** + * The object that will mutate the attribute context so that it uses + * different attributes. + */ + private org.apache.tiles.web.util.AttributeContextMutator mutator; + + + /** + * {@inheritDoc} + */ + @Override + public void init() throws ServletException { + super.init(); + + containerKey = getServletConfig().getInitParameter( + CONTAINER_KEY_INIT_PARAMETER); + + String temp = getInitParameter("mutator"); + if (temp != null) { + try { + mutator = (org.apache.tiles.web.util.AttributeContextMutator) ClassUtil.instantiate(temp); + } catch (Exception e) { + throw new ServletException("Unable to instantiate specified context mutator.", e); + } + } else { + mutator = new DefaultMutator(); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse res) { + + ApplicationContext applicationContext = org.apache.tiles.request.servlet.ServletUtil + .getApplicationContext(getServletContext()); + Request request = new ServletRequest(applicationContext, + req, res); + TilesContainer container = TilesAccess.getContainer(applicationContext, + containerKey); + mutator.mutate(container.getAttributeContext(request), req); + String definition = getDefinitionName(req); + if (LOG.isDebugEnabled()) { + LOG.info("Dispatching to tile '{}'", definition); + } + container.render(definition, request); + } + + /** + * Returns the called definition name for the given request. + * + * @param request The request to parse. + * @return The definition name to render. + */ + protected String getDefinitionName(HttpServletRequest request) { + String path = (String) request.getAttribute("javax.servlet.include.servlet_path"); + if (path == null) { + path = request.getServletPath(); + } + + int start = path.startsWith("/") ? 1 : 0; + int end = path.endsWith(".tiles") ? path.indexOf(".tiles") : path.length(); + + return path.substring(start, end); + } + + /** + * {@inheritDoc} + */ + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse res) { + LOG.info("Tiles dispatch request received. Redirecting POST to GET."); + doGet(req, res); + } + + /** + * Default no-op mutator. + */ + static class DefaultMutator implements AttributeContextMutator { + + /** + * {@inheritDoc} + */ + public void mutate(AttributeContext context, javax.servlet.ServletRequest request) { + // noop; + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/util/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/web/util/package-info.java new file mode 100644 index 0000000000..4a373d94fa --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/util/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * 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. + */ +/** + * Utility classes to use Tiles in a servlet environment. + */ +package org.apache.tiles.web.util; diff --git a/plugins/tiles/src/main/resources/META-INF/template-suite.xml b/plugins/tiles/src/main/resources/META-INF/template-suite.xml new file mode 100644 index 0000000000..3d0a48ec5d --- /dev/null +++ b/plugins/tiles/src/main/resources/META-INF/template-suite.xml @@ -0,0 +1,1188 @@ + + + tiles + This tag library provides Tiles tags. + + + org.apache.tiles.template.InsertDefinitionModel + + org.apache.tiles.template.InsertDefinitionModel + insertDefinition + InsertDefinition + <p> +Insert a definition. +</p> +<p> +Insert a definition with the possibility to override and specify parameters +(called attributes). A definition can be seen as a (partially or totally) +filled template that can override or complete attribute values. +&lt;tiles:insertDefinition&gt; allows to define these attributes +and pass them to the inserted jsp page, called template. Attributes are +defined using nested tag &lt;tiles:putAttribute&gt; or +&lt;tiles:putListAttribute&gt;. +</p> +<p> +You must specify name tag attribute, for inserting a definition from definitions factory. +</p> +<p> +Example : +</p> + +<pre> + &lt;tiles:insertDefinition name=&quot;.my.tiles.defininition flush=&quot;true&quot;&gt; + &lt;tiles:putAttribute name=&quot;title&quot; value=&quot;My first page&quot; /&gt; + &lt;tiles:putAttribute name=&quot;header&quot; value=&quot;/common/header.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;footer&quot; value=&quot;/common/footer.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;menu&quot; value=&quot;/basic/menu.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;body&quot; value=&quot;/basic/helloBody.jsp&quot; /&gt; + &lt;/tiles:insertDefinition&gt; +</pre> + + execute + Executes the operation. + + + definitionName + + definitionName + name + The name of the definition to render. + java.lang.String + true + false + + + + template + + template + template + If specified, this template will be used instead of the one used by the definition. + java.lang.String + false + false + + + + templateType + + templateType + templateType + The type of the template attribute. + java.lang.String + false + false + + + + templateExpression + + templateExpression + templateExpression + The expression to evaluate to get the value of the template. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the definition +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + preparer + + preparer + preparer + The preparer to use to invoke before the definition is +rendered. If specified, it overrides the preparer specified in the definition itself. + java.lang.String + false + false + + + + flush + + flush + flush + If true, the response will be flushed after the insert. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.ImportAttributeModel + + org.apache.tiles.template.ImportAttributeModel + importAttribute + ImportAttribute + <p> +Import attribute(s) in specified context. +</p> +<p> +Import attribute(s) to requested scope. Attribute name and scope are +optional. If not specified, all attributes are imported in page scope. Once +imported, an attribute can be used as any other beans from jsp contexts. +</p> + + execute + Executes the model. + + + name + + name + name + The name of the attribute to import. If it is null, all the attributes will be imported. + java.lang.String + false + false + + + + scope + + scope + scope + The scope into which the attribute(s) will be imported. If +null, the import will go in page scope. + java.lang.String + false + false + + + + toName + + toName + toName + The name of the attribute into which the attribute will be +imported. To be used in conjunction to name. If null, the value of name will be used. + java.lang.String + false + false + + + + ignore + + ignore + ignore + If true, if the attribute is not present, the problem will be ignored. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + + + + + org.apache.tiles.template.SetCurrentContainerModel + + org.apache.tiles.template.SetCurrentContainerModel + setCurrentContainer + SetCurrentContainer + Selects a container to be used as the "current" container. + + execute + Executes the model. + + + containerKey + + containerKey + containerKey + The key of the container to be used as "current". If null, the default one will be used. + java.lang.String + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + + + + + org.apache.tiles.template.AddListAttributeModel + + org.apache.tiles.template.AddListAttributeModel + addListAttribute + AddListAttribute + <p> +Declare a list that will be pass as an attribute. +</p> +<p> +Declare a list that will be pass as an attribute . List elements are added +using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used +inside 'insertTemplate', 'insertDefinition' or 'definition' tag. +</p> + + execute + Executes the model. + + + role + + role + role + The comma-separated list of roles that can use the list attribute. + java.lang.String + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.GetAsStringModel + + org.apache.tiles.template.GetAsStringModel + getAsString + GetAsString + <p> + Render the value of the specified template attribute to the current Writer +</p> + +<p> +Retrieve the value of the specified template attribute property, and render +it to the current Writer as a String. The usual toString() conversions is applied on found value. +</p> + + execute + Executes the operation. + + + ignore + + ignore + ignore + If true, if an exception happens during +rendering, of if the attribute is null, the problem will be ignored. + boolean + false + false + + + + preparer + + preparer + preparer + The preparer to invoke before rendering the attribute. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the attribute +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + defaultValue + + defaultValue + defaultValue + The default value of the attribute. To use only if +the attribute was not computed. + java.lang.Object + false + false + + + + defaultValueRole + + defaultValueRole + defaultValueRole + The default comma-separated list of roles. To use +only if the attribute was not computed. + java.lang.String + false + false + + + + defaultValueType + + defaultValueType + defaultValueType + The default type of the attribute. To use only if +the attribute was not computed. + java.lang.String + false + false + + + + name + + name + name + The name of the attribute. + java.lang.String + true + false + + + + value + + value + value + The attribute to use immediately, if not null. + org.apache.tiles.api.Attribute + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.InsertAttributeModel + + org.apache.tiles.template.InsertAttributeModel + insertAttribute + InsertAttribute + <p> +Inserts the value of an attribute into the page. +</p> +<p> +This tag can be flexibly used to insert the value of an attribute into a +page. As in other usages in Tiles, every attribute can be determined to have +a "type", either set explicitly when it was defined, or "computed". If the +type is not explicit, then if the attribute value is a valid definition, it +will be inserted as such. Otherwise, if it begins with a "/" character, it +will be treated as a "template". Finally, if it has not otherwise been +assigned a type, it will be treated as a String and included without any special handling. +</p> + +<p> +Example : +</p> + +<pre> + &lt;tiles:insertAttribute name=&quot;body&quot; /&gt; +</pre> + + execute + Executes the operation. + + + ignore + + ignore + ignore + If true, if an exception happens during +rendering, of if the attribute is null, the problem will be ignored. + boolean + false + false + + + + preparer + + preparer + preparer + The preparer to invoke before rendering the attribute. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the attribute +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + defaultValue + + defaultValue + defaultValue + The default value of the attribute. To use only if +the attribute was not computed. + java.lang.Object + false + false + + + + defaultValueRole + + defaultValueRole + defaultValueRole + The default comma-separated list of roles. To use +only if the attribute was not computed. + java.lang.String + false + false + + + + defaultValueType + + defaultValueType + defaultValueType + The default type of the attribute. To use only if +the attribute was not computed. + java.lang.String + false + false + + + + name + + name + name + The name of the attribute. + java.lang.String + false + false + + + + value + + value + value + The attribute to use immediately, if not null. + org.apache.tiles.api.Attribute + false + false + + + + flush + + flush + flush + If true, the response will be flushed after the insert. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.PutAttributeModel + + org.apache.tiles.template.PutAttributeModel + putAttribute + PutAttribute + <p> +Put an attribute in enclosing attribute container tag. +</p> +<p> +Enclosing attribute container tag can be : +<ul> +<li>&lt;initContainer&gt;</li> +<li>&lt;definition&gt;</li> +<li>&lt;insertAttribute&gt;</li> +<li>&lt;insertDefinition&gt;</li> +<li>&lt;putListAttribute&gt;</li> +</ul> +(or any other tag which implements the PutAttributeTagParent +interface. Exception is thrown if no appropriate tag can be found. +</p> +<p> +Put tag can have following atributes : +<ul> +<li>name : Name of the attribute</li> +<li>value : value to put as attribute</li> +<li>type : value type. Possible type are : string (value is used as direct +string), template (value is used as a page url to insert), definition (value +is used as a definition name to insert), object (value is used as it is)</li> +<li>role : Role to check when 'insertAttribute' will be called.</li> +</ul> +</p> +<p> +Value can also come from tag body. Tag body is taken into account only if +value is not set by one of the tag attributes. In this case Attribute type is +"string", unless tag body define another type. +</p> + + execute + Executes the operation. + + + name + + name + name + The name of the attribute to put. + java.lang.String + true + false + + + + value + + value + value + The value of the attribute. Use this parameter, or expression, or body. + java.lang.Object + false + false + + + + expression + + expression + expression + The expression to calculate the value from. Use this +parameter, or value, or body. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the attribute +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + type + + type + type + The type (renderer) of the attribute. + java.lang.String + false + false + + + + cascade + + cascade + cascade + If true the attribute will be cascaded to all nested attributes. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.DefinitionModel + + org.apache.tiles.template.DefinitionModel + definition + Definition + <p> +Create a definition at runtime. +</p> +<p> +Create a new definition at runtime. Newly created definition will be +available across the entire request. +</p> + + execute + Executes the operation. + + + name + + name + name + The name of the definition to create. If not specified, an +anonymous definition will be created. + java.lang.String + false + false + + + + template + + template + template + The template of this definition. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the definition +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + extendsParam + + extendsParam + extends + The definition name that this definition extends. + java.lang.String + false + false + + + + preparer + + preparer + preparer + The preparer to use to invoke before the definition is rendered. + java.lang.String + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.AddAttributeModel + + org.apache.tiles.template.AddAttributeModel + addAttribute + AddAttribute + <p> +Add an element to the surrounding list. Equivalent to 'putAttribute', +but for list element. +</p> + +<p> +Add an element to the surrounding list. This tag can only be used inside +'putListAttribute' or 'addListAttribute' tags. Value can come from a direct +assignment (value="aValue") +</p> + + execute + Executes the operation. + + + value + + value + value + The value of the attribute. Use this parameter, or expression, or body. + java.lang.Object + false + false + + + + expression + + expression + expression + The expression to calculate the value from. Use this +parameter, or value, or body. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the attribute +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + type + + type + type + The type (renderer) of the attribute. + java.lang.String + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.PutListAttributeModel + + org.apache.tiles.template.PutListAttributeModel + putListAttribute + PutListAttribute + <p> +Declare a list that will be pass as attribute to tile. +</p> +<p> +Declare a list that will be pass as attribute to tile. List elements are +added using the tags 'addAttribute' or 'addListAttribute'. This tag can only +be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. +</p> + + execute + Executes the model. + + + name + + name + name + The name of the attribute to put. + java.lang.String + true + false + + + + role + + role + role + A comma-separated list of roles. If present, the attribute +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + inherit + + inherit + inherit + If true, the list attribute will use, as first elements, the +list contained in the list attribute, put with the same name, of the containing definition. + boolean + false + false + + + + cascade + + cascade + cascade + If true the attribute will be cascaded to all nested attributes. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.InsertTemplateModel + + org.apache.tiles.template.InsertTemplateModel + insertTemplate + InsertTemplate + <p> +Insert a template. +</p> +<p> +Insert a template with the possibility to pass parameters (called +attributes). A template can be seen as a procedure that can take parameters +or attributes. &lt;tiles:insertTemplate&gt; allows to define +these attributes and pass them to the inserted jsp page, called template. +Attributes are defined using nested tag +&lt;tiles:putAttribute&gt; or +&lt;tiles:putListAttribute&gt;. +</p> +<p> +You must specify template attribute, for inserting a template +</p> + +<p> +Example : +</p> + +<pre> + &lt;tiles:insertTemplate template=&quot;/basic/myLayout.jsp&quot; flush=&quot;true&quot;&gt; + &lt;tiles:putAttribute name=&quot;title&quot; value=&quot;My first page&quot; /&gt; + &lt;tiles:putAttribute name=&quot;header&quot; value=&quot;/common/header.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;footer&quot; value=&quot;/common/footer.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;menu&quot; value=&quot;/basic/menu.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;body&quot; value=&quot;/basic/helloBody.jsp&quot; /&gt; + &lt;/tiles:insertTemplate&gt; +</pre> + + execute + Executes the operation. + + + template + + template + template + The template to render. + java.lang.String + true + false + + + + templateType + + templateType + templateType + The type of the template attribute. + java.lang.String + false + false + + + + templateExpression + + templateExpression + templateExpression + The expression to evaluate to get the value of the template. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the template +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + preparer + + preparer + preparer + The preparer to use to invoke before the definition is +rendered. If specified, it overrides the preparer specified in the +definition itself. + java.lang.String + false + false + + + + flush + + flush + flush + If true, the response will be flushed after the insert. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + \ No newline at end of file diff --git a/plugins/tiles/src/main/resources/META-INF/tld/tiles-extras-jsp.tld b/plugins/tiles/src/main/resources/META-INF/tld/tiles-extras-jsp.tld new file mode 100644 index 0000000000..4ba058ebe5 --- /dev/null +++ b/plugins/tiles/src/main/resources/META-INF/tld/tiles-extras-jsp.tld @@ -0,0 +1,105 @@ + + + + + This tag library provides Tiles tags.

+ ]]> +
+ 1.2 + tilesx + http://tiles.apache.org/tags-tiles-extras + + + Use attribute value inside page.

+

Declare a Java variable, and an attribute in the specified scope, using its attribute + value.

+

Java variable and attribute will have the name specified by 'id', or the original name + if not specified.

+ ]]> +
+ useAttribute + org.apache.tiles.web.jsp.taglib.UseAttributeTag + org.apache.tiles.web.jsp.taglib.UseAttributeTag$Tei + empty + + + Declared attribute and variable name.

+ ]]> +
+ id + false + true +
+ + + Class of the declared variable.

+ ]]> +
+ classname + false + true +
+ + + Scope of the declared attribute. Default to 'page'.

+ ]]> +
+ scope + false + false +
+ + + Attribute name.

+ ]]> +
+ name + true + true +
+ + + + If this attribute is set to true, and the attribute specified by the name does not exist, + simply return without error. The default value is false, which will cause a runtime + exception to be thrown. +

+ ]]> +
+ ignore + false + true + boolean +
+
+
+ diff --git a/plugins/tiles/src/main/resources/META-INF/tld/tiles-jsp.tld b/plugins/tiles/src/main/resources/META-INF/tld/tiles-jsp.tld new file mode 100644 index 0000000000..defe3ef55e --- /dev/null +++ b/plugins/tiles/src/main/resources/META-INF/tld/tiles-jsp.tld @@ -0,0 +1,922 @@ + + + + + + + + 1.2 + tiles + http://tiles.apache.org/tags-tiles + + + + Insert a definition. +

+

+ Insert a definition with the possibility to override and specify parameters + (called attributes). A definition can be seen as a (partially or totally) + filled template that can override or complete attribute values. + <tiles:insertDefinition> allows to define these attributes + and pass them to the inserted jsp page, called template. Attributes are + defined using nested tag <tiles:putAttribute> or + <tiles:putListAttribute>. +

+

+ You must specify name tag attribute, for inserting a definition from definitions factory. +

+

+ Example : +

+ +
+          <tiles:insertDefinition name=".my.tiles.defininition flush="true">
+              <tiles:putAttribute name="title" value="My first page" />
+              <tiles:putAttribute name="header" value="/common/header.jsp" />
+              <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+              <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+              <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+          </tiles:insertDefinition>
+      
+ ]]> +
+ insertDefinition + org.apache.tiles.web.jsp.taglib.InsertDefinitionTag + scriptless + + + + + name + true + true + java.lang.String + + + + + + template + false + true + java.lang.String + + + + + + templateType + false + true + java.lang.String + + + + + + templateExpression + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + preparer + false + true + java.lang.String + + + + + + flush + false + true + boolean + +
+ + + + Import attribute(s) in specified context. +

+

+ Import attribute(s) to requested scope. Attribute name and scope are + optional. If not specified, all attributes are imported in page scope. Once + imported, an attribute can be used as any other beans from jsp contexts. +

+ ]]> +
+ importAttribute + org.apache.tiles.web.jsp.taglib.ImportAttributeTag + empty + + + + + name + false + true + java.lang.String + + + + + + scope + false + true + java.lang.String + + + + + + toName + false + true + java.lang.String + + + + + + ignore + false + true + boolean + +
+ + + + + setCurrentContainer + org.apache.tiles.web.jsp.taglib.SetCurrentContainerTag + empty + + + + + containerKey + false + true + java.lang.String + + + + + + Declare a list that will be pass as an attribute. +

+

+ Declare a list that will be pass as an attribute . List elements are added + using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used + inside 'insertTemplate', 'insertDefinition' or 'definition' tag. +

+ ]]> +
+ addListAttribute + org.apache.tiles.web.jsp.taglib.AddListAttributeTag + scriptless + + + + + role + false + true + java.lang.String + +
+ + + + Render the value of the specified template attribute to the current Writer +

+ +

+ Retrieve the value of the specified template attribute property, and render + it to the current Writer as a String. The usual toString() conversions is applied on found value. +

+ ]]> +
+ getAsString + org.apache.tiles.web.jsp.taglib.GetAsStringTag + scriptless + + + + + ignore + false + true + boolean + + + + + + preparer + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + defaultValue + false + true + java.lang.Object + + + + + + defaultValueRole + false + true + java.lang.String + + + + + + defaultValueType + false + true + java.lang.String + + + + + + name + true + true + java.lang.String + + + + + + value + false + true + org.apache.tiles.api.Attribute + +
+ + + + Inserts the value of an attribute into the page. +

+

+ This tag can be flexibly used to insert the value of an attribute into a + page. As in other usages in Tiles, every attribute can be determined to have + a "type", either set explicitly when it was defined, or "computed". If the + type is not explicit, then if the attribute value is a valid definition, it + will be inserted as such. Otherwise, if it begins with a "/" character, it + will be treated as a "template". Finally, if it has not otherwise been + assigned a type, it will be treated as a String and included without any special handling. +

+ +

+ Example : +

+ +
+          <tiles:insertAttribute name="body" />
+      
+ ]]> +
+ insertAttribute + org.apache.tiles.web.jsp.taglib.InsertAttributeTag + scriptless + + + + + ignore + false + true + boolean + + + + + + preparer + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + defaultValue + false + true + java.lang.Object + + + + + + defaultValueRole + false + true + java.lang.String + + + + + + defaultValueType + false + true + java.lang.String + + + + + + name + false + true + java.lang.String + + + + + + value + false + true + org.apache.tiles.api.Attribute + + + + + + flush + false + true + boolean + +
+ + + + Put an attribute in enclosing attribute container tag. +

+

+ Enclosing attribute container tag can be : +

    +
  • <initContainer>
  • +
  • <definition>
  • +
  • <insertAttribute>
  • +
  • <insertDefinition>
  • +
  • <putListAttribute>
  • +
+ (or any other tag which implements the PutAttributeTagParent + interface. Exception is thrown if no appropriate tag can be found. +

+

+ Put tag can have following atributes : +

    +
  • name : Name of the attribute
  • +
  • value : value to put as attribute
  • +
  • type : value type. Possible type are : string (value is used as direct + string), template (value is used as a page url to insert), definition (value + is used as a definition name to insert), object (value is used as it is)
  • +
  • role : Role to check when 'insertAttribute' will be called.
  • +
+

+

+ Value can also come from tag body. Tag body is taken into account only if + value is not set by one of the tag attributes. In this case Attribute type is + "string", unless tag body define another type. +

+ ]]> +
+ putAttribute + org.apache.tiles.web.jsp.taglib.PutAttributeTag + scriptless + + + + + name + true + true + java.lang.String + + + + + + value + false + true + java.lang.Object + + + + + + expression + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + type + false + true + java.lang.String + + + + + + cascade + false + true + boolean + +
+ + + + Create a definition at runtime. +

+

+ Create a new definition at runtime. Newly created definition will be + available across the entire request. +

+ ]]> +
+ definition + org.apache.tiles.web.jsp.taglib.DefinitionTag + scriptless + + + + + name + false + true + java.lang.String + + + + + + template + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + extends + false + true + java.lang.String + + + + + + preparer + false + true + java.lang.String + +
+ + + + Add an element to the surrounding list. Equivalent to 'putAttribute', + but for list element. +

+ +

+ Add an element to the surrounding list. This tag can only be used inside + 'putListAttribute' or 'addListAttribute' tags. Value can come from a direct + assignment (value="aValue") +

+ ]]> +
+ addAttribute + org.apache.tiles.web.jsp.taglib.AddAttributeTag + scriptless + + + + + value + false + true + java.lang.Object + + + + + + expression + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + type + false + true + java.lang.String + +
+ + + + Declare a list that will be pass as attribute to tile. +

+

+ Declare a list that will be pass as attribute to tile. List elements are + added using the tags 'addAttribute' or 'addListAttribute'. This tag can only + be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. +

+ ]]> +
+ putListAttribute + org.apache.tiles.web.jsp.taglib.PutListAttributeTag + scriptless + + + + + name + true + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + inherit + false + true + boolean + + + + + + cascade + false + true + boolean + +
+ + + + Insert a template. +

+

+ Insert a template with the possibility to pass parameters (called + attributes). A template can be seen as a procedure that can take parameters + or attributes. <tiles:insertTemplate> allows to define + these attributes and pass them to the inserted jsp page, called template. + Attributes are defined using nested tag + <tiles:putAttribute> or + <tiles:putListAttribute>. +

+

+ You must specify template attribute, for inserting a template +

+ +

+ Example : +

+ +
+          <tiles:insertTemplate template="/basic/myLayout.jsp" flush="true">
+              <tiles:putAttribute name="title" value="My first page" />
+              <tiles:putAttribute name="header" value="/common/header.jsp" />
+              <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+              <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+              <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+          </tiles:insertTemplate>
+      
+ ]]> +
+ insertTemplate + org.apache.tiles.web.jsp.taglib.InsertTemplateTag + scriptless + + + + + template + true + true + java.lang.String + + + + + + templateType + false + true + java.lang.String + + + + + + templateExpression + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + preparer + false + true + java.lang.String + + + + + + flush + false + true + boolean + +
+
diff --git a/plugins/tiles/src/main/resources/META-INF/velocity.properties b/plugins/tiles/src/main/resources/META-INF/velocity.properties new file mode 100644 index 0000000000..4887c6cc36 --- /dev/null +++ b/plugins/tiles/src/main/resources/META-INF/velocity.properties @@ -0,0 +1,30 @@ +# 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. +# +# This file was automatically generated by Autotag. Please do not edit it manually. + +userdirective=org.apache.tiles.velocity.template.InsertDefinitionDirective,\ +org.apache.tiles.velocity.template.ImportAttributeDirective,\ +org.apache.tiles.velocity.template.SetCurrentContainerDirective,\ +org.apache.tiles.velocity.template.AddListAttributeDirective,\ +org.apache.tiles.velocity.template.GetAsStringDirective,\ +org.apache.tiles.velocity.template.InsertAttributeDirective,\ +org.apache.tiles.velocity.template.PutAttributeDirective,\ +org.apache.tiles.velocity.template.DefinitionDirective,\ +org.apache.tiles.velocity.template.AddAttributeDirective,\ +org.apache.tiles.velocity.template.PutListAttributeDirective,\ +org.apache.tiles.velocity.template.InsertTemplateDirective diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm new file mode 100644 index 0000000000..c307110dd7 --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm @@ -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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package ${packageName}; + +import java.io.IOException; +import java.util.Map; + +#if(${clazz.hasBody()}) +import org.apache.tiles.autotag.core.runtime.ModelBody; +#end +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** +#foreach($line in $stringTool.splitOnNewlines(${clazz.documentation})) + * ${line} +#end + */ +public class ${clazz.tagClassPrefix}FMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private ${clazz.name} model; + + /** + * Constructor. + * + * @param model + * The template model. + */ + public ${clazz.tagClassPrefix}FMModel(${clazz.name} model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime<${requestClass}> runtime = new ${runtimeClass}(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + ${requestClass} request = runtime.createRequest(); +#if(${clazz.hasBody()}) + ModelBody modelBody = runtime.createModelBody(); +#end + model.execute( +#foreach($parameter in ${clazz.parameters}) + runtime.getParameter("${parameter.exportedName}", ${stringTool.getClassToCast(${parameter.type})}.class, $stringTool.getDefaultValue(${parameter.type}, ${parameter.defaultValue})), +#end + request#if(${clazz.hasBody()}), modelBody#end + ); + } +} diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/repository.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/repository.vm new file mode 100644 index 0000000000..a854aa4acd --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/repository.vm @@ -0,0 +1,57 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package ${packageName}; + +/** +#foreach($line in $stringTool.splitOnNewlines(${suite.documentation})) + * $line +#end + */ +public class $stringTool.capitalizeFirstLetter(${suite.name})FMModelRepository { + +#foreach($clazz in ${suite.getTemplateClasses()}) + /** + * The "${clazz.tagName}" directive. + */ + private ${clazz.tagClassPrefix}FMModel ${clazz.tagName}; + +#end + /** + * Constructor. + */ + public TilesFMModelRepository() { +#foreach($clazz in ${suite.getTemplateClasses()}) + ${clazz.tagName} = new ${clazz.tagClassPrefix}FMModel(new ${clazz.name}()); +#end + } +#foreach($clazz in ${suite.getTemplateClasses()}) + + /** + * Returns the "${clazz.tagName}" directive. + * + * @return The "${clazz.tagName}" directive. + */ + public ${clazz.tagClassPrefix}FMModel get$stringTool.capitalizeFirstLetter(${clazz.tagName})() { + return ${clazz.tagName}; + } +#end +} diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm new file mode 100644 index 0000000000..e48be526cd --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm @@ -0,0 +1,102 @@ +/* + * 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. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package ${packageName}; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +#if(${clazz.hasBody()}) +import org.apache.tiles.autotag.core.runtime.ModelBody; +#end +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** +#foreach($line in $stringTool.splitOnNewlines(${clazz.documentation})) + * ${line} +#end + */ +public class ${clazz.tagClassPrefix}Tag extends SimpleTagSupport { + + /** + * The template model. + */ + private ${clazz.name} model = new ${clazz.name}(); + +#foreach($parameter in ${clazz.parameters}) + /** +#foreach($line in $stringTool.splitOnNewlines(${parameter.documentation})) + * ${line} +#end + */ + private ${parameter.type} ${parameter.name}; + +#end +#foreach($parameter in ${clazz.parameters}) + /** + * Getter for ${parameter.exportedName} property. + * + * @return +#foreach($line in $stringTool.splitOnNewlines(${parameter.documentation})) + * ${line} +#end + */ + public ${parameter.type} #if(${parameter.type} == 'boolean')is#{else}get#end${parameter.getterSetterSuffix}() { + return ${parameter.name}; + } + + /** + * Setter for ${parameter.exportedName} property. + * + * @param ${parameter.name} +#foreach($line in $stringTool.splitOnNewlines(${parameter.documentation})) + * ${line} +#end + */ + public void set${parameter.getterSetterSuffix}(${parameter.type} ${parameter.name}) { + this.${parameter.name} = ${parameter.name}; + } + +#end + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime<${requestClass}> runtime = new ${runtimeClass}(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + ${requestClass} request = runtime.createRequest(); +#if(${clazz.hasBody()}) + ModelBody modelBody = runtime.createModelBody(); +#end + model.execute( +#foreach($parameter in ${clazz.parameters}) + ${parameter.name}, +#end + request#if(${clazz.hasBody()}), modelBody#end + ); + } +} diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/tld.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/tld.vm new file mode 100644 index 0000000000..2faecf6622 --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/tld.vm @@ -0,0 +1,66 @@ + + + + + + + + 1.2 + ${suite.name} + ${parameters.taglibURI} +#foreach($clazz in ${suite.getTemplateClasses()}) + + + + + ${clazz.tagName} + ${packageName}.${clazz.tagClassPrefix}Tag + #if(${clazz.hasBody()})scriptless#{else}empty#end +#foreach($parameter in ${clazz.parameters}) + + + + + ${parameter.exportedName} + ${parameter.required} + true + ${parameter.type} + +#end + +#end + diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity.properties b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity.properties new file mode 100644 index 0000000000..821c6d762c --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity.properties @@ -0,0 +1,101 @@ + # 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. +# ---------------------------------------------------------------------------- +# These are the default properties for the +# Velocity Runtime. These values are used when +# Runtime.init() is called, and when Runtime.init(properties) +# fails to find the specificed properties file. +# ---------------------------------------------------------------------------- + + +# ---------------------------------------------------------------------------- +# R U N T I M E L O G +# ---------------------------------------------------------------------------- +# Velocity uses the Servlet APIs logging facilites. + +# ---------------------------------------------------------------------------- +# This controls if Runtime.error(), info() and warn() messages include the +# whole stack trace. The last property controls whether invalid references +# are logged. +# ---------------------------------------------------------------------------- + +runtime.log.invalid.reference = true + + +# ---------------------------------------------------------------------------- +# T E M P L A T E E N C O D I N G +# ---------------------------------------------------------------------------- + +input.encoding=ISO-8859-1 +output.encoding=ISO-8859-1 + + +# ---------------------------------------------------------------------------- +# I N C L U D E P R O P E R T I E S +# ---------------------------------------------------------------------------- +# These are the properties that governed the way #include'd content +# is governed. +# ---------------------------------------------------------------------------- + +directive.include.output.errormsg.start = + + +# ---------------------------------------------------------------------------- +# P A R S E P R O P E R T I E S +# ---------------------------------------------------------------------------- + +directive.parse.max.depth = 10 + + +# ---------------------------------------------------------------------------- +# VELOCIMACRO PROPERTIES +# ---------------------------------------------------------------------------- +# global : name of default global library. It is expected to be in the regular +# template path. You may remove it (either the file or this property) if +# you wish with no harm. +# ---------------------------------------------------------------------------- +# dev-changes by Marino +resource.loader=class, string + +class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader + +velocimacro.library.autoreload = false + +velocimacro.permissions.allow.inline = true +velocimacro.permissions.allow.inline.to.replace.global = false +velocimacro.permissions.allow.inline.local.scope = false + +velocimacro.context.localscope = false + +# ---------------------------------------------------------------------------- +# INTERPOLATION +# ---------------------------------------------------------------------------- +# turn off and on interpolation of references and directives in string +# literals. ON by default :) +# ---------------------------------------------------------------------------- +runtime.interpolate.string.literals = true + + +# ---------------------------------------------------------------------------- +# RESOURCE MANAGEMENT +# ---------------------------------------------------------------------------- +# Allows alternative ResourceManager and ResourceCache implementations +# to be plugged in. +# ---------------------------------------------------------------------------- +resource.manager.class = org.apache.velocity.runtime.resource.ResourceManagerImpl +resource.manager.cache.class = org.apache.velocity.runtime.resource.ResourceCacheImpl diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm new file mode 100644 index 0000000000..0528affaba --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm @@ -0,0 +1,76 @@ +/* + * 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. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package ${packageName}; + +import java.io.IOException; +import java.io.Writer; + +#if(${clazz.hasBody()}) +import org.apache.tiles.autotag.core.runtime.ModelBody; +#end +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** +#foreach($line in $stringTool.splitOnNewlines(${clazz.documentation})) + * ${line} +#end + */ +public class ${clazz.tagClassPrefix}Directive extends Directive { + + /** + * The template model. + */ + private ${clazz.name} model = new ${clazz.name}(); + + @Override + public String getName() { + return "${suite.name}_${clazz.tagName}"; + } + + @Override + public int getType() { + return #if(${clazz.hasBody()})BLOCK#{else}LINE#{end}; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) + throws IOException { + AutotagRuntime<${requestClass}> runtime = new ${runtimeClass}(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + ${requestClass} request = runtime.createRequest(); +#if(${clazz.hasBody()}) + ModelBody modelBody = runtime.createModelBody(); +#end + model.execute( +#foreach($parameter in ${clazz.parameters}) + runtime.getParameter("${parameter.exportedName}", ${stringTool.getClassToCast(${parameter.type})}.class, $stringTool.getDefaultValue(${parameter.type}, ${parameter.defaultValue})), +#end + request#if(${clazz.hasBody()}), modelBody#end + ); + return true; + } +} diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityProperties.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityProperties.vm new file mode 100644 index 0000000000..6360d64f47 --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityProperties.vm @@ -0,0 +1,21 @@ +# 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. +# +# This file was automatically generated by Autotag. Please do not edit it manually. + +userdirective=#foreach($clazz in ${suite.getTemplateClasses()})#if($foreach.count > 1),\ + #{end}${packageName}.${clazz.tagClassPrefix}Directive#end \ No newline at end of file diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/resources/tiles-config_3_0.dtd b/plugins/tiles/src/main/resources/org/apache/tiles/resources/tiles-config_3_0.dtd new file mode 100644 index 0000000000..dab8d78574 --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/resources/tiles-config_3_0.dtd @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/main/resources/tools.xml b/plugins/tiles/src/main/resources/tools.xml new file mode 100644 index 0000000000..65d673763b --- /dev/null +++ b/plugins/tiles/src/main/resources/tools.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessorTest.java b/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessorTest.java index bad09f4b40..ca11f3bff7 100644 --- a/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessorTest.java +++ b/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessorTest.java @@ -22,9 +22,9 @@ import java.util.Set; import org.apache.struts2.tiles.annotation.TilesDefinition; -import org.apache.tiles.Attribute; -import org.apache.tiles.Definition; -import org.apache.tiles.Expression; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; import org.junit.Test; import org.junit.Assert; diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/AttributeTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/AttributeTest.java new file mode 100644 index 0000000000..703dde92b7 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/AttributeTest.java @@ -0,0 +1,275 @@ +/* + * 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.apache.tiles.api; + +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Objects; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link Attribute}. + */ +public class AttributeTest { + + /** + * Tests {@link Attribute#createTemplateAttribute(String)}. + */ + @Test + public void testCreateTemplateAttribute1() { + Attribute attribute = Attribute.createTemplateAttribute("/my/template.jsp"); + assertEquals("/my/template.jsp", attribute.getValue()); + assertEquals("template", attribute.getRenderer()); + } + + /** + * Tests {@link Attribute#Attribute()}. + */ + @Test + public void testAttribute() { + Attribute attribute = new Attribute(); + assertNull(attribute.getValue()); + } + + /** + * Tests {@link Attribute#Attribute(Object)}. + */ + @Test + public void testAttributeObject() { + Attribute attribute = new Attribute("my.value"); + assertEquals("my.value", attribute.getValue()); + assertNull(attribute.getRenderer()); + } + + /** + * Tests {@link Attribute#Attribute(Object, String)}. + */ + @Test + public void testAttributeObjectString() { + Attribute attribute = new Attribute("my.value", "role1,role2"); + assertEquals("my.value", attribute.getValue()); + assertNull(attribute.getRenderer()); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals(roles, attribute.getRoles()); + } + + /** + * Tests {@link Attribute#Attribute(Object, Expression, String, String)}. + */ + @Test + public void testAttributeComplete() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + assertEquals("my.value", attribute.getValue()); + assertEquals("myrenderer", attribute.getRenderer()); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals(roles, attribute.getRoles()); + assertEquals("my.expression", attribute.getExpressionObject().getExpression()); + assertEquals("MYLANG", attribute.getExpressionObject().getLanguage()); + } + + /** + * Tests {@link Attribute#Attribute(Attribute)}. + */ + @Test + public void testAttributeCopy() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + attribute = new Attribute(attribute); + assertEquals("my.value", attribute.getValue()); + assertEquals("myrenderer", attribute.getRenderer()); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals(roles, attribute.getRoles()); + assertEquals("my.expression", attribute.getExpressionObject().getExpression()); + assertEquals("MYLANG", attribute.getExpressionObject().getLanguage()); + + attribute = new Attribute("my.value", null, "role1,role2", "myrenderer"); + attribute = new Attribute(attribute); + assertEquals("my.value", attribute.getValue()); + assertEquals("myrenderer", attribute.getRenderer()); + roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals(roles, attribute.getRoles()); + assertNull(attribute.getExpressionObject()); + } + + /** + * Tests {@link Attribute#equals(Object)}. + */ + @Test + public void testEquals() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + Attribute attribute2 = new Attribute(attribute); + assertEquals(attribute, attribute2); + attribute2.setRenderer("anotherRenderer"); + assertNotEquals(attribute, attribute2); + attribute2 = new Attribute(attribute); + attribute2.setRole("otherrole"); + assertNotEquals(attribute, attribute2); + attribute2 = new Attribute(attribute); + attribute2.setExpressionObject(new Expression("another.expression", "MYLANG")); + assertNotEquals(attribute, attribute2); + attribute2 = new Attribute(attribute); + attribute2.setValue("anothervalue"); + assertNotEquals(attribute, attribute2); + } + + /** + * Tests {@link Attribute#getRole()} and {@link Attribute#setRole(String)}. + */ + @Test + public void testGetRole() { + Attribute attribute = new Attribute("my.value"); + assertNull(attribute.getRole()); + Set roles = new LinkedHashSet<>(); + attribute.setRoles(roles); + assertNull(attribute.getRole()); + roles.add("role1"); + roles.add("role2"); + assertEquals("role1,role2", attribute.getRole()); + } + + /** + * Tests {@link Attribute#hashCode()}. + */ + @Test + public void testHashCode() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals( + Objects.hashCode("my.value") + + Objects.hashCode(expression) + Objects.hashCode(roles) + + Objects.hashCode("myrenderer"), attribute.hashCode() + ); + } + + /** + * Tests {@link Attribute#toString()}. + */ + @Test + public void testToString() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + assertEquals("my.value", attribute.toString()); + attribute.setValue(null); + assertNotNull(attribute.toString()); + } + + @Test + public void testInherit() { + Attribute attribute = new Attribute(null, null, null, null); + Attribute parentAttribute = new Attribute("value", Expression + .createExpression("expression", "language"), "role", "renderer"); + attribute.inherit(parentAttribute); + assertEquals("value", attribute.getValue()); + assertEquals("expression", attribute.getExpressionObject().getExpression()); + assertEquals("language", attribute.getExpressionObject().getLanguage()); + assertEquals("role", attribute.getRole()); + assertEquals("renderer", attribute.getRenderer()); + Expression expression = new Expression(null, "MYLANG"); + attribute = new Attribute(null, expression, null, null); + attribute.setRoles(new HashSet<>()); + attribute.inherit(parentAttribute); + assertEquals("value", attribute.getValue()); + assertEquals("expression", attribute.getExpressionObject().getExpression()); + assertEquals("language", attribute.getExpressionObject().getLanguage()); + assertEquals("role", attribute.getRole()); + assertEquals("renderer", attribute.getRenderer()); + } + + /** + * Tests {@link Attribute#clone()}. + */ + @Test + public void testClone() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + attribute = attribute.copy(); + assertEquals("my.value", attribute.getValue()); + assertEquals("myrenderer", attribute.getRenderer()); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals(roles, attribute.getRoles()); + assertEquals("my.expression", attribute.getExpressionObject().getExpression()); + assertEquals("MYLANG", attribute.getExpressionObject().getLanguage()); + } + + /** + * Tests {@link Attribute#createTemplateAttribute(String, String, String, String)}. + */ + @Test + public void testCreateTemplateAttribute() { + Attribute attribute = Attribute.createTemplateAttribute("myTemplate", "MYLANG:myExpression", "myType", "myRole"); + assertEquals("myTemplate", attribute.getValue()); + assertEquals("MYLANG", attribute.getExpressionObject().getLanguage()); + assertEquals("myExpression", attribute.getExpressionObject().getExpression()); + assertEquals("myType", attribute.getRenderer()); + Set roles = attribute.getRoles(); + assertEquals(1, roles.size()); + assertTrue(roles.contains("myRole")); + } + + @Test + public void testIsPermitted() { + Attribute attribute = new Attribute("myvalue"); + Request requestContext = createMock(Request.class); + expect(requestContext.isUserInRole("first")).andReturn(Boolean.TRUE) + .anyTimes(); + expect(requestContext.isUserInRole("second")).andReturn(Boolean.FALSE) + .anyTimes(); + replay(requestContext); + assertTrue(attribute.isPermitted(requestContext)); + Set roles = new HashSet<>(); + roles.add("first"); + attribute.setRoles(roles); + assertTrue("The role is not permitted", attribute.isPermitted( + requestContext)); + roles.clear(); + roles.add("second"); + assertFalse("The role is not permitted", attribute.isPermitted( + requestContext)); + verify(requestContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/BasicAttributeContextTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/BasicAttributeContextTest.java new file mode 100644 index 0000000000..8b60953b56 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/BasicAttributeContextTest.java @@ -0,0 +1,681 @@ +/* + * 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.apache.tiles.api; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests BasicAttributeContext. + * + * @version $Rev$ $Date$ + */ +public class BasicAttributeContextTest { + + /** + * Tests {@link BasicAttributeContext#BasicAttributeContext()}. + */ + @Test + public void testBasicAttributeContext() { + AttributeContext context = new BasicAttributeContext(); + assertNull("There are some spurious attributes", context + .getLocalAttributeNames()); + assertNull("There are some spurious attributes", context + .getCascadedAttributeNames()); + } + + /** + * Tests {@link BasicAttributeContext#BasicAttributeContext(Map)}. + */ + @Test + public void testBasicAttributeContextMapOfStringAttribute() { + Map name2attrib = new HashMap<>(); + Attribute attribute = new Attribute("Value 1"); + name2attrib.put("name1", attribute); + attribute = new Attribute("Value 2"); + name2attrib.put("name2", attribute); + AttributeContext context = new BasicAttributeContext(name2attrib); + attribute = context.getAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "Value 1", + attribute.getValue()); + attribute = context.getAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "Value 2", + attribute.getValue()); + } + + /** + * Tests + * {@link BasicAttributeContext#BasicAttributeContext(AttributeContext)}. + */ + @Test + public void testBasicAttributeContextAttributeContext() { + Set localAttributes = new LinkedHashSet<>(); + Set cascadedAttributes = new LinkedHashSet<>(); + localAttributes.add("local1"); + localAttributes.add("local2"); + cascadedAttributes.add("cascaded1"); + cascadedAttributes.add("cascaded2"); + AttributeContext toCopy = createMock(AttributeContext.class); + expect(toCopy.getLocalAttributeNames()).andReturn(localAttributes); + expect(toCopy.getLocalAttribute("local1")).andReturn( + new Attribute("value1")).anyTimes(); + expect(toCopy.getLocalAttribute("local2")).andReturn( + new Attribute("value2")).anyTimes(); + expect(toCopy.getCascadedAttributeNames()) + .andReturn(cascadedAttributes); + expect(toCopy.getCascadedAttribute("cascaded1")).andReturn( + new Attribute("value3")).anyTimes(); + expect(toCopy.getCascadedAttribute("cascaded2")).andReturn( + new Attribute("value4")).anyTimes(); + Attribute templateAttribute = new Attribute("/template.jsp", Expression + .createExpression("expression", null), "role1,role2", + "template"); + expect(toCopy.getTemplateAttribute()).andReturn(templateAttribute); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + expect(toCopy.getPreparer()).andReturn("my.preparer.Preparer"); + replay(toCopy); + BasicAttributeContext context = new BasicAttributeContext(toCopy); + assertEquals("The template has not been set correctly", + "/template.jsp", context.getTemplateAttribute().getValue()); + assertEquals("The template expression has not been set correctly", + "expression", context.getTemplateAttribute() + .getExpressionObject().getExpression()); + assertEquals("The roles are not the same", roles, context + .getTemplateAttribute().getRoles()); + assertEquals("The preparer has not been set correctly", + "my.preparer.Preparer", context.getPreparer()); + Attribute attribute = context.getLocalAttribute("local1"); + assertNotNull("Attribute local1 not found", attribute); + assertEquals("Attribute local1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getLocalAttribute("local2"); + assertNotNull("Attribute local2 not found", attribute); + assertEquals("Attribute local2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getCascadedAttribute("cascaded1"); + assertNotNull("Attribute cascaded1 not found", attribute); + assertEquals("Attribute cascaded1 has not been set correctly", + "value3", attribute.getValue()); + attribute = context.getCascadedAttribute("cascaded2"); + assertNotNull("Attribute cascaded2 not found", attribute); + assertEquals("Attribute cascaded2 has not been set correctly", + "value4", attribute.getValue()); + } + + /** + * Tests + * {@link BasicAttributeContext#BasicAttributeContext(BasicAttributeContext)} + * . + */ + @Test + public void testBasicAttributeContextBasicAttributeContext() { + BasicAttributeContext toCopy = new BasicAttributeContext(); + toCopy.putAttribute("name1", new Attribute("value1"), false); + toCopy.putAttribute("name2", new Attribute("value2"), true); + Attribute templateAttribute = Attribute + .createTemplateAttribute("/template.jsp"); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + templateAttribute.setRoles(roles); + toCopy.setTemplateAttribute(templateAttribute); + toCopy.setPreparer("my.preparer.Preparer"); + AttributeContext context = new BasicAttributeContext(toCopy); + assertEquals("The template has not been set correctly", + "/template.jsp", context.getTemplateAttribute().getValue()); + assertEquals("The roles are not the same", roles, context + .getTemplateAttribute().getRoles()); + assertEquals("The preparer has not been set correctly", + "my.preparer.Preparer", context.getPreparer()); + Attribute attribute = context.getLocalAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + } + + /** + * Tests + * {@link BasicAttributeContext#inheritCascadedAttributes(AttributeContext)} + * . + */ + @Test + public void testInheritCascadedAttributes() { + AttributeContext toCopy = new BasicAttributeContext(); + toCopy.putAttribute("name1", new Attribute("value1"), false); + toCopy.putAttribute("name2", new Attribute("value2"), true); + AttributeContext context = new BasicAttributeContext(); + context.inheritCascadedAttributes(toCopy); + Attribute attribute = context.getLocalAttribute("name1"); + assertNull("Attribute name1 found", attribute); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + } + + /** + * Tests {@link BasicAttributeContext#inherit(BasicAttributeContext)} + * testing inheritance between {@link ListAttribute} instances. + */ + @Test + public void testInheritListAttribute() { + AttributeContext toCopy = new BasicAttributeContext(); + ListAttribute parentListAttribute = new ListAttribute(); + Attribute first = new Attribute("first"); + Attribute second = new Attribute("second"); + parentListAttribute.add(first); + toCopy.putAttribute("list", parentListAttribute); + AttributeContext context = new BasicAttributeContext(); + ListAttribute listAttribute = new ListAttribute(); + listAttribute.setInherit(true); + listAttribute.add(second); + context.putAttribute("list", listAttribute); + context.inherit(toCopy); + ListAttribute result = (ListAttribute) context.getAttribute("list"); + assertNotNull("The attribute must exist", result); + List value = result.getValue(); + assertNotNull("The list must exist", value); + assertEquals("The size is not correct", 2, value.size()); + assertEquals("The first element is not correct", first, value.get(0)); + assertEquals("The second element is not correct", second, value + .get(1)); + + context = new BasicAttributeContext(); + listAttribute = new ListAttribute(); + listAttribute.add(second); + context.putAttribute("list", listAttribute); + context.inherit(toCopy); + result = (ListAttribute) context.getAttribute("list"); + assertNotNull("The attribute must exist", result); + value = result.getValue(); + assertNotNull("The list must exist", value); + assertEquals("The size is not correct", 1, value.size()); + assertEquals("The second element is not correct", second, value + .get(0)); + } + + /** + * Tests + * {@link BasicAttributeContext#inheritCascadedAttributes(AttributeContext)} + * . + */ + @Test + public void testInherit() { + AttributeContext toCopy = new BasicAttributeContext(); + Attribute parentTemplateAttribute = new Attribute(); + parentTemplateAttribute.setValue("/parent/template.jsp"); + toCopy.setTemplateAttribute(parentTemplateAttribute); + toCopy.putAttribute("name1", new Attribute("value1"), true); + toCopy.putAttribute("name2", new Attribute("value2"), true); + toCopy.putAttribute("name3", new Attribute("value3"), false); + toCopy.putAttribute("name4", new Attribute("value4"), false); + AttributeContext context = new BasicAttributeContext(); + Attribute templateAttribute = new Attribute(); + templateAttribute.setRole("role1,role2"); + context.setTemplateAttribute(templateAttribute); + context.putAttribute("name1", new Attribute("newValue1"), true); + context.putAttribute("name3", new Attribute("newValue3"), false); + context.inherit(toCopy); + Attribute attribute = context.getTemplateAttribute(); + assertEquals("/parent/template.jsp", attribute.getValue()); + assertTrue(attribute.getRoles().contains("role1")); + assertTrue(attribute.getRoles().contains("role2")); + attribute = context.getCascadedAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "newValue1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getLocalAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "newValue3", + attribute.getValue()); + attribute = context.getLocalAttribute("name4"); + assertNotNull("Attribute name4 not found", attribute); + assertEquals("Attribute name4 has not been set correctly", "value4", + attribute.getValue()); + + toCopy = new BasicAttributeContext(); + toCopy.putAttribute("name1", new Attribute("value1"), true); + toCopy.putAttribute("name2", new Attribute("value2"), true); + toCopy.putAttribute("name3", new Attribute("value3"), false); + toCopy.putAttribute("name4", new Attribute("value4"), false); + context = new BasicAttributeContext(); + context.inherit(toCopy); + attribute = context.getCascadedAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getLocalAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "value3", + attribute.getValue()); + attribute = context.getLocalAttribute("name4"); + assertNotNull("Attribute name4 not found", attribute); + assertEquals("Attribute name4 has not been set correctly", "value4", + attribute.getValue()); + } + + /** + * Tests + * {@link BasicAttributeContext#inherit(AttributeContext)} + * . + */ + @Test + public void testInheritAttributeContext() { + AttributeContext toCopy = createMock(AttributeContext.class); + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + expect(toCopy.getTemplateAttribute()).andReturn(templateAttribute); + expect(toCopy.getPreparer()).andReturn("my.preparer"); + Set cascadedNames = new HashSet<>(); + cascadedNames.add("name1"); + cascadedNames.add("name2"); + expect(toCopy.getCascadedAttributeNames()).andReturn(cascadedNames); + expect(toCopy.getCascadedAttribute("name1")).andReturn(new Attribute("value1")); + expect(toCopy.getCascadedAttribute("name2")).andReturn(new Attribute("value2")); + Set names = new HashSet<>(); + names.add("name3"); + names.add("name4"); + expect(toCopy.getLocalAttributeNames()).andReturn(names); + expect(toCopy.getLocalAttribute("name3")).andReturn(new Attribute("value3")); + expect(toCopy.getLocalAttribute("name4")).andReturn(new Attribute("value4")); + + replay(toCopy); + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("newValue1"), true); + context.putAttribute("name3", new Attribute("newValue3"), false); + context.inherit(toCopy); + Attribute attribute = context.getCascadedAttribute("name1"); + assertEquals("/my/template.jsp", context.getTemplateAttribute().getValue()); + assertEquals("my.preparer", context.getPreparer()); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "newValue1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getLocalAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "newValue3", + attribute.getValue()); + attribute = context.getLocalAttribute("name4"); + assertNotNull("Attribute name4 not found", attribute); + assertEquals("Attribute name4 has not been set correctly", "value4", + attribute.getValue()); + verify(toCopy); + } + + /** + * Tests {@link BasicAttributeContext#inherit(AttributeContext)} + * testing inheritance between {@link ListAttribute} instances. + */ + @Test + public void testInheritAttributeContextListAttribute() { + AttributeContext toCopy = createMock(AttributeContext.class); + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + expect(toCopy.getTemplateAttribute()).andReturn(templateAttribute).times(2); + expect(toCopy.getPreparer()).andReturn("my.preparer").times(2); + ListAttribute parentListAttribute = new ListAttribute(); + Attribute first = new Attribute("first"); + Attribute second = new Attribute("second"); + Attribute third = new Attribute("third"); + Attribute fourth = new Attribute("fourth"); + parentListAttribute.add(first); + ListAttribute parentListAttribute2 = new ListAttribute(); + parentListAttribute2.add(third); + Set names = new HashSet<>(); + names.add("list"); + Set cascadedNames = new HashSet<>(); + cascadedNames.add("list2"); + expect(toCopy.getCascadedAttributeNames()).andReturn(cascadedNames).times(2); + expect(toCopy.getCascadedAttribute("list2")).andReturn(parentListAttribute2).times(2); + expect(toCopy.getLocalAttributeNames()).andReturn(names).times(2); + expect(toCopy.getLocalAttribute("list")).andReturn(parentListAttribute).times(2); + + replay(toCopy); + AttributeContext context = new BasicAttributeContext(); + ListAttribute listAttribute = new ListAttribute(); + listAttribute.setInherit(true); + listAttribute.add(second); + context.putAttribute("list", listAttribute, false); + ListAttribute listAttribute2 = new ListAttribute(); + listAttribute2.setInherit(true); + listAttribute2.add(fourth); + context.putAttribute("list2", listAttribute2, true); + context.inherit(toCopy); + ListAttribute result = (ListAttribute) context.getAttribute("list"); + assertNotNull("The attribute must exist", result); + List value = result.getValue(); + assertNotNull("The list must exist", value); + assertEquals("The size is not correct", 2, value.size()); + assertEquals("The first element is not correct", first, value.get(0)); + assertEquals("The second element is not correct", second, value + .get(1)); + result = (ListAttribute) context.getAttribute("list2"); + assertNotNull("The attribute must exist", result); + value = result.getValue(); + assertNotNull("The list must exist", value); + assertEquals("The size is not correct", 2, value.size()); + assertEquals("The first element is not correct", third, value.get(0)); + assertEquals("The second element is not correct", fourth, value + .get(1)); + + context = new BasicAttributeContext(); + listAttribute = new ListAttribute(); + listAttribute.add(second); + context.putAttribute("list", listAttribute); + context.inherit(toCopy); + result = (ListAttribute) context.getAttribute("list"); + assertNotNull("The attribute must exist", result); + value = result.getValue(); + assertNotNull("The list must exist", value); + assertEquals("The size is not correct", 1, value.size()); + assertEquals("The second element is not correct", second, value + .get(0)); + verify(toCopy); + } + + /** + * Tests {@link BasicAttributeContext#addAll(Map)}. + */ + @Test + public void testAddAll() { + AttributeContext context = new BasicAttributeContext(); + Map name2attrib = new HashMap<>(); + Attribute attribute = new Attribute("Value 1"); + name2attrib.put("name1", attribute); + attribute = new Attribute("Value 2"); + name2attrib.put("name2", attribute); + context.addAll(name2attrib); + attribute = context.getAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "Value 1", + attribute.getValue()); + attribute = context.getAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "Value 2", + attribute.getValue()); + + context.addAll(null); + attribute = context.getAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "Value 1", + attribute.getValue()); + attribute = context.getAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "Value 2", + attribute.getValue()); + + name2attrib = new HashMap<>(); + name2attrib.put("name3", new Attribute("Value 3")); + context.addAll(name2attrib); + attribute = context.getAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "Value 1", + attribute.getValue()); + attribute = context.getAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "Value 2", + attribute.getValue()); + attribute = context.getAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "Value 3", + attribute.getValue()); + } + + /** + * Tests {@link BasicAttributeContext#getAttribute(String)}. + */ + @Test + public void testGetAttribute() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.putAttribute("name3", new Attribute("value3a"), true); + context.putAttribute("name3", new Attribute("value3"), false); + Attribute attribute = context.getAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "value3", + attribute.getValue()); + } + + /** + * Tests {@link BasicAttributeContext#getLocalAttribute(String)}. + */ + @Test + public void testGetLocalAttribute() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.putAttribute("name3", new Attribute("value3a"), true); + context.putAttribute("name3", new Attribute("value3"), false); + Attribute attribute = context.getLocalAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getLocalAttribute("name2"); + assertNull("Attribute name2 found", attribute); + attribute = context.getLocalAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "value3", + attribute.getValue()); + } + + /** + * Tests {@link BasicAttributeContext#getCascadedAttribute(String)}. + */ + @Test + public void testGetCascadedAttribute() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.putAttribute("name3", new Attribute("value3a"), true); + context.putAttribute("name3", new Attribute("value3"), false); + Attribute attribute = context.getCascadedAttribute("name1"); + assertNull("Attribute name1 found", attribute); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getCascadedAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "value3a", + attribute.getValue()); + } + + /** + * Tests {@link BasicAttributeContext#getLocalAttributeNames()}. + */ + @Test + public void testGetLocalAttributeNames() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.putAttribute("name3", new Attribute("value3a"), true); + context.putAttribute("name3", new Attribute("value3"), false); + Set names = context.getLocalAttributeNames(); + assertTrue("Attribute name1 is not present", names.contains("name1")); + assertFalse("Attribute name2 is present", names.contains("name2")); + assertTrue("Attribute name3 is not present", names.contains("name3")); + } + + /** + * Tests {@link BasicAttributeContext#getCascadedAttributeNames()}. + */ + @Test + public void testGetCascadedAttributeNames() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.putAttribute("name3", new Attribute("value3a"), true); + context.putAttribute("name3", new Attribute("value3"), false); + Set names = context.getCascadedAttributeNames(); + assertFalse("Attribute name1 is present", names.contains("name1")); + assertTrue("Attribute name2 is not present", names.contains("name2")); + assertTrue("Attribute name3 is not present", names.contains("name3")); + } + + /** + * Tests {@link BasicAttributeContext#putAttribute(String, Attribute)}. + */ + @Test + public void testPutAttributeStringAttribute() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1")); + Attribute attribute = context.getLocalAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name1"); + assertNull("Attribute name1 found", attribute); + } + + /** + * Tests + * {@link BasicAttributeContext#putAttribute(String, Attribute, boolean)}. + */ + @Test + public void testPutAttributeStringAttributeBoolean() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + Attribute attribute = context.getLocalAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name1"); + assertNull("Attribute name1 found", attribute); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getLocalAttribute("name2"); + assertNull("Attribute name2 found", attribute); + } + + /** + * Tests {@link BasicAttributeContext#clear()}. + */ + @Test + public void testClear() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.clear(); + Set names = context.getLocalAttributeNames(); + assertTrue("There are local attributes", names == null + || names.isEmpty()); + names = context.getCascadedAttributeNames(); + assertTrue("There are cascaded attributes", names == null + || names.isEmpty()); + } + + /** + * Tests {@link BasicAttributeContext#equals(Object)}. + */ + @Test + public void testEquals() { + BasicAttributeContext attributeContext = new BasicAttributeContext(); + attributeContext.setPreparer("my.preparer"); + attributeContext.setTemplateAttribute(Attribute.createTemplateAttribute("/my/template.jsp")); + attributeContext.putAttribute("attribute1", new Attribute("value1"), true); + attributeContext.putAttribute("attribute2", new Attribute("value2"), true); + attributeContext.putAttribute("attribute3", new Attribute("value3"), false); + BasicAttributeContext toCompare = new BasicAttributeContext(attributeContext); + assertEquals(toCompare, attributeContext); + toCompare = new BasicAttributeContext(attributeContext); + toCompare.putAttribute("attribute4", new Attribute("value4"), true); + assertNotEquals(toCompare, attributeContext); + toCompare = new BasicAttributeContext(attributeContext); + toCompare.putAttribute("attribute4", new Attribute("value4"), false); + assertNotEquals(toCompare, attributeContext); + toCompare = new BasicAttributeContext(attributeContext); + toCompare.setPreparer("another.preparer"); + assertNotEquals(toCompare, attributeContext); + toCompare = new BasicAttributeContext(attributeContext); + toCompare.setTemplateAttribute(Attribute.createTemplateAttribute("/another/template.jsp")); + assertNotEquals(toCompare, attributeContext); + } + + /** + * Tests {@link BasicAttributeContext#hashCode()}. + */ + @Test + public void testHashCode() { + BasicAttributeContext attributeContext = new BasicAttributeContext(); + attributeContext.setPreparer("my.preparer"); + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + attributeContext.setTemplateAttribute(templateAttribute); + Attribute attribute1 = new Attribute("value1"); + Attribute attribute2 = new Attribute("value2"); + Attribute attribute3 = new Attribute("value3"); + attributeContext.putAttribute("attribute1", attribute1, true); + attributeContext.putAttribute("attribute2", attribute2, true); + attributeContext.putAttribute("attribute3", attribute3, false); + Map cascadedAttributes = new HashMap<>(); + cascadedAttributes.put("attribute1", attribute1); + cascadedAttributes.put("attribute2", attribute2); + Map attributes = new HashMap<>(); + attributes.put("attribute3", attribute3); + assertEquals(templateAttribute.hashCode() + "my.preparer".hashCode() + + attributes.hashCode() + cascadedAttributes.hashCode(), + attributeContext.hashCode()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/ExpressionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/ExpressionTest.java new file mode 100644 index 0000000000..6c2d618b15 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/ExpressionTest.java @@ -0,0 +1,108 @@ +/* + * 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.apache.tiles.api; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link Expression}. + */ +public class ExpressionTest { + + @Test + public void testHashCode() { + Expression expression = new Expression("hello", "there"); + assertEquals("hello".hashCode() + "there".hashCode(), expression.hashCode()); + } + + @Test + public void testExpressionStringString() { + Expression expression = new Expression("hello", "there"); + assertEquals("hello", expression.getExpression()); + assertEquals("there", expression.getLanguage()); + } + + @Test + public void testExpressionString() { + Expression expression = new Expression("hello"); + assertEquals("hello", expression.getExpression()); + assertNull(expression.getLanguage()); + } + + @Test + public void testExpressionExpression() { + Expression expression = new Expression("hello", "there"); + Expression expression2 = new Expression(expression); + assertEquals("hello", expression2.getExpression()); + assertEquals("there", expression2.getLanguage()); + } + + @Test + public void testCreateExpressionFromDescribedExpression() { + Expression expression = Expression.createExpressionFromDescribedExpression("hello"); + assertEquals("hello", expression.getExpression()); + assertNull(expression.getLanguage()); + expression = Expression.createExpressionFromDescribedExpression("there:hello"); + assertEquals("hello", expression.getExpression()); + assertEquals("there", expression.getLanguage()); + expression = Expression.createExpressionFromDescribedExpression("there_:hello"); + assertEquals("there_:hello", expression.getExpression()); + assertNull(expression.getLanguage()); + assertNull(Expression.createExpressionFromDescribedExpression(null)); + } + + @Test + public void testCreateExpression() { + Expression expression = Expression.createExpression("hello", "there"); + assertEquals("hello", expression.getExpression()); + assertEquals("there", expression.getLanguage()); + expression = Expression.createExpression("hello", null); + assertEquals("hello", expression.getExpression()); + assertNull(expression.getLanguage()); + expression = Expression.createExpression(null, "there"); + assertNull(expression); + } + + @Test + public void testEqualsObject() { + Expression expression = new Expression("hello", "there"); + Expression expression2 = new Expression("hello", "there"); + assertEquals(expression, expression2); + expression2 = new Expression("hello", "there2"); + assertNotEquals(expression, expression2); + expression2 = new Expression("hello"); + assertNotEquals(expression, expression2); + expression = new Expression("hello"); + assertEquals(expression, expression2); + } + + @Test + public void testToString() { + Expression expression = new Expression("hello", "there"); + assertEquals("there:hello", expression.toString()); + expression = new Expression("hello"); + assertEquals("DEFAULT:hello", expression.toString()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/ListAttributeTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/ListAttributeTest.java new file mode 100644 index 0000000000..baa41fd7ae --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/ListAttributeTest.java @@ -0,0 +1,109 @@ +/* + * 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.apache.tiles.api; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ListAttribute}. + */ +public class ListAttributeTest { + + @Test + public void testHashCode() { + ListAttribute attribute = new ListAttribute(); + List list = new ArrayList<>(); + list.add(new Attribute("value1")); + list.add(new Attribute("value2")); + attribute.setValue(list); + attribute.setInherit(true); + assertEquals(list.hashCode() + Boolean.TRUE.hashCode(), attribute.hashCode()); + } + + @Test + public void testEqualsObject() { + ListAttribute attribute = new ListAttribute(); + List list = new ArrayList<>(); + list.add(new Attribute("value1")); + list.add(new Attribute("value2")); + attribute.setValue(list); + attribute.setInherit(true); + ListAttribute toCheck = new ListAttribute(attribute); + assertEquals(attribute, toCheck); + toCheck = new ListAttribute(attribute); + toCheck.setInherit(false); + assertNotEquals(attribute, toCheck); + toCheck = new ListAttribute(attribute); + toCheck.add(new Attribute("value3")); + assertNotEquals(attribute, toCheck); + } + + @Test + public void testListAttributeListAttribute() { + ListAttribute attribute = new ListAttribute(); + List list = new ArrayList<>(); + list.add(new Attribute("value1")); + list.add(new Attribute("value2")); + list.add(null); + attribute.setValue(list); + attribute.setInherit(true); + ListAttribute toCheck = new ListAttribute(attribute); + assertEquals(attribute, toCheck); + } + + @Test + public void testSetValue() { + ListAttribute attribute = new ListAttribute(); + List list = new ArrayList<>(); + list.add(new Attribute("value1")); + list.add(new Attribute("value2")); + attribute.setValue(list); + assertEquals(list, attribute.getValue()); + } + + @Test + public void testSetInherit() { + ListAttribute attribute = new ListAttribute(); + attribute.setInherit(true); + assertTrue(attribute.isInherit()); + attribute.setInherit(false); + assertFalse(attribute.isInherit()); + } + + @Test + public void testClone() { + ListAttribute attribute = new ListAttribute(); + List list = new ArrayList<>(); + list.add(new Attribute("value1")); + list.add(new Attribute("value2")); + attribute.setValue(list); + attribute.setInherit(true); + ListAttribute toCheck = attribute.copy(); + assertEquals(attribute, toCheck); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/NoSuchContainerExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/NoSuchContainerExceptionTest.java new file mode 100644 index 0000000000..7634873b86 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/NoSuchContainerExceptionTest.java @@ -0,0 +1,39 @@ +/* + * 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.apache.tiles.api; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link NoSuchContainerException}. + */ +public class NoSuchContainerExceptionTest { + + @Test + public void testNoSuchContainerExceptionString() { + NoSuchContainerException exception = new NoSuchContainerException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/TestDefinition.java b/plugins/tiles/src/test/java/org/apache/tiles/api/TestDefinition.java new file mode 100644 index 0000000000..520fd997ce --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/TestDefinition.java @@ -0,0 +1,248 @@ +/* + * 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.apache.tiles.api; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests the Definition class. + */ +public class TestDefinition { + + /** + * Tests {@link Definition#Definition(Definition)}. + */ + @Test + public void testDefinitionCopy() { + Definition definition = new Definition(); + definition.setName("myDefinition"); + definition.setExtends("myExtends"); + Attribute attribute1 = new Attribute("value1"); + definition.putAttribute("name1", attribute1); + Attribute attribute2 = new Attribute("value2"); + definition.putAttribute("name2", attribute2); + Definition toCheck = new Definition(definition); + assertEquals("myDefinition", toCheck.getName()); + assertEquals("myExtends", toCheck.getExtends()); + assertEquals(attribute1, toCheck.getAttribute("name1")); + assertEquals(attribute2, toCheck.getAttribute("name2")); + } + + /** + * Tests {@link Definition#Definition(Definition)}. + */ + @Test + public void testDefinitionComplete() { + Map attributeMap = new HashMap<>(); + Attribute attribute1 = new Attribute("value1"); + Attribute attribute2 = new Attribute("value2"); + attributeMap.put("name1", attribute1); + attributeMap.put("name2", attribute2); + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + Definition definition = new Definition("myDefinition", + templateAttribute, attributeMap); + assertEquals("myDefinition", definition.getName()); + assertEquals(templateAttribute, definition.getTemplateAttribute()); + assertEquals(attribute1, definition.getAttribute("name1")); + assertEquals(attribute2, definition.getAttribute("name2")); + } + + /** + * Verifies the put Attribute functionality. Attributes are added or replaced in the definition. + */ + @Test + public void testPutAttribute() { + Definition def = new Definition(); + def.setName("test1"); + def.setTemplateAttribute(Attribute + .createTemplateAttribute("/page1.jsp")); + Attribute attr1 = new Attribute("test.definition.name", null, null, "definition"); + def.putAttribute("attr1", attr1); + + attr1 = def.getAttribute("attr1"); + assertNotNull("Null attribute.", attr1); + assertEquals("Wrong attribute type", "definition", attr1.getRenderer()); + } + + /** + * Tests the {@link Definition#inherit(BasicAttributeContext)} method. + */ + @Test + public void testInherit() { + Definition toCopy = new Definition(); + toCopy.putAttribute("name1", new Attribute("value1"), true); + toCopy.putAttribute("name2", new Attribute("value2"), true); + toCopy.putAttribute("name3", new Attribute("value3"), false); + toCopy.putAttribute("name4", new Attribute("value4"), false); + Definition context = new Definition(); + toCopy.putAttribute("name1", new Attribute("newValue1"), true); + toCopy.putAttribute("name3", new Attribute("newValue3"), false); + context.inherit(toCopy); + Attribute attribute = context.getCascadedAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "newValue1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getLocalAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "newValue3", + attribute.getValue()); + attribute = context.getLocalAttribute("name4"); + assertNotNull("Attribute name4 not found", attribute); + assertEquals("Attribute name4 has not been set correctly", "value4", + attribute.getValue()); + + toCopy = new Definition(); + toCopy.setPreparer("ExtendedPreparer"); + Attribute templateAttribute = new Attribute("extendedTemplate.jsp", + Expression.createExpression("expression", "language"), + "extendedRole", "template"); + toCopy.setTemplateAttribute(templateAttribute); + context = new Definition(); + context.inherit(toCopy); + assertEquals("Preparer not inherited", "ExtendedPreparer", context + .getPreparer()); + assertNotNull("Roles not inherited", context.getTemplateAttribute() + .getRoles()); + assertEquals("Roles not inherited", context.getTemplateAttribute() + .getRoles().size(), 1); + assertTrue("Roles not inherited", context.getTemplateAttribute() + .getRoles().contains( + "extendedRole")); + assertEquals("Template not inherited", "extendedTemplate.jsp", context + .getTemplateAttribute().getValue()); + assertEquals("Template expression not inherited", "expression", context + .getTemplateAttribute().getExpressionObject().getExpression()); + assertEquals("Template expression language not inherited", "language", + context.getTemplateAttribute().getExpressionObject() + .getLanguage()); + context = new Definition(); + context.setPreparer("LocalPreparer"); + templateAttribute = new Attribute("localTemplate.jsp", Expression + .createExpression("localExpression", "localLanguage"), + "localRole", "template"); + context.setTemplateAttribute(templateAttribute); + assertEquals("Preparer inherited", "LocalPreparer", context + .getPreparer()); + assertNotNull("Roles not correct", context.getTemplateAttribute() + .getRoles()); + assertEquals("Roles not correct", context.getTemplateAttribute() + .getRoles().size(), 1); + assertTrue("Roles inherited", context.getTemplateAttribute().getRoles() + .contains("localRole")); + assertEquals("Template inherited", "localTemplate.jsp", context + .getTemplateAttribute().getValue()); + assertEquals("Template expression inherited", "localExpression", + context.getTemplateAttribute().getExpressionObject() + .getExpression()); + assertEquals("Template expression language not inherited", + "localLanguage", context.getTemplateAttribute() + .getExpressionObject().getLanguage()); + } + + /** + * Tests {@link Definition#toString()}. + */ + @Test + public void testToString() { + Definition definition = new Definition(); + definition.setName("myDefinitionName"); + assertEquals( + "{name=myDefinitionName, template=, role=, preparerInstance=null, attributes=null}", + definition.toString()); + definition.setTemplateAttribute(Attribute.createTemplateAttribute("myTemplate")); + assertEquals( + "{name=myDefinitionName, template=myTemplate, role=null, preparerInstance=null, attributes=null}", + definition.toString()); + definition.putAttribute("myAttributeName", new Attribute("myAttributeValue")); + assertEquals( + "{name=myDefinitionName, template=myTemplate, role=null, preparerInstance=null, " + + "attributes={myAttributeName=myAttributeValue}}", + definition.toString()); + } + + /** + * Tests {@link Definition#equals(Object)}. + */ + @Test + public void testEquals() { + Definition definition = new Definition(); + definition.setName("myDefinition"); + definition.setExtends("myExtends"); + Attribute attribute1 = new Attribute("value1"); + definition.putAttribute("name1", attribute1); + Attribute attribute2 = new Attribute("value2"); + definition.putAttribute("name2", attribute2); + Definition toCheck = new Definition(definition); + assertEquals(definition, toCheck); + toCheck = new Definition(definition); + toCheck.setName("anotherDefinition"); + assertNotEquals(definition, toCheck); + toCheck = new Definition(definition); + toCheck.setExtends("anotherExtends"); + assertNotEquals(definition, toCheck); + toCheck = new Definition(definition); + toCheck.putAttribute("name1", new Attribute("anotherAttribute")); + assertNotEquals(definition, toCheck); + } + + /** + * Tests {@link Definition#hashCode()}. + */ + @Test + public void testHashCode() { + Definition definition = new Definition(); + definition.setName("myDefinition"); + definition.setExtends("myExtends"); + Attribute attribute1 = new Attribute("value1"); + definition.putAttribute("name1", attribute1); + Attribute attribute2 = new Attribute("value2"); + definition.putAttribute("name2", attribute2); + BasicAttributeContext attributeContext = new BasicAttributeContext(); + attributeContext.putAttribute("name1", attribute1); + attributeContext.putAttribute("name2", attribute2); + assertEquals("myDefinition".hashCode() + "myExtends".hashCode() + + attributeContext.hashCode(), definition.hashCode()); + } + + /** + * Tests {@link Definition#isExtending()}. + */ + @Test + public void testIsExtending() { + Definition definition = new Definition(); + definition.setName("myDefinition"); + assertFalse(definition.isExtending()); + definition.setExtends("myExtends"); + assertTrue(definition.isExtending()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/TilesContainerWrapperTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/TilesContainerWrapperTest.java new file mode 100644 index 0000000000..c4a3bb9197 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/TilesContainerWrapperTest.java @@ -0,0 +1,232 @@ +/* + * 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.apache.tiles.api; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TilesContainerWrapper}. + */ +public class TilesContainerWrapperTest { + + /** + * The container. + */ + private TilesContainer container; + + /** + * The wrapper to test. + */ + private TilesContainerWrapper wrapper; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + container = createMock(TilesContainer.class); + wrapper = new TilesContainerWrapper(container); + } + + /** + * Tests {@link TilesContainerWrapper#TilesContainerWrapper(TilesContainer)}. + */ + @Test(expected = NullPointerException.class) + public void testTilesContainerWrapperNPE() { + new TilesContainerWrapper(null); + } + + @Test + public void testEndContext() { + Request request = createMock(Request.class); + + container.endContext(request); + + replay(container, request); + wrapper.endContext(request); + verify(container, request); + } + + /** + * Test method for {@link TilesContainerWrapper#evaluate(Attribute, Request)}. + */ + @Test + public void testEvaluate() { + Request request = createMock(Request.class); + Attribute attribute = createMock(Attribute.class); + + expect(container.evaluate(attribute, request)).andReturn(1); + + replay(container, request, attribute); + assertEquals(new Integer(1), wrapper.evaluate(attribute, request)); + verify(container, request, attribute); + } + + @Test + public void testGetApplicationContext() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + expect(container.getApplicationContext()).andReturn(applicationContext); + + replay(container, applicationContext); + assertSame(applicationContext, wrapper.getApplicationContext()); + verify(container, applicationContext); + } + + /** + * Test method for {@link TilesContainerWrapper#getAttributeContext(Request)}. + */ + @Test + public void testGetAttributeContext() { + Request request = createMock(Request.class); + AttributeContext attribute = createMock(AttributeContext.class); + + expect(container.getAttributeContext(request)).andReturn(attribute); + + replay(container, request, attribute); + assertSame(attribute, wrapper.getAttributeContext(request)); + verify(container, request, attribute); + } + + /** + * Test method for {@link TilesContainerWrapper#getDefinition(String, Request)}. + */ + @Test + public void testGetDefinition() { + Request request = createMock(Request.class); + Definition definition = createMock(Definition.class); + + expect(container.getDefinition("definition", request)).andReturn(definition); + + replay(container, request, definition); + assertSame(definition, wrapper.getDefinition("definition", request)); + verify(container, request, definition); + } + + /** + * Test method for {@link TilesContainerWrapper#isValidDefinition(String, Request)}. + */ + @Test + public void testIsValidDefinition() { + Request request = createMock(Request.class); + + expect(container.isValidDefinition("definition", request)).andReturn(true); + + replay(container, request); + assertTrue(wrapper.isValidDefinition("definition", request)); + verify(container, request); + } + + /** + * Test method for {@link TilesContainerWrapper#prepare(String, Request)}. + */ + @Test + public void testPrepare() { + Request request = createMock(Request.class); + + container.prepare("preparer", request); + + replay(container, request); + wrapper.prepare("preparer", request); + verify(container, request); + } + + /** + * Test method for {@link TilesContainerWrapper#render(String, Request)}. + */ + @Test + public void testRenderStringRequest() { + Request request = createMock(Request.class); + + container.render("definition", request); + + replay(container, request); + wrapper.render("definition", request); + verify(container, request); + } + + /** + * Test method for {@link TilesContainerWrapper#render(Definition, Request)}. + */ + @Test + public void testRenderDefinitionRequest() { + Request request = createMock(Request.class); + Definition definition = createMock(Definition.class); + + container.render(definition, request); + + replay(container, request, definition); + wrapper.render(definition, request); + verify(container, request, definition); + } + + /** + * Test method for {@link TilesContainerWrapper#render(Attribute, Request)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testRenderAttributeRequest() throws IOException { + Request request = createMock(Request.class); + Attribute attribute = createMock(Attribute.class); + + container.render(attribute, request); + + replay(container, request, attribute); + wrapper.render(attribute, request); + verify(container, request, attribute); + } + + @Test + public void testRenderContext() { + Request request = createMock(Request.class); + + container.renderContext(request); + + replay(container, request); + wrapper.renderContext(request); + verify(container, request); + } + + @Test + public void testStartContext() { + Request request = createMock(Request.class); + AttributeContext attribute = createMock(AttributeContext.class); + + expect(container.startContext(request)).andReturn(attribute); + + replay(container, request, attribute); + assertSame(attribute, wrapper.startContext(request)); + verify(container, request, attribute); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/TilesExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/TilesExceptionTest.java new file mode 100644 index 0000000000..cb6b8012be --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/TilesExceptionTest.java @@ -0,0 +1,62 @@ +/* + * 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.apache.tiles.api; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link TilesException}. + */ +public class TilesExceptionTest { + + @Test + public void testTilesException() { + TilesException exception = new TilesException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testTilesExceptionString() { + TilesException exception = new TilesException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testTilesExceptionThrowable() { + Throwable cause = new Throwable(); + TilesException exception = new TilesException(cause); + assertEquals(cause.toString(), exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + @Test + public void testTilesExceptionStringThrowable() { + Throwable cause = new Throwable(); + TilesException exception = new TilesException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/access/TilesAccessTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/access/TilesAccessTest.java new file mode 100644 index 0000000000..93726132bf --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/access/TilesAccessTest.java @@ -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.apache.tiles.api.access; + +import org.apache.tiles.api.NoSuchContainerException; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link TilesAccess}. + */ +public class TilesAccessTest { + + @Test + public void testSetContainer() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + expect(context.getApplicationScope()).andReturn(attribs); + replay(context, container); + TilesAccess.setContainer(context, container, null); + assertEquals(attribs.size(), 1); + assertEquals(attribs.get(TilesAccess.CONTAINER_ATTRIBUTE), container); + verify(context, container); + } + + @Test + public void testSetContainerWithKey() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + replay(context, container); + TilesAccess.setContainer(context, container, "myKey"); + assertEquals(1, attribs.size()); + assertEquals(container, attribs.get("myKey")); + + TilesAccess.setContainer(context, null, "myKey"); + assertEquals(0, attribs.size()); + + TilesAccess.setContainer(context, container, null); + assertEquals(1, attribs.size()); + assertEquals(container, attribs.get(TilesAccess.CONTAINER_ATTRIBUTE)); + verify(context, container); + } + + @Test + public void testGetContainer() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + + replay(context, container); + attribs.put(TilesAccess.CONTAINER_ATTRIBUTE, container); + assertEquals(container, TilesAccess.getContainer(context)); + verify(context, container); + } + + @Test + public void testGetContainerWithKey() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + + replay(context, container); + attribs.put(TilesAccess.CONTAINER_ATTRIBUTE, container); + attribs.put("myKey", container); + assertEquals(container, TilesAccess.getContainer(context, null)); + assertEquals(container, TilesAccess.getContainer(context, "myKey")); + verify(context, container); + } + + @Test + public void testSetCurrentContainer() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + attribs.put("myKey", container); + Map requestScope = new HashMap<>(); + + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + expect(request.getContext("request")).andReturn(requestScope); + expect(request.getApplicationContext()).andReturn(context); + replay(request, context, container); + TilesAccess.setCurrentContainer(request, "myKey"); + assertEquals(container, requestScope.get(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME)); + verify(request, context, container); + } + + @Test(expected = NoSuchContainerException.class) + public void testSetCurrentContainerException() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + Map attribs = new HashMap<>(); + + expect(request.getApplicationContext()).andReturn(context); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + replay(request, context); + try { + TilesAccess.setCurrentContainer(request, "myKey"); + } finally { + verify(request, context); + } + } + + @Test + public void testSetCurrentContainerWithContainer() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + attribs.put("myKey", container); + Map requestScope = new HashMap<>(); + + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request, context, container); + TilesAccess.setCurrentContainer(request, container); + assertEquals(container, requestScope.get(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME)); + verify(request, context, container); + } + + @Test(expected = NullPointerException.class) + public void testSetCurrentContainerWithContainerException() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + Map attribs = new HashMap<>(); + + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + + replay(request, context); + try { + TilesAccess.setCurrentContainer(request, (TilesContainer) null); + } finally { + verify(request, context); + } + } + + @Test + public void testGetCurrentContainer() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + attribs.put("myKey", container); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(context); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request, context, container); + assertEquals(container, TilesAccess.getCurrentContainer(request)); + verify(request, context, container); + } + + @Test + public void testGetCurrentContainerDefault() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + attribs.put(TilesAccess.CONTAINER_ATTRIBUTE, container); + Map requestScope = new HashMap<>(); + + expect(request.getApplicationContext()).andReturn(context); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request, context, container); + assertEquals(container, TilesAccess.getCurrentContainer(request)); + verify(request, context, container); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/preparer/PreparerExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/preparer/PreparerExceptionTest.java new file mode 100644 index 0000000000..35cbc3bbb9 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/preparer/PreparerExceptionTest.java @@ -0,0 +1,74 @@ +/* + * 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.apache.tiles.api.preparer; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link PreparerException}. + */ +public class PreparerExceptionTest { + + /** + * Test method for {@link PreparerException#PreparerException()}. + */ + @Test + public void testPreparerException() { + PreparerException exception = new PreparerException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link PreparerException#PreparerException(String)}. + */ + @Test + public void testPreparerExceptionString() { + PreparerException exception = new PreparerException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link PreparerException#PreparerException(Throwable)}. + */ + @Test + public void testPreparerExceptionThrowable() { + Throwable cause = new Throwable(); + PreparerException exception = new PreparerException(cause); + assertEquals(cause.toString(), exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + /** + * Test method for {@link PreparerException#PreparerException(String, Throwable)}. + */ + @Test + public void testPreparerExceptionStringThrowable() { + Throwable cause = new Throwable(); + PreparerException exception = new PreparerException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelGeneratorTest.java new file mode 100644 index 0000000000..599e7f4722 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelGeneratorTest.java @@ -0,0 +1,139 @@ +/* + * 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.apache.tiles.autotag.freemarker; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests TagClassGenerator. + */ +public class FMModelGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.freemarker.test.Request"; + + /** + * Test method for TagClassGenerator#generate(File, String, TemplateSuite, + * TemplateClass, java.util.Map). + * + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + FMModelGenerator generator = new FMModelGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "boolean", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", "doStuff", + "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class."); + + generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, clazz, null, + "org.apache.tiles.autotag.freemarker.test.Runtime", REQUEST_CLASS); + + InputStream expected = getClass() + .getResourceAsStream("/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat"); + File effectiveFile = new File(file, "/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.java"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", "doStuffNoBody", + "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class."); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, clazz, null, + "org.apache.tiles.autotag.freemarker.test.Runtime", REQUEST_CLASS); + + expected = getClass() + .getResourceAsStream("/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat"); + effectiveFile = new File(file, "/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.java"); + assertTrue(effectiveFile.exists()); + effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGeneratorTest.java new file mode 100644 index 0000000000..ac3b449c45 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGeneratorTest.java @@ -0,0 +1,126 @@ +/* + * 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.apache.tiles.autotag.freemarker; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests TLDGenerator. + */ +public class FMModelRepositoryGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.freemarker.test.Request"; + + /** + * Test method for + * {@link FMModelRepositoryGenerator#generate(File, String, TemplateSuite, java.util.Map)}. + * + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + FMModelRepositoryGenerator generator = new FMModelRepositoryGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "long", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", "doStuff", + "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class"); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", "doStuffNoBody", + "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class"); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, null); + + InputStream expected = getClass() + .getResourceAsStream("/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat"); + File effectiveFile = new File(file, "/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.java"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactoryTest.java new file mode 100644 index 0000000000..c8f91af826 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactoryTest.java @@ -0,0 +1,58 @@ +/* + * 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.apache.tiles.autotag.freemarker; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests FMTemplateGeneratorFactory. + */ +public class FMTemplateGeneratorFactoryTest { + + /** + * Test method forFMTemplateGeneratorFactory#createTemplateGenerator(). + */ + @Test + public void testCreateTemplateGenerator() { + File classesOutputDirectory = createMock(File.class); + VelocityEngine velocityEngine = createMock(VelocityEngine.class); + TemplateGeneratorBuilder builder = createMock(TemplateGeneratorBuilder.class); + TemplateGenerator generator = createMock(TemplateGenerator.class); + + expect(builder.setClassesOutputDirectory(classesOutputDirectory)).andReturn(builder); + expect(builder.addClassesTemplateSuiteGenerator(isA(FMModelRepositoryGenerator.class))).andReturn(builder); + expect(builder.addClassesTemplateClassGenerator(isA(FMModelGenerator.class))).andReturn(builder); + expect(builder.build()).andReturn(generator); + + replay(classesOutputDirectory, velocityEngine, builder, generator); + FMTemplateGeneratorFactory factory = new FMTemplateGeneratorFactory(classesOutputDirectory, velocityEngine, + builder); + assertSame(generator, factory.createTemplateGenerator()); + verify(classesOutputDirectory, velocityEngine, builder, generator); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactoryTest.java new file mode 100644 index 0000000000..a753756c97 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactoryTest.java @@ -0,0 +1,61 @@ +/* + * 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.apache.tiles.autotag.jsp; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests JspTemplateGeneratorFactory. + */ +public class JspTemplateGeneratorFactoryTest { + + /** + * Test method JspTemplateGeneratorFactory#createTemplateGenerator(). + */ + @Test + public void testCreateTemplateGenerator() { + File classesOutputDirectory = createMock(File.class); + File resourcesOutputDirectory = createMock(File.class); + VelocityEngine velocityEngine = createMock(VelocityEngine.class); + TemplateGeneratorBuilder builder = createMock(TemplateGeneratorBuilder.class); + TemplateGenerator generator = createMock(TemplateGenerator.class); + + expect(builder.setClassesOutputDirectory(classesOutputDirectory)).andReturn(builder); + expect(builder.setResourcesOutputDirectory(resourcesOutputDirectory)).andReturn(builder); + expect(builder.addResourcesTemplateSuiteGenerator(isA(TLDGenerator.class))).andReturn(builder); + expect(builder.addClassesTemplateClassGenerator(isA(TagClassGenerator.class))).andReturn(builder); + expect(builder.build()).andReturn(generator); + + replay(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator); + JspTemplateGeneratorFactory factory = new JspTemplateGeneratorFactory( + classesOutputDirectory, resourcesOutputDirectory, + velocityEngine, builder); + assertSame(generator, factory.createTemplateGenerator()); + verify(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TLDGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TLDGeneratorTest.java new file mode 100644 index 0000000000..0fbe25c07a --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TLDGeneratorTest.java @@ -0,0 +1,129 @@ +/* + * 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.apache.tiles.autotag.jsp; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests TLDGenerator. + * + * @version $Rev: 1349964 $ $Date: 2012-06-13 13:18:51 -0400 (Wed, 13 Jun 2012) $ + */ +public class TLDGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.jsp.test.Request"; + + /** + * Test method for TLDGenerator#generate(File, String, TemplateSuite, Map). + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + TLDGenerator generator = new TLDGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + Map parameters = new HashMap(); + parameters.put("taglibURI", "http://www.initrode.net/tags/test"); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "long", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", + "doStuff", "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class"); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false ,true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", + "doStuffNoBody", "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class"); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, parameters); + + InputStream expected = getClass().getResourceAsStream("/tldtest-jsp.tld"); + File effectiveFile = new File(file, "META-INF/tld/tldtest-jsp.tld"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TagClassGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TagClassGeneratorTest.java new file mode 100644 index 0000000000..834ef8ebd9 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TagClassGeneratorTest.java @@ -0,0 +1,139 @@ +/* + * 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.apache.tiles.autotag.jsp; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests TagClassGenerator. + */ +public class TagClassGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.jsp.test.Request"; + + /** + * Test method for TagClassGenerator#generate(File, String, TemplateSuite, TemplateClass, Map). + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + TagClassGenerator generator = new TagClassGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + Map parameters = new HashMap(); + parameters.put("taglibURI", "http://www.initrode.net/tags/test"); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "boolean", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", + "doStuff", "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class."); + + generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, clazz, parameters, + "org.apache.tiles.autotag.jsp.test.Runtime", REQUEST_CLASS); + + InputStream expected = getClass().getResourceAsStream("/org/apache/tiles/autotag/jsp/test/DoStuffTag.java"); + File effectiveFile = new File(file, "/org/apache/tiles/autotag/jsp/test/DoStuffTag.java"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", + "doStuffNoBody", "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class."); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, clazz, parameters, + "org.apache.tiles.autotag.jsp.test.Runtime", REQUEST_CLASS); + + expected = getClass().getResourceAsStream("/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java"); + effectiveFile = new File(file, "/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java"); + assertTrue(effectiveFile.exists()); + effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateClassTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateClassTest.java new file mode 100644 index 0000000000..1b875c37d9 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateClassTest.java @@ -0,0 +1,153 @@ +/* + * 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.apache.tiles.autotag.model; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +public class TemplateClassTest { + + /** + * Test method for {@link TemplateClass#TemplateClass(String)}. + */ + @Test + public void testTemplateConstructor1() { + TemplateClass templateClass = new TemplateClass("name"); + assertEquals("name", templateClass.getName()); + assertNull(templateClass.getTagName()); + assertNull(templateClass.getTagClassPrefix()); + assertNull(templateClass.getExecuteMethod()); + Collection params = templateClass.getParameters(); + assertTrue(params.isEmpty()); + } + + /** + * Test method for {@link TemplateClass#TemplateClass(String, String, String, TemplateMethod)}. + */ + @Test + public void testTemplateConstructor2() { + TemplateMethod method = createMock(TemplateMethod.class); + + replay(method); + TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method); + assertEquals("name", templateClass.getName()); + assertEquals("tagName", templateClass.getTagName()); + assertEquals("tagClassPrefix", templateClass.getTagClassPrefix()); + assertEquals(method, templateClass.getExecuteMethod()); + verify(method); + } + + /** + * Test method for {@link TemplateClass#getSimpleName()}. + */ + @Test + public void testGetSimpleName() { + TemplateClass templateClass = new TemplateClass("name"); + assertEquals("name", templateClass.getSimpleName()); + templateClass = new TemplateClass("org.whatever.Hello"); + assertEquals("Hello", templateClass.getSimpleName()); + } + + /** + * Test method for {@link TemplateClass#setDocumentation(String)}. + */ + @Test + public void testSetDocumentation() { + TemplateClass templateClass = new TemplateClass("name"); + templateClass.setDocumentation("docs"); + assertEquals("docs", templateClass.getDocumentation()); + } + + /** + * Test method for {@link TemplateClass#getParameters()}. + */ + @Test + public void testGetParameters() { + TemplateParameter param1 = createMock(TemplateParameter.class); + TemplateParameter param2 = createMock(TemplateParameter.class); + TemplateParameter param3 = createMock(TemplateParameter.class); + TemplateParameter param4 = createMock(TemplateParameter.class); + TemplateMethod method = createMock(TemplateMethod.class); + List params = new ArrayList<>(); + + expect(method.getParameters()).andReturn(params); + expect(param1.isRequest()).andReturn(true); + expect(param2.isRequest()).andReturn(false); + expect(param2.isBody()).andReturn(true); + expect(param3.isRequest()).andReturn(false); + expect(param3.isBody()).andReturn(false); + expect(param4.isRequest()).andReturn(false); + expect(param4.isBody()).andReturn(false); + expect(param3.getName()).andReturn("param1"); + expect(param4.getName()).andReturn("param2"); + + replay(param1, param2, param3, param4, method); + params.add(param1); + params.add(param2); + params.add(param3); + params.add(param4); + + TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method); + Collection returnedParams = templateClass.getParameters(); + Iterator paramIt = returnedParams.iterator(); + assertSame(param3, paramIt.next()); + assertSame(param4, paramIt.next()); + assertFalse(paramIt.hasNext()); + verify(param1, param2, param3, param4, method); + } + + /** + * Test method for {@link TemplateClass#hasBody()}. + */ + @Test + public void testHasBody() { + TemplateMethod method = createMock(TemplateMethod.class); + expect(method.hasBody()).andReturn(true); + + replay(method); + TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method); + assertTrue(templateClass.hasBody()); + verify(method); + } + + /** + * Test method for {@link TemplateClass#toString()}. + */ + @Test + public void testToString() { + TemplateMethod method = new TemplateMethod("method", new ArrayList<>()); + TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method); + assertEquals("TemplateClass [name=name, tagName=tagName, tagClassPrefix=tagClassPrefix, " + "documentation=null, executeMethod=TemplateMethod " + "[name=method, documentation=null, parameters={}]]", templateClass.toString()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateMethodTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateMethodTest.java new file mode 100644 index 0000000000..e6ad8b1818 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateMethodTest.java @@ -0,0 +1,132 @@ +/* + * 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.apache.tiles.autotag.model; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TemplateMethod}. + */ +public class TemplateMethodTest { + + /** + * Tests {@link TemplateMethod#TemplateMethod(String, Iterable)}. + */ + @Test + public void testTemplateMethod() { + TemplateParameter param1 = createMock(TemplateParameter.class); + TemplateParameter param2 = createMock(TemplateParameter.class); + + expect(param1.getName()).andReturn("param1"); + expect(param2.getName()).andReturn("param2"); + + replay(param1, param2); + List parameters = new ArrayList<>(); + parameters.add(param1); + parameters.add(param2); + + TemplateMethod method = new TemplateMethod("method", parameters); + assertEquals("method", method.getName()); + Iterator params = method.getParameters().iterator(); + assertSame(param1, params.next()); + assertSame(param2, params.next()); + assertFalse(params.hasNext()); + assertSame(param1, method.getParameterByName("param1")); + assertSame(param2, method.getParameterByName("param2")); + verify(param1, param2); + } + + /** + * Tests {@link TemplateMethod#setDocumentation(String)}. + */ + @Test + public void testSetDocumentation() { + TemplateMethod method = new TemplateMethod("method", new ArrayList<>()); + method.setDocumentation("docs"); + assertEquals("docs", method.getDocumentation()); + } + + /** + * Tests {@link TemplateMethod#hasBody()}. + */ + @Test + public void testHasBody() { + TemplateParameter param1 = createMock(TemplateParameter.class); + TemplateParameter param2 = createMock(TemplateParameter.class); + + expect(param1.getName()).andReturn("param1"); + expect(param2.getName()).andReturn("param2"); + expect(param1.isBody()).andReturn(true); + + replay(param1, param2); + List parameters = new ArrayList<>(); + parameters.add(param1); + parameters.add(param2); + + TemplateMethod method = new TemplateMethod("method", parameters); + assertTrue(method.hasBody()); + verify(param1, param2); + } + + /** + * Tests {@link TemplateMethod#hasBody()}. + */ + @Test + public void testHasBody2() { + TemplateParameter param1 = createMock(TemplateParameter.class); + TemplateParameter param2 = createMock(TemplateParameter.class); + + expect(param1.getName()).andReturn("param1"); + expect(param2.getName()).andReturn("param2"); + expect(param1.isBody()).andReturn(false); + expect(param2.isBody()).andReturn(false); + + replay(param1, param2); + List parameters = new ArrayList<>(); + parameters.add(param1); + parameters.add(param2); + + TemplateMethod method = new TemplateMethod("method", parameters); + assertFalse(method.hasBody()); + verify(param1, param2); + } + + /** + * Tests {@link TemplateMethod#toString()}. + */ + @Test + public void testToString() { + TemplateMethod method = new TemplateMethod("method", new ArrayList<>()); + assertEquals("TemplateMethod [name=method, documentation=null, parameters={}]", method.toString()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateParameterTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateParameterTest.java new file mode 100644 index 0000000000..efa4869507 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateParameterTest.java @@ -0,0 +1,88 @@ +/* + * 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.apache.tiles.autotag.model; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TemplateParameter}. + */ +public class TemplateParameterTest { + + @Test + public void testTemplateParameter() { + TemplateParameter parameter = new TemplateParameter("name", "exportedName", "type", "defaultValue", true, false); + assertEquals("name", parameter.getName()); + assertEquals("exportedName", parameter.getExportedName()); + assertEquals("type", parameter.getType()); + assertEquals("defaultValue", parameter.getDefaultValue()); + assertTrue(parameter.isRequired()); + assertEquals("ExportedName", parameter.getGetterSetterSuffix()); + assertFalse(parameter.isBody()); + assertFalse(parameter.isRequest()); + + parameter = new TemplateParameter("name", "exportedName", "my.Request", "defaultValue", false, true); + assertEquals("name", parameter.getName()); + assertEquals("exportedName", parameter.getExportedName()); + assertEquals("my.Request", parameter.getType()); + assertEquals("defaultValue", parameter.getDefaultValue()); + assertFalse(parameter.isRequired()); + assertEquals("ExportedName", parameter.getGetterSetterSuffix()); + assertFalse(parameter.isBody()); + assertTrue(parameter.isRequest()); + + parameter = new TemplateParameter("name", "exportedName", ModelBody.class.getName(), "defaultValue", false, false); + assertEquals("name", parameter.getName()); + assertEquals("exportedName", parameter.getExportedName()); + assertEquals(ModelBody.class.getName(), parameter.getType()); + assertEquals("defaultValue", parameter.getDefaultValue()); + assertFalse(parameter.isRequired()); + assertEquals("ExportedName", parameter.getGetterSetterSuffix()); + assertTrue(parameter.isBody()); + assertFalse(parameter.isRequest()); + } + + /** + * Tests {@link TemplateParameter#setDocumentation(String)}. + */ + @Test + public void testSetDocumentation() { + TemplateParameter parameter = new TemplateParameter("name", "exportedName", "type", "defaultValue", true, false); + parameter.setDocumentation("docs"); + assertEquals("docs", parameter.getDocumentation()); + } + + /** + * Tests {@link TemplateParameter#toString()}. + */ + @Test + public void testToString() { + TemplateParameter parameter = new TemplateParameter("name", "exportedName", "type", "defaultValue", true, false); + assertEquals( + "TemplateParameter [name=name, exportedName=exportedName, " + + "documentation=null, type=type, defaultValue=defaultValue, required=true, request=false]", + parameter.toString()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateSuiteTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateSuiteTest.java new file mode 100644 index 0000000000..cdb5c52168 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateSuiteTest.java @@ -0,0 +1,112 @@ +/* + * 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.apache.tiles.autotag.model; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TemplateSuite}. + */ +public class TemplateSuiteTest { + + /** + * Test method for {@link TemplateSuite#TemplateSuite(String, String)}. + */ + @Test + public void testTemplateSuiteConstructor1() { + TemplateSuite suite = new TemplateSuite("name", "docs"); + assertEquals("name", suite.getName()); + assertEquals("docs", suite.getDocumentation()); + assertTrue(suite.getTemplateClasses().isEmpty()); + } + + /** + * Test method for {@link TemplateSuite#TemplateSuite(String, String, Iterable)}. + */ + @Test + public void testTemplateSuiteConstructor2() { + TemplateClass class1 = createMock(TemplateClass.class); + TemplateClass class2 = createMock(TemplateClass.class); + expect(class1.getName()).andReturn("class1"); + expect(class2.getName()).andReturn("class2"); + + replay(class1, class2); + List classes = new ArrayList<>(); + classes.add(class1); + classes.add(class2); + TemplateSuite suite = new TemplateSuite("name", "docs", classes); + assertEquals("name", suite.getName()); + assertEquals("docs", suite.getDocumentation()); + Iterator clazzes = suite.getTemplateClasses().iterator(); + assertSame(class1, clazzes.next()); + assertSame(class2, clazzes.next()); + assertFalse(clazzes.hasNext()); + assertSame(class1, suite.getTemplateClassByName("class1")); + assertSame(class2, suite.getTemplateClassByName("class2")); + verify(class1, class2); + } + + /** + * Test method for {@link TemplateSuite#addTemplateClass(TemplateClass)}. + */ + @Test + public void testAddTemplateClass() { + TemplateClass class1 = createMock(TemplateClass.class); + TemplateClass class2 = createMock(TemplateClass.class); + expect(class1.getName()).andReturn("class1"); + expect(class2.getName()).andReturn("class2"); + + replay(class1, class2); + TemplateSuite suite = new TemplateSuite("name", "docs"); + assertEquals("name", suite.getName()); + assertEquals("docs", suite.getDocumentation()); + assertTrue(suite.getTemplateClasses().isEmpty()); + suite.addTemplateClass(class1); + suite.addTemplateClass(class2); + Iterator clazzes = suite.getTemplateClasses().iterator(); + assertSame(class1, clazzes.next()); + assertSame(class2, clazzes.next()); + assertFalse(clazzes.hasNext()); + assertSame(class1, suite.getTemplateClassByName("class1")); + assertSame(class2, suite.getTemplateClassByName("class2")); + verify(class1, class2); + } + + /** + * Test method for {@link TemplateSuite#toString()}. + */ + @Test + public void testToString() { + TemplateSuite suite = new TemplateSuite("name", "docs"); + assertEquals("TemplateSuite [name=name, documentation=docs, templateClasses={}]", suite.toString()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/AbstractModelBodyTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/AbstractModelBodyTest.java new file mode 100644 index 0000000000..3bfe89ff58 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/AbstractModelBodyTest.java @@ -0,0 +1,157 @@ +/* + * 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.apache.tiles.autotag.runtime; + +import org.apache.tiles.autotag.core.runtime.AbstractModelBody; +import org.apache.tiles.autotag.core.runtime.util.NullWriter; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link AbstractModelBody}. + */ +public class AbstractModelBodyTest { + + /** + * Test method for {@link AbstractModelBody#evaluate()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testEvaluate() throws IOException { + Writer writer = createMock(Writer.class); + AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock(); + + modelBody.evaluate(writer); + + replay(writer, modelBody); + modelBody.evaluate(); + verify(writer, modelBody); + } + + /** + * Test method for {@link AbstractModelBody#evaluateAsString()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testEvaluateAsString() throws IOException { + AbstractModelBody modelBody = new MockModelBody(null, "return me"); + assertEquals("return me", modelBody.evaluateAsString()); + + modelBody = new MockModelBody(null, "\n \n"); + assertNull(modelBody.evaluateAsString()); + } + + /** + * Test method for {@link AbstractModelBody#evaluateAsString()}. + * + * @throws IOException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testEvaluateAsStringException() throws IOException { + Writer writer = createMock(Writer.class); + AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock(); + + modelBody.evaluate(isA(StringWriter.class)); + expectLastCall().andThrow(new IOException()); + + replay(writer, modelBody); + try { + modelBody.evaluateAsString(); + } finally { + verify(writer, modelBody); + } + } + + /** + * Test method for {@link AbstractModelBody#evaluateWithoutWriting()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testEvaluateWithoutWriting() throws IOException { + Writer writer = createMock(Writer.class); + AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock(); + + modelBody.evaluate(isA(NullWriter.class)); + + replay(writer, modelBody); + modelBody.evaluateWithoutWriting(); + verify(writer, modelBody); + } + + /** + * Test method for {@link AbstractModelBody#evaluateWithoutWriting()}. + * + * @throws IOException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testEvaluateWithoutWritingException() throws IOException { + Writer writer = createMock(Writer.class); + AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock(); + + modelBody.evaluate(isA(NullWriter.class)); + expectLastCall().andThrow(new IOException()); + + replay(writer, modelBody); + try { + modelBody.evaluateWithoutWriting(); + } finally { + verify(writer, modelBody); + } + } + + public static class MockModelBody extends AbstractModelBody { + + /** + * The result to return. + */ + private final String toReturn; + + /** + * Constructor. + * + * @param defaultWriter The default writer. + * @param toReturn The result to return. + */ + public MockModelBody(Writer defaultWriter, String toReturn) { + super(defaultWriter); + this.toReturn = toReturn; + } + + @Override + public void evaluate(Writer writer) throws IOException { + writer.write(toReturn); + } + + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/util/NullWriterTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/util/NullWriterTest.java new file mode 100644 index 0000000000..00f6b452ca --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/util/NullWriterTest.java @@ -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.apache.tiles.autotag.runtime.util; + +import org.apache.tiles.autotag.core.runtime.util.NullWriter; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests {@link NullWriter}. + */ +public class NullWriterTest { + + /** + * A dummy size. + */ + private static final int DUMMY_SIZE = 15; + /** + * The object to test. + */ + private NullWriter writer; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + writer = new NullWriter(); + } + + /** + * Test method for {@link NullWriter#write(char[], int, int)}. + */ + @Test + public void testWriteCharArrayIntInt() { + writer.write("Hello there".toCharArray(), 0, DUMMY_SIZE); + } + + /** + * Test method for {@link NullWriter#flush()}. + */ + @Test + public void testFlush() { + writer.flush(); + } + + /** + * Test method for {@link NullWriter#close()}. + */ + @Test + public void testClose() { + writer.close(); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGeneratorTest.java new file mode 100644 index 0000000000..b9854bf1ce --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGeneratorTest.java @@ -0,0 +1,139 @@ +/* + * 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.apache.tiles.autotag.velocity; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests VelocityDirectiveGenerator. + */ +public class VelocityDirectiveGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.velocity.Request"; + + /** + * Test method for VelocityDirectiveGenerator#generate(File, String, + * TemplateSuite, TemplateClass, java.util.Map). + * + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + VelocityDirectiveGenerator generator = new VelocityDirectiveGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "boolean", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", "doStuff", + "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class."); + + generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, clazz, null, + "org.apache.tiles.autotag.velocity.test.Runtime", REQUEST_CLASS); + + InputStream expected = getClass() + .getResourceAsStream("/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat"); + File effectiveFile = new File(file, "/org/apache/tiles/autotag/velocity/test/DoStuffDirective.java"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", "doStuffNoBody", + "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class."); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, clazz, null, + "org.apache.tiles.autotag.velocity.test.Runtime", REQUEST_CLASS); + + expected = getClass() + .getResourceAsStream("/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat"); + effectiveFile = new File(file, "/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.java"); + assertTrue(effectiveFile.exists()); + effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGeneratorTest.java new file mode 100644 index 0000000000..1ea2b37fc4 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGeneratorTest.java @@ -0,0 +1,125 @@ +/* + * 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.apache.tiles.autotag.velocity; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests VelocityPropertiesGenerator. + */ +public class VelocityPropertiesGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.velocity.Request"; + + /** + * Test method for org.apache.tiles.autotag.velocity.VelocityPropertiesGenerator + * #generate(File, String, TemplateSuite, java.util.Map). + * + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + VelocityPropertiesGenerator generator = new VelocityPropertiesGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "long", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", "doStuff", + "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class"); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", "doStuffNoBody", + "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class"); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, null); + + InputStream expected = getClass().getResourceAsStream("/velocity.properties.test"); + File effectiveFile = new File(file, "META-INF/velocity.properties"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactoryTest.java new file mode 100644 index 0000000000..e0924178af --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactoryTest.java @@ -0,0 +1,60 @@ +/* + * 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.apache.tiles.autotag.velocity; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests JspTemplateGeneratorFactory. + */ +public class VelocityTemplateGeneratorFactoryTest { + + /** + * Test method for VelocityTemplateGeneratorFactory#createTemplateGenerator(). + */ + @Test + public void testCreateTemplateGenerator() { + File classesOutputDirectory = createMock(File.class); + File resourcesOutputDirectory = createMock(File.class); + VelocityEngine velocityEngine = createMock(VelocityEngine.class); + TemplateGeneratorBuilder builder = createMock(TemplateGeneratorBuilder.class); + TemplateGenerator generator = createMock(TemplateGenerator.class); + + expect(builder.setClassesOutputDirectory(classesOutputDirectory)).andReturn(builder); + expect(builder.setResourcesOutputDirectory(resourcesOutputDirectory)).andReturn(builder); + expect(builder.addResourcesTemplateSuiteGenerator(isA(VelocityPropertiesGenerator.class))).andReturn(builder); + expect(builder.addClassesTemplateClassGenerator(isA(VelocityDirectiveGenerator.class))).andReturn(builder); + expect(builder.build()).andReturn(generator); + + replay(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator); + VelocityTemplateGeneratorFactory factory = new VelocityTemplateGeneratorFactory(classesOutputDirectory, + resourcesOutputDirectory, velocityEngine, builder); + assertSame(generator, factory.createTemplateGenerator()); + verify(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/DefinitionsFactoryExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/DefinitionsFactoryExceptionTest.java new file mode 100644 index 0000000000..c9f4d5bd2e --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/DefinitionsFactoryExceptionTest.java @@ -0,0 +1,74 @@ +/* + * 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.apache.tiles.core.definition; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link DefinitionsFactoryException}. + */ +public class DefinitionsFactoryExceptionTest { + + /** + * Test method for {@link DefinitionsFactoryException#DefinitionsFactoryException()}. + */ + @Test + public void testDefinitionsFactoryException() { + DefinitionsFactoryException exception = new DefinitionsFactoryException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link DefinitionsFactoryException#DefinitionsFactoryException(String)}. + */ + @Test + public void testDefinitionsFactoryExceptionString() { + DefinitionsFactoryException exception = new DefinitionsFactoryException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link DefinitionsFactoryException#DefinitionsFactoryException(Throwable)}. + */ + @Test + public void testDefinitionsFactoryExceptionThrowable() { + Throwable cause = new Throwable(); + DefinitionsFactoryException exception = new DefinitionsFactoryException(cause); + assertEquals(cause.toString(), exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + /** + * Test method for {@link DefinitionsFactoryException#DefinitionsFactoryException(String, Throwable)}. + */ + @Test + public void testDefinitionsFactoryExceptionStringThrowable() { + Throwable cause = new Throwable(); + DefinitionsFactoryException exception = new DefinitionsFactoryException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/MockDefinitionsReader.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/MockDefinitionsReader.java new file mode 100644 index 0000000000..865e2230f1 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/MockDefinitionsReader.java @@ -0,0 +1,44 @@ +/* + * 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.apache.tiles.core.definition; + +import org.apache.tiles.api.Definition; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Mock Definitions Reader implementation. Stubs out all functionality. + */ +public class MockDefinitionsReader implements DefinitionsReader { + + /** + * Reads {@link Definition} objects from a source. + * Implementations should publish what type of source object is expected. + * + * @param source The source from which definitions will be read. + * @return a Map of Definition objects read from + * the source. + * @throws org.apache.tiles.core.definition.DefinitionsFactoryException if the source is invalid or + * an error occurs when reading definitions. + */ + public Map read(Object source) { + return new LinkedHashMap<>(); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/NoSuchDefinitionExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/NoSuchDefinitionExceptionTest.java new file mode 100644 index 0000000000..9e2c2faabc --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/NoSuchDefinitionExceptionTest.java @@ -0,0 +1,42 @@ +/* + * 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.apache.tiles.core.definition; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link NoSuchDefinitionException}. + */ +public class NoSuchDefinitionExceptionTest { + + /** + * Test method for {@link NoSuchDefinitionException#NoSuchDefinitionException(String)}. + */ + @Test + public void testNoSuchDefinitionExceptionString() { + NoSuchDefinitionException exception = new NoSuchDefinitionException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactoryTest.java new file mode 100644 index 0000000000..1d136589fd --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactoryTest.java @@ -0,0 +1,63 @@ +/* + * 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.apache.tiles.core.definition; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.dao.DefinitionDAO; +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.Locale; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link UnresolvingLocaleDefinitionsFactory}. + */ +public class UnresolvingLocaleDefinitionsFactoryTest { + + /** + * Test method for {@link UnresolvingLocaleDefinitionsFactory#getDefinition(String, Request)}. + */ + @Test + public void testGetDefinition() { + DefinitionDAO dao = createMock(DefinitionDAO.class); + LocaleResolver localeResolver = createMock(LocaleResolver.class); + UnresolvingLocaleDefinitionsFactory factory = new UnresolvingLocaleDefinitionsFactory(); + Request request = createMock(Request.class); + Definition definition = createMock(Definition.class); + Locale locale = Locale.ITALY; + + expect(localeResolver.resolveLocale(request)).andReturn(locale); + expect(dao.getDefinition("myDefinition", locale)).andReturn(definition); + + replay(dao, localeResolver, request, definition); + factory.setDefinitionDAO(dao); + factory.setLocaleResolver(localeResolver); + assertEquals(definition, factory.getDefinition("myDefinition", request)); + verify(dao, localeResolver, request, definition); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAOTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAOTest.java new file mode 100644 index 0000000000..77dc4fba9a --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAOTest.java @@ -0,0 +1,156 @@ +/* + * 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.apache.tiles.core.definition.dao; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.RefreshMonitor; +import org.apache.tiles.core.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.locale.PostfixedApplicationResource; +import org.junit.Before; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link BaseLocaleUrlDefinitionDAO}. + */ +public class BaseLocaleUrlDefinitionDAOTest { + + private static final class MutableApplicationResource extends PostfixedApplicationResource { + private long lastModified = System.currentTimeMillis(); + private String xml = "\n" + + "\n\n" + "" + + "" + + "" + "" // + + ""; + + private MutableApplicationResource(String localePath) { + super(localePath); + } + + public void modify(String xml) { + lastModified = System.currentTimeMillis(); + this.xml = xml; + } + + @Override + public long getLastModified() { + return lastModified; + } + + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(xml.getBytes(StandardCharsets.ISO_8859_1)); + } + } + + /** + * The time (in milliseconds) to wait to be sure that the system updates the + * modify date of a file. + */ + private static final int SLEEP_MILLIS = 2000; + + private BaseLocaleUrlDefinitionDAO dao; + private MutableApplicationResource resource; + + @Before + public void setUp() throws IOException { + resource = new MutableApplicationResource("org/apache/tiles/core/config/temp-defs.xml"); + + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(applicationContext.getResource("org/apache/tiles/core/config/temp-defs.xml")).andReturn(resource).anyTimes(); + replay(applicationContext); + dao = createMockBuilder(BaseLocaleUrlDefinitionDAO.class).withConstructor(applicationContext).createMock(); + } + + /** + * Test method for {@link org.apache.tiles.core.definition.dao.BaseLocaleUrlDefinitionDAO#refreshRequired()}. + * + * @throws InterruptedException If something goes wrong. + */ + @Test + public void testRefreshRequired() throws InterruptedException { + // Set up multiple data sources. + Map attribs = new HashMap<>(); + attribs.put("testparm", new Attribute("testval")); + Definition rewriteTest = new Definition("rewrite.test", Attribute.createTemplateAttribute("/test.jsp"), attribs); + expect(dao.getDefinition("rewrite.test", null)).andReturn(rewriteTest); + + replay(dao); + + List sources = new ArrayList<>(); + sources.add(resource); + dao.setSources(sources); + DefinitionsReader reader = new DigesterDefinitionsReader(); + dao.setReader(reader); + + Request context = createMock(Request.class); + expect(context.getContext("session")).andReturn(new HashMap<>()).anyTimes(); + expect(context.getRequestLocale()).andReturn(null).anyTimes(); + replay(context); + + Definition definition = dao.getDefinition("rewrite.test", null); + assertNotNull("rewrite.test definition not found.", definition); + assertEquals("Incorrect initial template value", "/test.jsp", definition.getTemplateAttribute().getValue()); + + RefreshMonitor reloadable = dao; + dao.loadDefinitionsFromResource(resource); + assertFalse("Factory should be fresh.", reloadable.refreshRequired()); + + // Make sure the system actually updates the timestamp. + Thread.sleep(SLEEP_MILLIS); + + // Set up multiple data sources. + resource.modify("\n" + "\n\n" + "" + + "" + + "" + "" // + + ""); + + assertTrue("Factory should be stale.", reloadable.refreshRequired()); + + verify(context, dao); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAOTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAOTest.java new file mode 100644 index 0000000000..0485773219 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAOTest.java @@ -0,0 +1,371 @@ +/* + * 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.apache.tiles.core.definition.dao; + +import junit.framework.TestCase; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.MockDefinitionsReader; +import org.apache.tiles.core.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.core.definition.pattern.BasicPatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.locale.URLApplicationResource; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reset; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link CachingLocaleUrlDefinitionDAO}. + * + * @version $Rev$ $Date$ + */ +public class CachingLocaleUrlDefinitionDAOTest extends TestCase { + + /** + * The object to test. + */ + private CachingLocaleUrlDefinitionDAO definitionDao; + + private ApplicationContext applicationContext; + + private ApplicationResource url1; + + private ApplicationResource url2; + + private ApplicationResource url3; + + private ApplicationResource urlWildcard; + + private ApplicationResource url21; + + private ApplicationResource setupUrl(String filename, Locale... locales) { + ApplicationResource url = new URLApplicationResource( + "org/apache/tiles/core/config/" + filename + ".xml", + Objects.requireNonNull(this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/" + filename + ".xml")) + ); + assertNotNull("Could not load " + filename + " file.", url); + expect(applicationContext.getResource(url.getLocalePath())).andReturn(url).anyTimes(); + expect(applicationContext.getResource(url, Locale.ROOT)).andReturn(url).anyTimes(); + Map localeResources = new HashMap(); + for (Locale locale : locales) { + ApplicationResource urlLocale = new URLApplicationResource( + "org/apache/tiles/core/config/" + filename + "_" + locale.toString() + ".xml", + Objects.requireNonNull(this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/" + filename + "_" + locale + ".xml")) + ); + assertNotNull("Could not load " + filename + "_" + locale + " file.", urlLocale); + localeResources.put(locale, urlLocale); + } + for (Locale locale : new Locale[]{Locale.CANADA_FRENCH, Locale.FRENCH, Locale.US, Locale.ENGLISH, + Locale.CHINA, Locale.CHINESE, Locale.ITALY, Locale.ITALIAN}) { + ApplicationResource urlLocale = localeResources.get(locale); + expect(applicationContext.getResource(url, locale)).andReturn(urlLocale).anyTimes(); + } + return url; + } + + /** + * {@inheritDoc} + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + applicationContext = createMock(ApplicationContext.class); + url1 = setupUrl("defs1", Locale.FRENCH, Locale.CANADA_FRENCH, Locale.US); + url2 = setupUrl("defs2"); + url3 = setupUrl("defs3"); + urlWildcard = setupUrl("defs-wildcard"); + url21 = setupUrl("tiles-defs-2.1", Locale.ITALIAN); + replay(applicationContext); + definitionDao = new CachingLocaleUrlDefinitionDAO(applicationContext); + WildcardDefinitionPatternMatcherFactory definitionPatternMatcherFactory = + new WildcardDefinitionPatternMatcherFactory(); + PatternDefinitionResolver definitionResolver = new BasicPatternDefinitionResolver<>( + definitionPatternMatcherFactory, + definitionPatternMatcherFactory); + definitionDao.setPatternDefinitionResolver(definitionResolver); + } + + public void testGetDefinition() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + + assertNotNull("test.def1 definition not found.", definitionDao + .getDefinition("test.def1", null)); + assertNotNull("test.def2 definition not found.", definitionDao + .getDefinition("test.def2", null)); + assertNotNull("test.def3 definition not found.", definitionDao + .getDefinition("test.def3", null)); + assertNotNull("test.common definition not found.", definitionDao + .getDefinition("test.common", null)); + assertNotNull("test.common definition in US locale not found.", + definitionDao.getDefinition("test.common", Locale.US)); + assertNotNull("test.common definition in FRENCH locale not found.", + definitionDao.getDefinition("test.common", Locale.FRENCH)); + assertNotNull("test.common definition in CHINA locale not found.", + definitionDao.getDefinition("test.common", Locale.CHINA)); + assertNotNull( + "test.common.french definition in FRENCH locale not found.", + definitionDao.getDefinition("test.common.french", + Locale.FRENCH)); + assertNotNull( + "test.common.french definition in CANADA_FRENCH locale not found.", + definitionDao.getDefinition("test.common.french", + Locale.CANADA_FRENCH)); + assertNotNull("test.def.toextend definition not found.", definitionDao + .getDefinition("test.def.toextend", null)); + assertNotNull("test.def.overridden definition not found.", + definitionDao.getDefinition("test.def.overridden", null)); + assertNotNull( + "test.def.overridden definition in FRENCH locale not found.", + definitionDao.getDefinition("test.def.overridden", + Locale.FRENCH)); + + assertEquals("Incorrect default country value", "default", + definitionDao.getDefinition("test.def1", null).getAttribute( + "country").getValue()); + assertEquals("Incorrect US country value", "US", definitionDao + .getDefinition("test.def1", Locale.US).getAttribute("country") + .getValue()); + assertEquals("Incorrect France country value", "France", definitionDao + .getDefinition("test.def1", Locale.FRENCH).getAttribute( + "country").getValue()); + assertEquals("Incorrect Chinese country value (should be default)", + "default", definitionDao.getDefinition("test.def1", + Locale.CHINA).getAttribute("country").getValue()); + assertEquals("Incorrect default country value", "default", + definitionDao.getDefinition("test.def.overridden", null) + .getAttribute("country").getValue()); + assertEquals("Incorrect default title value", + "Definition to be overridden", definitionDao.getDefinition( + "test.def.overridden", null).getAttribute("title") + .getValue()); + assertEquals("Incorrect France country value", "France", definitionDao + .getDefinition("test.def.overridden", Locale.FRENCH) + .getAttribute("country").getValue()); + assertNull("Definition in French not found", definitionDao + .getDefinition("test.def.overridden", Locale.FRENCH) + .getAttribute("title")); + } + + public void testGetDefinitions() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + + Map defaultDefinitions = definitionDao + .getDefinitions(null); + Map usDefinitions = definitionDao + .getDefinitions(Locale.US); + Map frenchDefinitions = definitionDao + .getDefinitions(Locale.FRENCH); + Map chinaDefinitions = definitionDao + .getDefinitions(Locale.CHINA); + Map canadaFrenchDefinitions = definitionDao + .getDefinitions(Locale.CANADA_FRENCH); + + assertNotNull("test.def1 definition not found.", defaultDefinitions + .get("test.def1")); + assertNotNull("test.def2 definition not found.", defaultDefinitions + .get("test.def2")); + assertNotNull("test.def3 definition not found.", defaultDefinitions + .get("test.def3")); + assertNotNull("test.common definition not found.", defaultDefinitions + .get("test.common")); + assertNotNull("test.common definition in US locale not found.", + usDefinitions.get("test.common")); + assertNotNull("test.common definition in FRENCH locale not found.", + frenchDefinitions.get("test.common")); + assertNotNull("test.common definition in CHINA locale not found.", + chinaDefinitions.get("test.common")); + assertNotNull( + "test.common.french definition in FRENCH locale not found.", + frenchDefinitions.get("test.common.french")); + assertNotNull( + "test.common.french definition in CANADA_FRENCH locale not found.", + canadaFrenchDefinitions.get("test.common.french")); + assertNotNull("test.def.toextend definition not found.", + defaultDefinitions.get("test.def.toextend")); + assertNotNull("test.def.overridden definition not found.", + defaultDefinitions.get("test.def.overridden")); + assertNotNull( + "test.def.overridden definition in FRENCH locale not found.", + frenchDefinitions.get("test.def.overridden")); + + assertEquals("Incorrect default country value", "default", + defaultDefinitions.get("test.def1").getAttribute("country") + .getValue()); + assertEquals("Incorrect US country value", "US", usDefinitions.get( + "test.def1").getAttribute("country").getValue()); + assertEquals("Incorrect France country value", "France", + frenchDefinitions.get("test.def1").getAttribute("country") + .getValue()); + assertEquals("Incorrect Chinese country value (should be default)", + "default", chinaDefinitions.get("test.def1").getAttribute( + "country").getValue()); + assertEquals("Incorrect default country value", "default", + defaultDefinitions.get("test.def.overridden").getAttribute( + "country").getValue()); + assertEquals("Incorrect default title value", + "Definition to be overridden", defaultDefinitions.get( + "test.def.overridden").getAttribute("title").getValue()); + assertEquals("Incorrect France country value", "France", + frenchDefinitions.get("test.def.overridden").getAttribute( + "country").getValue()); + assertNull("Definition in French not found", frenchDefinitions.get( + "test.def.overridden").getAttribute("title")); + } + + public void testSetSourceURLs() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + assertEquals("The source URLs are not set correctly", sourceURLs, + definitionDao.sources); + } + + public void testSetReader() { + DefinitionsReader reader = createMock(DefinitionsReader.class); + definitionDao.setReader(reader); + assertEquals("There reader has not been set correctly", reader, + definitionDao.reader); + } + + public void testInit() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Set urlSet = new HashSet<>(); + urlSet.add(url1); + expect(applicationContext.getResources("/WEB-INF/tiles.xml")) + .andReturn(urlSet); + replay(applicationContext); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + definitionDao.setSources(sourceURLs); + assertEquals("The reader is not of the correct class", + DigesterDefinitionsReader.class, definitionDao.reader + .getClass()); + assertEquals("The source URLs are not correct", sourceURLs, + definitionDao.sources); + reset(applicationContext); + + definitionDao.setReader(new MockDefinitionsReader()); + assertEquals("The reader is not of the correct class", + MockDefinitionsReader.class, definitionDao.reader.getClass()); + sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + assertEquals("The source URLs are not correct", sourceURLs, + definitionDao.sources); + } + + /** + * Tests wildcard mappings. + */ + public void testWildcardMapping() { + List urls = new ArrayList<>(); + urls.add(urlWildcard); + definitionDao.setSources(urls); + definitionDao.setReader(new DigesterDefinitionsReader()); + + Definition definition = definitionDao.getDefinition("test.defName.subLayered", Locale.ITALY); + assertEquals("The template is not correct", "/testName.jsp", definition + .getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", + "/common/headerLayered.jsp", definition.getAttribute("header") + .getValue()); + definition = definitionDao.getDefinition("test.defName.subLayered", Locale.ITALIAN); + assertEquals("The template is not correct", "/testName.jsp", definition + .getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", + "/common/headerLayered.jsp", definition.getAttribute("header") + .getValue()); + definition = definitionDao.getDefinition("test.defName.subLayered", null); + assertEquals("The template is not correct", "/testName.jsp", definition + .getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", + "/common/headerLayered.jsp", definition.getAttribute("header") + .getValue()); + definition = definitionDao.getDefinition("test.defName.noAttribute", null); + assertEquals("/testName.jsp", definition.getTemplateAttribute().getValue()); + assertNull(definition.getLocalAttributeNames()); + definition = definitionDao.getDefinition("test.def3", null); + assertNotNull("The simple definition is null", definition); + + definition = definitionDao.getDefinition("test.extended.defName.subLayered", null); + assertEquals("test.defName.subLayered", definition.getExtends()); + assertNull(definition.getTemplateAttribute().getValue()); + assertEquals(1, definition.getLocalAttributeNames().size()); + assertEquals("Overridden Title", definition.getAttribute("title").getValue()); + } + + /** + * Tests + * {@link ResolvingLocaleUrlDefinitionDAO#getDefinition(String, Locale)} + * when loading multiple files for a locale. + */ + public void testListAttributeLocaleInheritance() { + List urls = new ArrayList<>(); + urls.add(url21); + definitionDao.setSources(urls); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + definitionDao.setReader(new DigesterDefinitionsReader()); + replay(applicationContext); + + Definition definition = definitionDao.getDefinition( + "test.inherit.list", Locale.ITALIAN); + ListAttribute listAttribute = (ListAttribute) definition + .getAttribute("list"); + List attributes = listAttribute.getValue(); + // It is right not to resolve inheritance in this DAO. + assertEquals(1, attributes.size()); + verify(applicationContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java new file mode 100644 index 0000000000..727617b699 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java @@ -0,0 +1,391 @@ +/* + * 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.apache.tiles.core.definition.dao; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.MockDefinitionsReader; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.core.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.core.definition.pattern.BasicPatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.locale.URLApplicationResource; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reset; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link ResolvingLocaleUrlDefinitionDAO}. + */ +public class ResolvingLocaleUrlDefinitionDAOTest { + + /** + * The number of attribute names. + */ + private static final int ATTRIBUTE_NAMES_COUNT = 6; + + /** + * The object to test. + */ + private ResolvingLocaleUrlDefinitionDAO definitionDao; + + private ApplicationContext applicationContext; + + private ApplicationResource url1; + private ApplicationResource url2; + private ApplicationResource url3; + private ApplicationResource urlWildcard; + private ApplicationResource url21; + private ApplicationResource url513; + + private ApplicationResource setupUrl(String filename, Locale... locales) { + ApplicationResource url = new URLApplicationResource( + "org/apache/tiles/core/config/" + filename + ".xml", + Objects.requireNonNull(this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/" + filename + ".xml")) + ); + assertNotNull("Could not load " + filename + " file.", url); + expect(applicationContext.getResource(url.getLocalePath())).andReturn(url).anyTimes(); + expect(applicationContext.getResource(url, Locale.ROOT)).andReturn(url).anyTimes(); + Map localeResources = new HashMap<>(); + for (Locale locale : locales) { + ApplicationResource urlLocale = new URLApplicationResource( + "org/apache/tiles/core/config/" + filename + "_" + locale + ".xml", + Objects.requireNonNull(this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/" + filename + "_" + locale.toString() + ".xml")) + ); + assertNotNull("Could not load " + filename + "_" + locale + " file.", urlLocale); + localeResources.put(locale, urlLocale); + } + Locale[] supportedLocales = { + Locale.CANADA_FRENCH, + Locale.FRENCH, + Locale.US, + Locale.ENGLISH, + Locale.CHINA, + Locale.CHINESE, + Locale.ITALY, + Locale.ITALIAN, + new Locale("es"), + new Locale("es", "CO"), + new Locale("en", "CA") + }; + for (Locale locale : supportedLocales) { + ApplicationResource urlLocale = localeResources.get(locale); + expect(applicationContext.getResource(url, locale)).andReturn(urlLocale).anyTimes(); + } + return url; + } + + @Before + public void setUp() throws IOException { + // Set up multiple data sources. + applicationContext = createMock(ApplicationContext.class); + url1 = setupUrl("defs1", Locale.FRENCH, Locale.CANADA_FRENCH, Locale.US); + url2 = setupUrl("defs2"); + url3 = setupUrl("defs3"); + urlWildcard = setupUrl("defs-wildcard"); + url21 = setupUrl("tiles-defs-2.1", Locale.ITALIAN); + url513 = setupUrl("defs-tiles-513"); + replay(applicationContext); + + definitionDao = new ResolvingLocaleUrlDefinitionDAO(applicationContext); + WildcardDefinitionPatternMatcherFactory definitionPatternMatcherFactory = new WildcardDefinitionPatternMatcherFactory(); + PatternDefinitionResolver definitionResolver = new BasicPatternDefinitionResolver<>( + definitionPatternMatcherFactory, definitionPatternMatcherFactory); + definitionDao.setPatternDefinitionResolver(definitionResolver); + } + + @Test + public void testGetDefinition() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + + assertNotNull("test.def1 definition not found.", definitionDao.getDefinition("test.def1", null)); + assertNotNull("test.def2 definition not found.", definitionDao.getDefinition("test.def2", null)); + assertNotNull("test.def3 definition not found.", definitionDao.getDefinition("test.def3", null)); + assertNotNull("test.common definition not found.", definitionDao.getDefinition("test.common", null)); + assertNotNull("test.common definition in US locale not found.", + definitionDao.getDefinition("test.common", Locale.US)); + assertNotNull("test.common definition in FRENCH locale not found.", + definitionDao.getDefinition("test.common", Locale.FRENCH)); + assertNotNull("test.common definition in CHINA locale not found.", + definitionDao.getDefinition("test.common", Locale.CHINA)); + assertNotNull("test.common.french definition in FRENCH locale not found.", + definitionDao.getDefinition("test.common.french", Locale.FRENCH)); + assertNotNull("test.common.french definition in CANADA_FRENCH locale not found.", + definitionDao.getDefinition("test.common.french", Locale.CANADA_FRENCH)); + assertNotNull("test.def.toextend definition not found.", definitionDao.getDefinition("test.def.toextend", null)); + assertNotNull("test.def.overridden definition not found.", + definitionDao.getDefinition("test.def.overridden", null)); + assertNotNull("test.def.overridden definition in FRENCH locale not found.", + definitionDao.getDefinition("test.def.overridden", Locale.FRENCH)); + + assertEquals("Incorrect default country value", "default", definitionDao.getDefinition("test.def1", null) + .getAttribute("country").getValue()); + assertEquals("Incorrect US country value", "US", definitionDao.getDefinition("test.def1", Locale.US) + .getAttribute("country").getValue()); + assertEquals("Incorrect France country value", "France", definitionDao + .getDefinition("test.def1", Locale.FRENCH).getAttribute("country").getValue()); + assertEquals("Incorrect Chinese country value (should be default)", "default", + definitionDao.getDefinition("test.def1", Locale.CHINA).getAttribute("country").getValue()); + assertEquals("Incorrect default country value", "default", + definitionDao.getDefinition("test.def.overridden", null).getAttribute("country").getValue()); + assertEquals("Incorrect default title value", "Definition to be overridden", + definitionDao.getDefinition("test.def.overridden", null).getAttribute("title").getValue()); + assertEquals("Incorrect France country value", "France", + definitionDao.getDefinition("test.def.overridden", Locale.FRENCH).getAttribute("country").getValue()); + assertEquals("Incorrect France title value", "Definition to be extended", + definitionDao.getDefinition("test.def.overridden", Locale.FRENCH).getAttribute("title").getValue()); + } + + @Test + public void testGetDefinitions() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + + Map defaultDefinitions = definitionDao.getDefinitions(null); + Map usDefinitions = definitionDao.getDefinitions(Locale.US); + Map frenchDefinitions = definitionDao.getDefinitions(Locale.FRENCH); + Map chinaDefinitions = definitionDao.getDefinitions(Locale.CHINA); + Map canadaFrendDefinitions = definitionDao.getDefinitions(Locale.CANADA_FRENCH); + + assertNotNull("test.def1 definition not found.", defaultDefinitions.get("test.def1")); + assertNotNull("test.def2 definition not found.", defaultDefinitions.get("test.def2")); + assertNotNull("test.def3 definition not found.", defaultDefinitions.get("test.def3")); + assertNotNull("test.common definition not found.", defaultDefinitions.get("test.common")); + assertNotNull("test.common definition in US locale not found.", usDefinitions.get("test.common")); + assertNotNull("test.common definition in FRENCH locale not found.", frenchDefinitions.get("test.common")); + assertNotNull("test.common definition in CHINA locale not found.", chinaDefinitions.get("test.common")); + assertNotNull("test.common.french definition in FRENCH locale not found.", + canadaFrendDefinitions.get("test.common.french")); + assertNotNull("test.common.french definition in CANADA_FRENCH locale not found.", + canadaFrendDefinitions.get("test.common.french")); + assertNotNull("test.def.toextend definition not found.", defaultDefinitions.get("test.def.toextend")); + assertNotNull("test.def.overridden definition not found.", defaultDefinitions.get("test.def.overridden")); + assertNotNull("test.def.overridden definition in FRENCH locale not found.", + frenchDefinitions.get("test.def.overridden")); + + assertEquals("Incorrect default country value", "default", + defaultDefinitions.get("test.def1").getAttribute("country").getValue()); + assertEquals("Incorrect US country value", "US", usDefinitions.get("test.def1").getAttribute("country") + .getValue()); + assertEquals("Incorrect France country value", "France", + frenchDefinitions.get("test.def1").getAttribute("country").getValue()); + assertEquals("Incorrect Chinese country value (should be default)", "default", chinaDefinitions + .get("test.def1").getAttribute("country").getValue()); + assertEquals("Incorrect default country value", "default", defaultDefinitions.get("test.def.overridden") + .getAttribute("country").getValue()); + assertEquals("Incorrect default title value", "Definition to be overridden", + defaultDefinitions.get("test.def.overridden").getAttribute("title").getValue()); + assertEquals("Incorrect France country value", "France", frenchDefinitions.get("test.def.overridden") + .getAttribute("country").getValue()); + assertEquals("Incorrect France title value", "Definition to be extended", + frenchDefinitions.get("test.def.overridden").getAttribute("title").getValue()); + } + + @Test + public void testSetSourceURLs() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + assertEquals("The source URLs are not set correctly", sourceURLs, definitionDao.sources); + } + + @Test + public void testSetReader() { + DefinitionsReader reader = createMock(DefinitionsReader.class); + definitionDao.setReader(reader); + assertEquals("There reader has not been set correctly", reader, definitionDao.reader); + } + + /** + * Tests {@link ResolvingLocaleUrlDefinitionDAO#resolveInheritance(Definition, Map, Locale, Set)}. + */ + @Test(expected = NoSuchDefinitionException.class) + public void testResolveInheritanceNoParent() { + Definition definition = new Definition("mydef", null, null); + definition.setExtends("otherDef"); + definitionDao.resolveInheritance(definition, new HashMap<>(), Locale.ITALY, + new HashSet<>()); + } + + /** + * Tests execution. + */ + @Test + public void testInit() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Set urlSet = new HashSet<>(); + urlSet.add(url1); + expect(applicationContext.getResources("/WEB-INF/tiles.xml")).andReturn(urlSet); + replay(applicationContext); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + definitionDao.setSources(sourceURLs); + assertEquals("The reader is not of the correct class", DigesterDefinitionsReader.class, + definitionDao.reader.getClass()); + assertEquals("The source URLs are not correct", sourceURLs, definitionDao.sources); + reset(applicationContext); + + applicationContext = createMock(ApplicationContext.class); + replay(applicationContext); + definitionDao.setReader(new MockDefinitionsReader()); + assertEquals("The reader is not of the correct class", MockDefinitionsReader.class, + definitionDao.reader.getClass()); + sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + assertEquals("The source URLs are not correct", sourceURLs, definitionDao.sources); + verify(applicationContext); + } + + /** + * Tests wildcard mappings. + */ + @Test + public void testWildcardMapping() { + List urls = new ArrayList<>(); + urls.add(urlWildcard); + definitionDao.setSources(urls); + definitionDao.setReader(new DigesterDefinitionsReader()); + + Definition definition = definitionDao.getDefinition("test.defName.subLayered", Locale.ITALY); + assertEquals("The template is not correct", "/testName.jsp", definition.getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", "/common/headerLayered.jsp", + definition.getAttribute("header").getValue()); + definition = definitionDao.getDefinition("test.defName.subLayered", Locale.ITALIAN); + assertEquals("The template is not correct", "/testName.jsp", definition.getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", "/common/headerLayered.jsp", + definition.getAttribute("header").getValue()); + definition = definitionDao.getDefinition("test.defName.subLayered", null); + assertEquals("The template is not correct", "/testName.jsp", definition.getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", "/common/headerLayered.jsp", + definition.getAttribute("header").getValue()); + definition = definitionDao.getDefinition("test.defName.noAttribute", null); + assertEquals("/testName.jsp", definition.getTemplateAttribute().getValue()); + assertNull(definition.getLocalAttributeNames()); + definition = definitionDao.getDefinition("test.def3", null); + assertNotNull("The simple definition is null", definition); + + definition = definitionDao.getDefinition("test.extended.defName.subLayered", null); + assertEquals("test.defName.subLayered", definition.getExtends()); + assertEquals(ATTRIBUTE_NAMES_COUNT, definition.getLocalAttributeNames().size()); + assertEquals("The template is not correct", "/testName.jsp", definition.getTemplateAttribute().getValue()); + assertEquals("Overridden Title", definition.getAttribute("title").getValue()); + assertEquals("The header attribute is not correct", "/common/headerLayered.jsp", + definition.getAttribute("header").getValue()); + } + + /** + * Tests + * {@link ResolvingLocaleUrlDefinitionDAO#getDefinition(String, Locale)} + * when loading multiple files for a locale. + */ + @Test + public void testListAttributeLocaleInheritance() { + List urls = new ArrayList<>(); + urls.add(url21); + definitionDao.setSources(urls); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + definitionDao.setReader(new DigesterDefinitionsReader()); + replay(applicationContext); + + Definition definition = definitionDao.getDefinition("test.inherit.list", Locale.ITALIAN); + ListAttribute listAttribute = (ListAttribute) definition.getAttribute("list"); + List attributes = listAttribute.getValue(); + assertEquals(2, attributes.size()); + verify(applicationContext); + } + + @Test + public void testTiles512() { + List urls = new ArrayList<>(); + urls.add(url21); + definitionDao.setSources(urls); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + definitionDao.setReader(new DigesterDefinitionsReader()); + replay(applicationContext); + + Definition definition = definitionDao.getDefinition("test.inherit.othertype", Locale.ITALIAN); + assertEquals("/layout.ftl", definition.getTemplateAttribute().getValue()); + assertEquals("freemarker", definition.getTemplateAttribute().getRenderer()); + } + + @Test + public void testTiles513() { + List urls = new ArrayList<>(); + urls.add(url513); + definitionDao.setSources(urls); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + definitionDao.setReader(new DigesterDefinitionsReader()); + replay(applicationContext); + + Definition definition = definitionDao.getDefinition("test.anonymous", null); + definitionDao.getDefinition("test.anonymous", new Locale("es", "CO")); + definitionDao.getDefinition("test.anonymous", new Locale("en", "CA")); + Attribute attribute = definition.getAttribute("header"); + Definition child = definitionDao.getDefinition((String) attribute.getValue(), null); + assertNotNull(child); + attribute = definition.getAttribute("menu"); + child = definitionDao.getDefinition((String) attribute.getValue(), null); + assertNotNull(child); + attribute = definition.getAttribute("footer"); + child = definitionDao.getDefinition((String) attribute.getValue(), null); + assertNotNull(child); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderExceptionTest.java new file mode 100644 index 0000000000..55403cbbbf --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderExceptionTest.java @@ -0,0 +1,41 @@ +/* + * 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.apache.tiles.core.definition.digester; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link DigesterDefinitionsReaderException}. + */ +public class DigesterDefinitionsReaderExceptionTest { + + /** + * Test method for {@link DigesterDefinitionsReaderException#DigesterDefinitionsReaderException(String)}. + */ + @Test + public void testDigesterDefinitionsReaderExceptionString() { + DigesterDefinitionsReaderException exception = new DigesterDefinitionsReaderException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/TestDigesterDefinitionsReader.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/TestDigesterDefinitionsReader.java new file mode 100644 index 0000000000..f8a5ee0a3e --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/TestDigesterDefinitionsReader.java @@ -0,0 +1,279 @@ +/* + * 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.apache.tiles.core.definition.digester; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.core.definition.DefinitionsFactoryException; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests the org.apache.tiles.definition.digester.DigesterDefinitionsReader class. + */ +public class TestDigesterDefinitionsReader { + + private DigesterDefinitionsReader reader; + + @Before + public void setUp() { + reader = new DigesterDefinitionsReader(); + } + + /** + * Tests the read method under normal conditions. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testRead() throws IOException { + URL configFile = this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/tiles-defs.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + Map definitions = reader.read(source); + + assertNotNull("Definitions not returned.", definitions); + assertNotNull("Couldn't find doc.mainLayout tile.", definitions.get("doc.mainLayout")); + assertNotNull("Couldn't Find title attribute.", definitions.get("doc.mainLayout").getAttribute("title").getValue()); + assertEquals("Incorrect Find title attribute.", "Tiles Library Documentation", definitions.get("doc.mainLayout").getAttribute("title").getValue()); + + Definition def = definitions.get("doc.role.test"); + assertNotNull("Couldn't find doc.role.test tile.", def); + Attribute attribute = def.getAttribute("title"); + assertNotNull("Couldn't Find title attribute.", attribute.getValue()); + assertEquals("Role 'myrole' expected", attribute.getRole(), "myrole"); + + def = definitions.get("doc.listattribute.test"); + assertNotNull("Couldn't find doc.listattribute.test tile.", def); + attribute = def.getAttribute("items"); + assertNotNull("Couldn't Find items attribute.", attribute); + assertTrue("The class of the attribute is not right", attribute instanceof ListAttribute); + assertTrue("The class of value of the attribute is not right", attribute.getValue() instanceof List); + } + + + /** + * Tests the read method under normal conditions for the new features in 2.1 + * version of the DTD. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testRead21Version() throws IOException { + URL configFile = this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/tiles-defs-2.1.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + Map definitions = reader.read(source); + + assertNotNull("Definitions not returned.", definitions); + Definition def = definitions.get("doc.cascaded.test"); + + assertNotNull("Couldn't find doc.role.test tile.", def); + Attribute attribute = def.getLocalAttribute("title"); + assertNotNull("Couldn't Find title local attribute.", attribute); + attribute = def.getCascadedAttribute("title2"); + assertNotNull("Couldn't Find title2 cascaded attribute.", attribute); + attribute = def.getLocalAttribute("items1"); + assertNotNull("Couldn't Find items1 local attribute.", attribute); + attribute = def.getCascadedAttribute("items2"); + assertNotNull("Couldn't Find items2 cascaded attribute.", attribute); + + def = definitions.get("test.nesting.definitions"); + assertNotNull("Couldn't find test.nesting.definitions tile.", def); + assertEquals("/layout.jsp", def.getTemplateAttribute().getValue()); + assertEquals("template", def.getTemplateAttribute().getRenderer()); + attribute = def.getAttribute("body"); + assertNotNull("Couldn't Find body attribute.", attribute); + assertEquals("Attribute not of 'definition' type", "definition", attribute.getRenderer()); + assertNotNull("Attribute value null", attribute.getValue()); + String defName = attribute.getValue().toString(); + def = definitions.get(defName); + assertNotNull("Couldn't find " + defName + " tile.", def); + + def = definitions.get("test.nesting.list.definitions"); + assertNotNull("Couldn't find test.nesting.list.definitions tile.", def); + attribute = def.getAttribute("list"); + assertNotNull("Couldn't Find list attribute.", attribute); + assertTrue("Attribute not of valid type", attribute instanceof ListAttribute); + ListAttribute listAttribute = (ListAttribute) attribute; + List list = listAttribute.getValue(); + assertEquals("The list is not of correct size", 1, list.size()); + attribute = list.get(0); + assertNotNull("Couldn't Find element attribute.", attribute); + assertEquals("Attribute not of 'definition' type", "definition", attribute.getRenderer()); + assertNotNull("Attribute value null", attribute.getValue()); + defName = attribute.getValue().toString(); + def = definitions.get(defName); + assertNotNull("Couldn't find " + defName + " tile.", def); + + defName = "test.inherit.list.base"; + def = definitions.get(defName); + assertNotNull("Couldn't find " + defName + " tile.", def); + defName = "test.inherit.list"; + def = definitions.get(defName); + assertNotNull("Couldn't find " + defName + " tile.", def); + listAttribute = (ListAttribute) def.getAttribute("list"); + assertTrue("This definition does not inherit its list attribute", listAttribute.isInherit()); + defName = "test.noinherit.list"; + def = definitions.get(defName); + listAttribute = (ListAttribute) def.getAttribute("list"); + assertFalse("This definition inherits its list attribute", listAttribute.isInherit()); + + defName = "test.new.attributes"; + def = definitions.get(defName); + assertNotNull("Couldn't find " + defName + " tile.", def); + Attribute templateAttribute = def.getTemplateAttribute(); + assertEquals(templateAttribute.getExpressionObject().getExpression(), "${my.expression}"); + assertEquals("mytype", templateAttribute.getRenderer()); + attribute = def.getAttribute("body"); + assertNotNull("Couldn't Find body attribute.", attribute); + assertEquals("${my.attribute.expression}", attribute.getExpressionObject().getExpression()); + } + + /** + * Tests read with bad input source. + */ + @Test + public void testBadSource() { + try { + reader.read("Bad Input"); + fail("Should've thrown an exception."); + } catch (DefinitionsFactoryException e) { + assertTrue(true); + } catch (Exception e) { + fail("Exception reading configuration." + e); + } + } + + /** + * Tests read with bad XML source. + */ + @Test + public void testBadXml() { + try { + URL configFile = this.getClass().getClassLoader().getResource( + "org/apache/tiles/config/malformed-defs.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + reader.read(source); + fail("Should've thrown an exception."); + } catch (DefinitionsFactoryException e) { + assertTrue(true); + } catch (Exception e) { + fail("Exception reading configuration." + e); + } + } + + /** + * Tests the validating input parameter. + *

+ * This test case enables Digester's validating property then passes in a + * configuration file with invalid XML. + */ + @Test + public void testValidatingParameter() { + // Testing with default (validation ON). + try { + URL configFile = this.getClass().getClassLoader().getResource( + "org/apache/tiles/config/invalid-defs.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + reader.setValidating(true); + reader.read(source); + fail("Should've thrown an exception."); + } catch (DefinitionsFactoryException e) { + assertTrue(true); + } catch (Exception e) { + fail("Exception reading configuration." + e); + } + + // Testing with validation OFF. + try { + setUp(); + URL configFile = this.getClass().getClassLoader().getResource( + "org/apache/tiles/config/invalid-defs.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + reader.read(source); + } catch (DefinitionsFactoryException e) { + fail("Should not have thrown an exception." + e); + } catch (Exception e) { + fail("Exception reading configuration." + e); + } + } + + /** + * Regression test for bug TILES-352. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testRegressionTiles352() throws IOException { + URL configFile = this.getClass().getClassLoader().getResource( + "org/apache/tiles/config/defs_regression_TILES-352.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + Map name2defs = reader.read(source); + source.close(); + Definition root = name2defs.get("root"); + Attribute attribute = root.getAttribute("body"); + Definition child = name2defs.get(attribute.getValue()); + ListAttribute listAttribute = (ListAttribute) child.getAttribute("list"); + List list = listAttribute.getValue(); + assertEquals((list.get(0)).getValue(), "This is a value"); + } + + /** + * Tests {@link DigesterDefinitionsReader#read(Object)}. + */ + @Test + public void testReadNoSource() { + assertNull(reader.read(null)); + } + + /** + * Tests {@link DigesterDefinitionsReader#addDefinition(Definition)}. + */ + @Test(expected = DigesterDefinitionsReaderException.class) + public void testAddDefinitionNoName() { + Definition def = new Definition(); + reader.addDefinition(def); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolverTest.java new file mode 100644 index 0000000000..db9c00f6eb --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolverTest.java @@ -0,0 +1,119 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; +import org.junit.Test; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link AbstractPatternDefinitionResolver}. + */ +public class AbstractPatternDefinitionResolverTest { + + private DefinitionPatternMatcher firstMatcher; + private DefinitionPatternMatcher thirdMatcher; + + private final PatternDefinitionResolver resolver = new AbstractPatternDefinitionResolver() { + @Override + protected Map addDefinitionsAsPatternMatchers(List matchers, Map defsMap) { + if (defsMap.containsKey("first")) { + matchers.add(firstMatcher); + } + if (defsMap.containsKey("third")) { + matchers.add(thirdMatcher); + } + Map retValue = new HashMap<>(defsMap); + retValue.remove("first"); + retValue.remove("third"); + return retValue; + } + }; + + /** + * Test method for + * {@link BasicPatternDefinitionResolver#resolveDefinition(String, Object)}. + */ + @Test + public void testResolveDefinition() { + testResolveDefinitionImpl(); + } + + /** + * Test method for + * {@link BasicPatternDefinitionResolver#clearPatternPaths(Object)}. + */ + @Test + public void testClearPatternPaths() { + testResolveDefinitionImpl(); + resolver.clearPatternPaths(1); + resolver.clearPatternPaths(2); + testResolveDefinitionImpl(); + } + + private void testResolveDefinitionImpl() { + + firstMatcher = createMock(DefinitionPatternMatcher.class); + thirdMatcher = createMock(DefinitionPatternMatcher.class); + + Definition firstDefinition = new Definition("first", null, null); + Definition secondDefinition = new Definition("second", null, null); + Definition thirdDefinition = new Definition("third", null, null); + + Definition firstTransformedDefinition = new Definition("firstTransformed", null, null); + Definition thirdTransformedDefinition = new Definition("thirdTransformed", null, null); + + expect(firstMatcher.createDefinition("firstTransformed")).andReturn(firstTransformedDefinition); + expect(firstMatcher.createDefinition("secondTransformed")).andReturn(null); + expect(firstMatcher.createDefinition("thirdTransformed")).andReturn(null); + expect(thirdMatcher.createDefinition("thirdTransformed")).andReturn(thirdTransformedDefinition).times(2); + expect(thirdMatcher.createDefinition("firstTransformed")).andReturn(null); + expect(thirdMatcher.createDefinition("secondTransformed")).andReturn(null).times(2); + + replay(firstMatcher, thirdMatcher); + + Map localeDefsMap = new LinkedHashMap<>(); + localeDefsMap.put("first", firstDefinition); + localeDefsMap.put("second", secondDefinition); + localeDefsMap.put("third", thirdDefinition); + resolver.storeDefinitionPatterns(localeDefsMap, 1); + localeDefsMap = new LinkedHashMap<>(); + localeDefsMap.put("third", thirdDefinition); + resolver.storeDefinitionPatterns(localeDefsMap, 2); + assertEquals(firstTransformedDefinition, resolver.resolveDefinition("firstTransformed", 1)); + assertNull(resolver.resolveDefinition("secondTransformed", 1)); + assertEquals(thirdTransformedDefinition, resolver.resolveDefinition("thirdTransformed", 1)); + assertNull(resolver.resolveDefinition("firstTransformed", 2)); + assertNull(resolver.resolveDefinition("secondTransformed", 2)); + assertEquals(thirdTransformedDefinition, resolver.resolveDefinition("thirdTransformed", 2)); + verify(firstMatcher, thirdMatcher); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolverTest.java new file mode 100644 index 0000000000..7cd651b982 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolverTest.java @@ -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.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link BasicPatternDefinitionResolver}. + */ +public class BasicPatternDefinitionResolverTest { + + /** + * Test method for + * {@link BasicPatternDefinitionResolver#addDefinitionsAsPatternMatchers(List, Map)}. + */ + @Test + public void testAddDefinitionsAsPatternMatchers() { + DefinitionPatternMatcherFactory factory = createMock(DefinitionPatternMatcherFactory.class); + PatternRecognizer recognizer = createMock(PatternRecognizer.class); + DefinitionPatternMatcher firstMatcher = createMock(DefinitionPatternMatcher.class); + DefinitionPatternMatcher thirdMatcher = createMock(DefinitionPatternMatcher.class); + + expect(recognizer.isPatternRecognized("first")).andReturn(true); + expect(recognizer.isPatternRecognized("second")).andReturn(false); + expect(recognizer.isPatternRecognized("third")).andReturn(true); + + Definition firstDefinition = new Definition("first", null, null); + Definition secondDefinition = new Definition("second", null, null); + Definition thirdDefinition = new Definition("third", null, null); + + expect(factory.createDefinitionPatternMatcher("first", firstDefinition)) + .andReturn(firstMatcher); + expect(factory.createDefinitionPatternMatcher("third", thirdDefinition)) + .andReturn(thirdMatcher); + + replay(factory, recognizer, firstMatcher, thirdMatcher); + BasicPatternDefinitionResolver resolver = new BasicPatternDefinitionResolver<>(factory, recognizer); + Map localeDefsMap = new LinkedHashMap<>(); + localeDefsMap.put("first", firstDefinition); + localeDefsMap.put("second", secondDefinition); + localeDefsMap.put("third", thirdDefinition); + List matchers = new ArrayList<>(); + resolver.addDefinitionsAsPatternMatchers(matchers, localeDefsMap); + assertEquals(2, matchers.size()); + assertEquals(firstMatcher, matchers.get(0)); + assertEquals(thirdMatcher, matchers.get(1)); + verify(factory, recognizer, firstMatcher, thirdMatcher); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PatternUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PatternUtilTest.java new file mode 100644 index 0000000000..8dea7b4af2 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PatternUtilTest.java @@ -0,0 +1,316 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.ListAttribute; +import org.junit.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class PatternUtilTest { + + /** + * The size of the list in the main list attribute. + */ + private static final int LIST_ATTRIBUTE_SIZE = 3; + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholders() { + Map attributes = new HashMap<>(); + attributes.put("attrib1", new Attribute("value{2}")); + attributes.put("attrib2", new Attribute("value{2}{3}")); + attributes.put("attrib3", new Attribute(null, Expression + .createExpression("expr{1}", "EL"), null, null)); + Definition definition = new Definition("definitionName", new Attribute( + "template{1}"), attributes); + definition.setExtends("{2}ext"); + definition.setPreparer("{3}prep"); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", + "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + assertEquals("value2ext", nudef.getExtends()); + assertEquals("value3prep", nudef.getPreparer()); + Attribute attribute = nudef.getTemplateAttribute(); + assertEquals("templatevalue1", attribute.getValue()); + attribute = nudef.getAttribute("attrib1"); + assertEquals("valuevalue2", attribute.getValue()); + attribute = nudef.getAttribute("attrib2"); + assertEquals("valuevalue2value3", attribute.getValue()); + attribute = nudef.getAttribute("attrib3"); + assertEquals("exprvalue1", attribute.getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersNullTemplate() { + Map attributes = new HashMap<>(); + attributes.put("attrib1", new Attribute("value{2}")); + attributes.put("attrib2", new Attribute("value{2}{3}")); + Definition definition = new Definition("definitionName", null, attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", + "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + assertNull(nudef.getTemplateAttribute()); + Attribute attribute = nudef.getAttribute("attrib1"); + assertEquals("valuevalue2", attribute.getValue()); + attribute = nudef.getAttribute("attrib2"); + assertEquals("valuevalue2value3", attribute.getValue()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersCascadedAttributes() { + Definition definition = new Definition("definitionName", new Attribute( + "template{1}"), null); + definition.putAttribute("attrib1", new Attribute("value{2}"), true); + definition.putAttribute("attrib2", new Attribute("value{2}{3}"), true); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", + "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + Attribute attribute = nudef.getTemplateAttribute(); + assertEquals("templatevalue1", attribute.getValue()); + attribute = nudef.getAttribute("attrib1"); + assertEquals("valuevalue2", attribute.getValue()); + attribute = nudef.getAttribute("attrib2"); + assertEquals("valuevalue2value3", attribute.getValue()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersListAttribute() { + Map attributes = new HashMap<>(); + ListAttribute listAttribute = new ListAttribute(); + ListAttribute internalListAttribute = new ListAttribute(); + listAttribute.setInherit(true); + attributes.put("myList", listAttribute); + listAttribute.add(new Attribute("value{2}")); + listAttribute.add(new Attribute("value{2}{3}")); + listAttribute.add(internalListAttribute); + internalListAttribute.add(new Attribute("secondvalue{2}")); + internalListAttribute.add(new Attribute("secondvalue{2}{3}")); + Definition definition = new Definition("definitionName", new Attribute( + "template{1}"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", + "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + Attribute attribute = nudef.getTemplateAttribute(); + assertEquals("templatevalue1", attribute.getValue()); + ListAttribute nuListAttribute = (ListAttribute) nudef.getAttribute("myList"); + assertTrue(nuListAttribute.isInherit()); + List list = nuListAttribute.getValue(); + assertEquals(LIST_ATTRIBUTE_SIZE, list.size()); + attribute = list.get(0); + assertEquals("valuevalue2", attribute.getValue()); + attribute = list.get(1); + assertEquals("valuevalue2value3", attribute.getValue()); + ListAttribute evaluatedListAttribute = (ListAttribute) list.get(2); + assertFalse(evaluatedListAttribute.isInherit()); + list = evaluatedListAttribute.getValue(); + assertEquals(2, list.size()); + attribute = list.get(0); + assertEquals("secondvaluevalue2", attribute.getValue()); + attribute = list.get(1); + assertEquals("secondvaluevalue2value3", attribute.getValue()); + } + + + /** + * Tests {@link PatternUtil#createExtractedMap(Map, Set)}. + */ + @Test + public void testCreateExtractedMap() { + Map map = new HashMap<>(); + map.put(0, "value0"); + map.put(1, "value1"); + map.put(2, "value2"); + Set set = new HashSet<>(); + set.add(1); + set.add(2); + Map extractedMap = PatternUtil.createExtractedMap(map, set); + assertEquals(2, extractedMap.size()); + assertEquals("value1", extractedMap.get(1)); + assertEquals("value2", extractedMap.get(2)); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + * See TILES-502 + */ + @Test + public void testReplacePlaceholdersEL_0() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("some-{1}-${requestScope.someVariable}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "some-value1-${requestScope.someVariable}.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "some-value1-${requestScope.someVariable}.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + * See TILES-574 + */ + @Test + public void testReplacePlaceholdersEL_1() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("some-{1}-${requestScope.someVariable}-other-{2}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "some-value1-${requestScope.someVariable}-other-value2.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "some-value1-${requestScope.someVariable}-other-value2.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + * See TILES-574 + */ + @Test + public void testReplacePlaceholdersEL_2() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("some-${requestScope.someVariable}-other-{1}-${requestScope.someOtherVariable}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "some-${requestScope.someVariable}-other-value1-${requestScope.someOtherVariable}.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "some-${requestScope.someVariable}-other-value1-${requestScope.someOtherVariable}.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersEL_conditional() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("{1}/some-other-{2}-${requestScope.someBoolean ? 'a' : 'b'}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "value1/some-other-value2-${requestScope.someBoolean ? 'a' : 'b'}.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "value1/some-other-value2-${requestScope.someBoolean ? 'a' : 'b'}.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersEL_twice() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("some-${requestScope.firstVariable}-${requestScope.secondVariable}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "some-${requestScope.firstVariable}-${requestScope.secondVariable}.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "some-${requestScope.firstVariable}-${requestScope.secondVariable}.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersEL_options() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("{1}/{options[my_fallback}}/some-other-{2}-${requestScope.someVariable}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "value1/{options[my_fallback}}/some-other-value2-${requestScope.someVariable}.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "value1/{options[my_fallback}}/some-other-value2-${requestScope.someVariable}.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolverTest.java new file mode 100644 index 0000000000..bdeaca258f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolverTest.java @@ -0,0 +1,77 @@ +/* + * 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.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link PrefixedPatternDefinitionResolver}. + */ +public class PrefixedPatternDefinitionResolverTest { + + /** + * Test method for {@link PrefixedPatternDefinitionResolver#addDefinitionsAsPatternMatchers(List, Map)}. + */ + @Test + public void testAddDefinitionsAsPatternMatchers() { + DefinitionPatternMatcherFactory factory1 = createMock(DefinitionPatternMatcherFactory.class); + DefinitionPatternMatcherFactory factory2 = createMock(DefinitionPatternMatcherFactory.class); + DefinitionPatternMatcher matcher1 = createMock(DefinitionPatternMatcher.class); + DefinitionPatternMatcher matcher2 = createMock(DefinitionPatternMatcher.class); + Definition definition1 = new Definition("DF1:definition1", null, null); + Definition definition2 = new Definition("DF2:definition2", null, null); + Definition definition3 = new Definition("noLanguageHere", null, null); + + expect(factory1.createDefinitionPatternMatcher("definition1", definition1)).andReturn(matcher1); + expect(factory2.createDefinitionPatternMatcher("definition2", definition2)).andReturn(matcher2); + + replay(factory1, factory2, matcher1, matcher2); + + PrefixedPatternDefinitionResolver resolver = new PrefixedPatternDefinitionResolver<>(); + resolver.registerDefinitionPatternMatcherFactory("DF1", factory1); + resolver.registerDefinitionPatternMatcherFactory("DF2", factory2); + List matchers = new ArrayList<>(); + Map definitions = new LinkedHashMap<>(); + definitions.put("DF1:definition1", definition1); + definitions.put("DF2:definition2", definition2); + definitions.put("noLanguageHere", definition3); + + resolver.addDefinitionsAsPatternMatchers(matchers, definitions); + + assertEquals(2, matchers.size()); + assertEquals(matcher1, matchers.get(0)); + assertEquals(matcher2, matchers.get(1)); + + verify(factory1, factory2, matcher1, matcher2); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactoryTest.java new file mode 100644 index 0000000000..35e9826cb3 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactoryTest.java @@ -0,0 +1,49 @@ +/* + * 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.apache.tiles.core.definition.pattern.regexp; + +import org.apache.tiles.api.Definition; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link RegexpDefinitionPatternMatcherFactory}. + */ +public class RegexpDefinitionPatternMatcherFactoryTest { + + /** + * The object to test. + */ + private RegexpDefinitionPatternMatcherFactory factory; + + /** + * Sets up the object to test. + */ + @Before + public void setUp() { + factory = new RegexpDefinitionPatternMatcherFactory(); + } + + @Test + public void testCreateDefinitionPatternMatcher() { + assertTrue(factory.createDefinitionPatternMatcher("myPattern", new Definition()) instanceof RegexpDefinitionPatternMatcher); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherTest.java new file mode 100644 index 0000000000..291918fc21 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherTest.java @@ -0,0 +1,47 @@ +/* + * 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.apache.tiles.core.definition.pattern.regexp; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Tests {@link RegexpDefinitionPatternMatcher}. + */ +public class RegexpDefinitionPatternMatcherTest { + + @Test + public void testResolveDefinition() { + Definition def = new Definition(); + def.setName("testDef(.*)\\.message(.*)"); + def.setTemplateAttribute(Attribute.createTemplateAttribute("/test{1}.jsp")); + def.putAttribute("body", new Attribute("message{2}")); + DefinitionPatternMatcher patternMatcher = new RegexpDefinitionPatternMatcher("testDef(.*)\\.message(.*)", def); + Definition result = patternMatcher.createDefinition("testDefOne.messageTwo"); + assertNotNull(result); + assertEquals("testDefOne.messageTwo", result.getName()); + assertEquals("/testOne.jsp", result.getTemplateAttribute().getValue()); + assertEquals("messageTwo", result.getAttribute("body").getValue()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactoryTest.java new file mode 100644 index 0000000000..dc98f2033d --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactoryTest.java @@ -0,0 +1,61 @@ +/* + * 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.apache.tiles.core.definition.pattern.wildcard; + +import org.apache.tiles.api.Definition; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link WildcardDefinitionPatternMatcherFactory}. + */ +public class WildcardDefinitionPatternMatcherFactoryTest { + + /** + * The object to test. + */ + private WildcardDefinitionPatternMatcherFactory factory; + + /** + * Sets up the object to test. + */ + @Before + public void setUp() { + factory = new WildcardDefinitionPatternMatcherFactory(); + } + + @Test + public void testCreateDefinitionPatternMatcher() { + assertTrue(factory.createDefinitionPatternMatcher("myPattern", new Definition()) instanceof WildcardDefinitionPatternMatcher); + } + + /** + * Test method for {@link WildcardDefinitionPatternMatcherFactory#isPatternRecognized(String)}. + */ + @Test + public void testIsPatternRecognized() { + assertTrue(factory.isPatternRecognized("my*pattern")); + assertFalse(factory.isPatternRecognized("mypattern")); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherTest.java new file mode 100644 index 0000000000..90eea7eb6c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherTest.java @@ -0,0 +1,53 @@ +/* + * 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.apache.tiles.core.definition.pattern.wildcard; + + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.apache.tiles.core.util.WildcardHelper; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Tests {@link WildcardDefinitionPatternMatcher}. + */ +public class WildcardDefinitionPatternMatcherTest { + + /** + * Test method for {@link WildcardDefinitionPatternMatcher#createDefinition(String)}. + */ + @Test + public void testResolveDefinition() { + Definition def = new Definition(); + def.setName("testDef*.message*"); + def.setTemplateAttribute(Attribute.createTemplateAttribute("/test{1}.jsp")); + def.putAttribute("body", new Attribute("message{2}")); + DefinitionPatternMatcher patternMatcher = new WildcardDefinitionPatternMatcher("testDef*.message*", def, new WildcardHelper()); + Definition result = patternMatcher.createDefinition("testDefOne.messageTwo"); + assertNotNull(result); + assertEquals("testDefOne.messageTwo", result.getName()); + assertEquals("/testOne.jsp", result.getTemplateAttribute().getValue()); + assertEquals("messageTwo", result.getAttribute("body").getValue()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactoryTest.java new file mode 100644 index 0000000000..ccba2299b8 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactoryTest.java @@ -0,0 +1,85 @@ +/* + * 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.apache.tiles.core.evaluator; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.junit.Test; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertSame; + +/** + * Tests {@link BasicAttributeEvaluatorFactory}. + */ +public class BasicAttributeEvaluatorFactoryTest { + + /** + * Test method for {@link BasicAttributeEvaluatorFactory#getAttributeEvaluator(String)}. + */ + @Test + public void testGetAttributeEvaluatorString() { + AttributeEvaluator defaultEvaluator = createMock(AttributeEvaluator.class); + AttributeEvaluator evaluator1 = createMock(AttributeEvaluator.class); + AttributeEvaluator evaluator2 = createMock(AttributeEvaluator.class); + replay(defaultEvaluator, evaluator1, evaluator2); + BasicAttributeEvaluatorFactory factory = new BasicAttributeEvaluatorFactory(defaultEvaluator); + factory.registerAttributeEvaluator("LANG1", evaluator1); + factory.registerAttributeEvaluator("LANG2", evaluator2); + assertSame(evaluator1, factory.getAttributeEvaluator("LANG1")); + assertSame(evaluator2, factory.getAttributeEvaluator("LANG2")); + assertSame(defaultEvaluator, factory.getAttributeEvaluator("LANG3")); + verify(defaultEvaluator, evaluator1, evaluator2); + } + + /** + * Test method for {@link BasicAttributeEvaluatorFactory#getAttributeEvaluator(Attribute)}. + */ + @Test + public void testGetAttributeEvaluatorAttribute() { + AttributeEvaluator defaultEvaluator = createMock(AttributeEvaluator.class); + AttributeEvaluator evaluator1 = createMock(AttributeEvaluator.class); + AttributeEvaluator evaluator2 = createMock(AttributeEvaluator.class); + replay(defaultEvaluator, evaluator1, evaluator2); + BasicAttributeEvaluatorFactory factory = new BasicAttributeEvaluatorFactory(defaultEvaluator); + factory.registerAttributeEvaluator("LANG1", evaluator1); + factory.registerAttributeEvaluator("LANG2", evaluator2); + assertSame(evaluator1, factory + .getAttributeEvaluator(createExpressionAttribute("LANG1"))); + assertSame(evaluator2, factory + .getAttributeEvaluator(createExpressionAttribute("LANG2"))); + assertSame(defaultEvaluator, factory + .getAttributeEvaluator(createExpressionAttribute("LANG3"))); + verify(defaultEvaluator, evaluator1, evaluator2); + } + + /** + * Creates a sample attribute with an expression. + * + * @param language The expression language. + * @return The attribute. + */ + private Attribute createExpressionAttribute(String language) { + return new Attribute(null, Expression.createExpression("myExpression", language), null, "string"); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/EvaluatorExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/EvaluatorExceptionTest.java new file mode 100644 index 0000000000..d3fc072152 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/EvaluatorExceptionTest.java @@ -0,0 +1,53 @@ +/* + * 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.apache.tiles.core.evaluator; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link EvaluationException}. + */ +public class EvaluatorExceptionTest { + + /** + * Test method for {@link EvaluationException#EvaluationException(Throwable)}. + */ + @Test + public void testEvaluationExceptionThrowable() { + Throwable cause = new Throwable(); + EvaluationException exception = new EvaluationException(cause); + assertEquals(cause.toString(), exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + /** + * Test method for {@link EvaluationException#EvaluationException(String, Throwable)}. + */ + @Test + public void testEvaluationExceptionStringThrowable() { + Throwable cause = new Throwable(); + EvaluationException exception = new EvaluationException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluatorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluatorTest.java new file mode 100644 index 0000000000..1af84a7d02 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluatorTest.java @@ -0,0 +1,84 @@ +/* + * 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.apache.tiles.core.evaluator.impl; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link DirectAttributeEvaluator}. + */ +public class DirectAttributeEvaluatorTest { + + /** + * The evaluator to test. + */ + private DirectAttributeEvaluator evaluator; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + evaluator = new DirectAttributeEvaluator(); + } + + /** + * Tests + * {@link DirectAttributeEvaluator#evaluate(Attribute, org.apache.tiles.request.Request)}. + */ + @Test + public void testEvaluate() { + String expression = "This is an expression"; + Attribute attribute = new Attribute(null, Expression.createExpression(expression, null), null, null); + Object result = evaluator.evaluate(attribute, null); + assertEquals("The expression has not been evaluated correctly", result, expression); + expression = "${attributeName}"; + attribute.setExpressionObject(new Expression(expression)); + result = evaluator.evaluate(attribute, null); + assertEquals("The expression has not been evaluated correctly", result, expression); + } + + /** + * Tests + * {@link DirectAttributeEvaluator#evaluate(Attribute, org.apache.tiles.request.Request)}. + */ + @Test(expected = IllegalArgumentException.class) + public void testEvaluateNullAttribute() { + evaluator.evaluate((Attribute) null, null); + } + + /** + * Tests + * {@link DirectAttributeEvaluator#evaluate(String, org.apache.tiles.request.Request)}. + */ + @Test + public void testEvaluateString() { + String expression = "This is an expression"; + Object result = evaluator.evaluate(expression, null); + assertEquals("The expression has not been evaluated correctly", result, expression); + expression = "${attributeName}"; + result = evaluator.evaluate(expression, null); + assertEquals("The expression has not been evaluated correctly", result, expression); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicPreparerFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicPreparerFactoryTest.java new file mode 100644 index 0000000000..0e5ffed61c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicPreparerFactoryTest.java @@ -0,0 +1,72 @@ +/* + * 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.apache.tiles.core.factory; + +import junit.framework.TestCase; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.core.prepare.factory.BasicPreparerFactory; +import org.apache.tiles.request.Request; + +/** + * Tests the basic preparer factory. + */ +public class BasicPreparerFactoryTest extends TestCase { + + /** + * The preparer factory. + */ + private BasicPreparerFactory factory; + + /** + * {@inheritDoc} + */ + @Override + public void setUp() { + factory = new BasicPreparerFactory(); + } + + /** + * Tests getting a preparer. + */ + public void testGetPreparer() { + String name = MockViewPreparer.class.getName(); + ViewPreparer p = factory.getPreparer(name, null); + assertNotNull(p); + assertTrue(p instanceof MockViewPreparer); + + name = "org.doesnotexist.Class"; + p = factory.getPreparer(name, null); + assertNull(p); + } + + /** + * Mock view preparer. + * + * @version $Rev$ $Date$ + */ + public static class MockViewPreparer implements ViewPreparer { + + /** + * {@inheritDoc} + */ + public void execute(Request tilesContext, AttributeContext attributeContext) { + } + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicTilesContainerFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicTilesContainerFactoryTest.java new file mode 100644 index 0000000000..788584650f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicTilesContainerFactoryTest.java @@ -0,0 +1,252 @@ +/* + * 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.apache.tiles.core.factory; + +import junit.framework.TestCase; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.UnresolvingLocaleDefinitionsFactory; +import org.apache.tiles.core.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.impl.DirectAttributeEvaluator; +import org.apache.tiles.core.impl.BasicTilesContainer; +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.core.locale.impl.DefaultLocaleResolver; +import org.apache.tiles.core.prepare.factory.BasicPreparerFactory; +import org.apache.tiles.core.prepare.factory.PreparerFactory; +import org.apache.tiles.core.renderer.DefinitionRenderer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.locale.URLApplicationResource; +import org.apache.tiles.request.render.BasicRendererFactory; +import org.apache.tiles.request.render.ChainedDelegateRenderer; +import org.apache.tiles.request.render.DispatchRenderer; +import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.render.RendererFactory; +import org.apache.tiles.request.render.StringRenderer; + +import java.util.List; +import java.util.Objects; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link BasicTilesContainerFactory}. + */ +public class BasicTilesContainerFactoryTest extends TestCase { + + /** + * The factory to test. + */ + private BasicTilesContainerFactory factory; + + /** + * The context object. + */ + private ApplicationContext applicationContext; + + /** + * The resource to load. + */ + private ApplicationResource resource; + + /** {@inheritDoc} */ + @Override + protected void setUp() throws Exception { + applicationContext = createMock(ApplicationContext.class); + resource = new URLApplicationResource( + "/org/apache/tiles/core/config/tiles-defs.xml", + Objects.requireNonNull(getClass().getResource("/org/apache/tiles/core/config/tiles-defs.xml")) + ); + expect(applicationContext.getResource("/WEB-INF/tiles.xml")).andReturn(resource); + replay(applicationContext); + factory = new BasicTilesContainerFactory(); + } + + /** + * Tests {@link BasicTilesContainerFactory#createContainer(ApplicationContext)}. + */ + public void testCreateContainer() { + TilesContainer container = factory.createContainer(applicationContext); + assertTrue("The class of the container is not correct", container instanceof BasicTilesContainer); + } + + /** + * Tests {@link BasicTilesContainerFactory#createDefinitionsFactory( + * ApplicationContext, LocaleResolver)}. + */ + public void testCreateDefinitionsFactory() { + LocaleResolver resolver = factory.createLocaleResolver(applicationContext); + DefinitionsFactory defsFactory = factory.createDefinitionsFactory(applicationContext, resolver); + assertTrue("The class of the definitions factory is not correct", + defsFactory instanceof UnresolvingLocaleDefinitionsFactory); + } + + /** + * Tests {@link BasicTilesContainerFactory#createLocaleResolver( + * ApplicationContext)}. + */ + public void testCreateLocaleResolver() { + LocaleResolver localeResolver = factory.createLocaleResolver(applicationContext); + assertTrue("The class of the locale resolver is not correct", localeResolver instanceof DefaultLocaleResolver); + } + + /** + * Tests {@link BasicTilesContainerFactory#createDefinitionsReader( + * ApplicationContext)}. + */ + public void testCreateDefinitionsReader() { + DefinitionsReader reader = factory.createDefinitionsReader(applicationContext); + assertTrue("The class of the reader is not correct", reader instanceof DigesterDefinitionsReader); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#getSources(ApplicationContext)}. + */ + public void testGetSources() { + List resources = factory.getSources(applicationContext); + assertEquals("The urls list is not one-sized", 1, resources.size()); + assertEquals("The URL is not correct", resource, resources.get(0)); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createAttributeEvaluatorFactory( + * ApplicationContext, LocaleResolver)}. + */ + public void testCreateAttributeEvaluatorFactory() { + LocaleResolver resolver = factory.createLocaleResolver(applicationContext); + AttributeEvaluatorFactory attributeEvaluatorFactory = factory.createAttributeEvaluatorFactory( + applicationContext, resolver); + assertTrue("The class of the evaluator is not correct", + attributeEvaluatorFactory.getAttributeEvaluator((String) null) instanceof DirectAttributeEvaluator); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createPreparerFactory(ApplicationContext)}. + */ + public void testCreatePreparerFactory() { + PreparerFactory preparerFactory = factory.createPreparerFactory(applicationContext); + assertTrue("The class of the preparer factory is not correct", preparerFactory instanceof BasicPreparerFactory); + } + + /** + * Tests {@link BasicTilesContainerFactory#createRendererFactory( + * ApplicationContext, TilesContainer, AttributeEvaluatorFactory)}. + */ + public void testCreateRendererFactory() { + TilesContainer container = factory.createContainer(applicationContext); + LocaleResolver resolver = factory.createLocaleResolver(applicationContext); + AttributeEvaluatorFactory attributeEvaluatorFactory = factory.createAttributeEvaluatorFactory( + applicationContext, resolver); + RendererFactory rendererFactory = factory.createRendererFactory(applicationContext, container, + attributeEvaluatorFactory); + assertTrue("The class of the renderer factory is not correct", rendererFactory instanceof BasicRendererFactory); + Renderer renderer = rendererFactory.getRenderer("string"); + assertNotNull("The string renderer is null", renderer); + assertTrue("The string renderer class is not correct", renderer instanceof StringRenderer); + renderer = rendererFactory.getRenderer("template"); + assertNotNull("The template renderer is null", renderer); + assertTrue("The template renderer class is not correct", renderer instanceof DispatchRenderer); + renderer = rendererFactory.getRenderer("definition"); + assertNotNull("The definition renderer is null", renderer); + assertTrue("The definition renderer class is not correct", renderer instanceof DefinitionRenderer); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createDefaultAttributeRenderer(BasicRendererFactory, + * ApplicationContext, TilesContainer, AttributeEvaluatorFactory)}. + */ + public void testCreateDefaultAttributeRenderer() { + TilesContainer container = createMock(TilesContainer.class); + AttributeEvaluatorFactory attributeEvaluatorFactory = createMock(AttributeEvaluatorFactory.class); + BasicRendererFactory rendererFactory = createMock(BasicRendererFactory.class); + Renderer stringRenderer = createMock(Renderer.class); + Renderer templateRenderer = createMock(Renderer.class); + Renderer definitionRenderer = createMock(Renderer.class); + + expect(rendererFactory.getRenderer("string")).andReturn(stringRenderer); + expect(rendererFactory.getRenderer("template")).andReturn(templateRenderer); + expect(rendererFactory.getRenderer("definition")).andReturn(definitionRenderer); + + replay(container, attributeEvaluatorFactory, rendererFactory); + Renderer renderer = factory.createDefaultAttributeRenderer(rendererFactory, applicationContext, container, + attributeEvaluatorFactory); + assertTrue("The default renderer class is not correct", renderer instanceof ChainedDelegateRenderer); + verify(container, attributeEvaluatorFactory, rendererFactory); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createStringAttributeRenderer(BasicRendererFactory, + * ApplicationContext, TilesContainer, AttributeEvaluatorFactory)}. + */ + public void testCreateStringAttributeRenderer() { + TilesContainer container = createMock(TilesContainer.class); + AttributeEvaluatorFactory attributeEvaluatorFactory = createMock(AttributeEvaluatorFactory.class); + BasicRendererFactory rendererFactory = createMock(BasicRendererFactory.class); + + replay(container, attributeEvaluatorFactory, rendererFactory); + Renderer renderer = factory.createStringAttributeRenderer(rendererFactory, applicationContext, container, + attributeEvaluatorFactory); + assertTrue("The renderer class is not correct", renderer instanceof StringRenderer); + verify(container, attributeEvaluatorFactory, rendererFactory); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createTemplateAttributeRenderer(BasicRendererFactory, + * ApplicationContext, TilesContainer, AttributeEvaluatorFactory)}. + */ + public void testCreateTemplateAttributeRenderer() { + TilesContainer container = createMock(TilesContainer.class); + AttributeEvaluatorFactory attributeEvaluatorFactory = createMock(AttributeEvaluatorFactory.class); + BasicRendererFactory rendererFactory = createMock(BasicRendererFactory.class); + + replay(container, attributeEvaluatorFactory, rendererFactory); + Renderer renderer = factory.createTemplateAttributeRenderer(rendererFactory, applicationContext, container, + attributeEvaluatorFactory); + assertTrue("The renderer class is not correct", renderer instanceof DispatchRenderer); + verify(container, attributeEvaluatorFactory, rendererFactory); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createDefinitionAttributeRenderer(BasicRendererFactory, + * ApplicationContext, TilesContainer, AttributeEvaluatorFactory)}. + */ + public void testCreateDefinitionAttributeRenderer() { + TilesContainer container = createMock(TilesContainer.class); + AttributeEvaluatorFactory attributeEvaluatorFactory = createMock(AttributeEvaluatorFactory.class); + BasicRendererFactory rendererFactory = createMock(BasicRendererFactory.class); + + replay(container, attributeEvaluatorFactory, rendererFactory); + Renderer renderer = factory.createDefinitionAttributeRenderer(rendererFactory, applicationContext, container, + attributeEvaluatorFactory); + assertTrue("The renderer class is not correct", renderer instanceof DefinitionRenderer); + verify(container, attributeEvaluatorFactory, rendererFactory); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/factory/NoSuchPreparerExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/NoSuchPreparerExceptionTest.java new file mode 100644 index 0000000000..2255f1667a --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/NoSuchPreparerExceptionTest.java @@ -0,0 +1,43 @@ +/* + * 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.apache.tiles.core.factory; + +import org.apache.tiles.core.prepare.factory.NoSuchPreparerException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link NoSuchPreparerException}. + */ +public class NoSuchPreparerExceptionTest { + + /** + * Test method for {@link NoSuchPreparerException#NoSuchPreparerException(String)}. + */ + @Test + public void testNoSuchPreparerExceptionString() { + NoSuchPreparerException exception = new NoSuchPreparerException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/factory/TilesContainerFactoryExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/TilesContainerFactoryExceptionTest.java new file mode 100644 index 0000000000..bc1aaec3dc --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/TilesContainerFactoryExceptionTest.java @@ -0,0 +1,42 @@ +/* + * 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.apache.tiles.core.factory; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link TilesContainerFactoryException}. + */ +public class TilesContainerFactoryExceptionTest { + + /** + * Test method for {@link TilesContainerFactoryException#TilesContainerFactoryException(String, Throwable)}. + */ + @Test + public void testTilesContainerFactoryExceptionStringThrowable() { + Throwable cause = new Throwable(); + TilesContainerFactoryException exception = new TilesContainerFactoryException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerTest.java new file mode 100644 index 0000000000..2e7328481e --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerTest.java @@ -0,0 +1,126 @@ +/* + * 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.apache.tiles.core.impl; + +import junit.framework.TestCase; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.core.factory.AbstractTilesContainerFactory; +import org.apache.tiles.core.factory.BasicTilesContainerFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.locale.URLApplicationResource; +import org.apache.tiles.request.render.CannotRenderException; +import org.easymock.EasyMock; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Objects; + +public class BasicTilesContainerTest extends TestCase { + + /** + * A sample integer value to check object rendering. + */ + private static final int SAMPLE_INT = 15; + + /** + * The container. + */ + private BasicTilesContainer container; + + @Override + public void setUp() { + ApplicationContext context = EasyMock.createMock(ApplicationContext.class); + URLApplicationResource resource = new URLApplicationResource( + "/WEB-INF/tiles.xml", + Objects.requireNonNull(getClass().getResource("/org/apache/tiles/core/factory/test-defs.xml")) + ); + + EasyMock.expect(context.getResource("/WEB-INF/tiles.xml")).andReturn(resource); + EasyMock.replay(context); + AbstractTilesContainerFactory factory = new BasicTilesContainerFactory(); + container = (BasicTilesContainer) factory.createContainer(context); + } + + /** + * Tests basic Tiles container initialization. + */ + public void testInitialization() { + assertNotNull(container); + } + + /** + * Tests that attributes of type "object" won't be rendered. + * + * @throws IOException If something goes wrong, but it's not a Tiles + * exception. + */ + public void testObjectAttribute() throws IOException { + Attribute attribute = new Attribute(); + Request request = EasyMock.createMock(Request.class); + EasyMock.replay(request); + boolean exceptionFound = false; + + attribute.setValue(SAMPLE_INT); + try { + container.render(attribute, request); + } catch (CannotRenderException e) { + exceptionFound = true; + } + + assertTrue("An attribute of 'object' type cannot be rendered", exceptionFound); + } + + /** + * Tests is attributes are rendered correctly according to users roles. + * + * @throws IOException If a problem arises during rendering or writing in the writer. + */ + public void testAttributeCredentials() throws IOException { + Request request = EasyMock.createMock(Request.class); + EasyMock.expect(request.isUserInRole("myrole")).andReturn(Boolean.TRUE); + StringWriter writer = new StringWriter(); + EasyMock.expect(request.getWriter()).andReturn(writer); + EasyMock.replay(request); + Attribute attribute = new Attribute("This is the value", "myrole"); + attribute.setRenderer("string"); + container.render(attribute, request); + writer.close(); + assertEquals("The attribute should have been rendered", "This is the value", writer.toString()); + EasyMock.reset(request); + request = EasyMock.createMock(Request.class); + EasyMock.expect(request.isUserInRole("myrole")).andReturn(Boolean.FALSE); + EasyMock.replay(request); + writer = new StringWriter(); + container.render(attribute, request); + writer.close(); + assertNotSame("The attribute should have not been rendered", "This is the value", writer.toString()); + } + + /** + * Tests {@link BasicTilesContainer#evaluate(Attribute, Request)}. + */ + public void testEvaluate() { + Request request = EasyMock.createMock(Request.class); + EasyMock.replay(request); + Attribute attribute = new Attribute("This is the value"); + Object value = container.evaluate(attribute, request); + assertEquals("The attribute has not been evaluated correctly", "This is the value", value); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerUnitTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerUnitTest.java new file mode 100644 index 0000000000..7f4c9d0c40 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerUnitTest.java @@ -0,0 +1,836 @@ +/* + * 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.apache.tiles.core.impl; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.BasicAttributeContext; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.core.evaluator.AttributeEvaluator; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.prepare.factory.NoSuchPreparerException; +import org.apache.tiles.core.prepare.factory.PreparerFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.CannotRenderException; +import org.apache.tiles.request.render.NoSuchRendererException; +import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.render.RendererFactory; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Deque; +import java.util.LinkedList; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link BasicTilesContainer}. + */ +public class BasicTilesContainerUnitTest { + + /** + * Name used to store attribute context stack. + */ + private static final String ATTRIBUTE_CONTEXT_STACK = + "org.apache.tiles.AttributeContext.STACK"; + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * The definitions factory. + */ + private DefinitionsFactory definitionsFactory; + + /** + * The preparer factory. + */ + private PreparerFactory preparerFactory; + + /** + * The renderer factory. + */ + private RendererFactory rendererFactory; + + /** + * The evaluator factory. + */ + private AttributeEvaluatorFactory attributeEvaluatorFactory; + + /** + * The container to test. + */ + private BasicTilesContainer container; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + applicationContext = createMock(ApplicationContext.class); + definitionsFactory = createMock(DefinitionsFactory.class); + preparerFactory = createMock(PreparerFactory.class); + rendererFactory = createMock(RendererFactory.class); + attributeEvaluatorFactory = createMock(AttributeEvaluatorFactory.class); + container = new BasicTilesContainer(); + container.setApplicationContext(applicationContext); + container.setAttributeEvaluatorFactory(attributeEvaluatorFactory); + container.setDefinitionsFactory(definitionsFactory); + container.setPreparerFactory(preparerFactory); + container.setRendererFactory(rendererFactory); + } + + /** + * Test method for {@link BasicTilesContainer#startContext(Request)}. + */ + @Test + public void testStartContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + expect(attributeContext.getCascadedAttributeNames()).andReturn(null); + deque.push(isA(BasicAttributeContext.class)); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + assertTrue(container.startContext(request) instanceof BasicAttributeContext); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#endContext(Request)}. + */ + @Test + public void testEndContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.pop()).andReturn(attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + container.endContext(request); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#renderContext(Request)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testRenderContext() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + Attribute templateAttribute = createMock(Attribute.class); + Renderer renderer = createMock(Renderer.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + expect(attributeContext.getPreparer()).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(rendererFactory.getRenderer("renderer")).andReturn(renderer); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/mytemplate.jsp"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + renderer.render("/mytemplate.jsp", request); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, templateAttribute, renderer); + container.renderContext(request); + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, templateAttribute, renderer); + } + + /** + * Test method for {@link BasicTilesContainer#getApplicationContext()}. + */ + @Test + public void testGetApplicationContext() { + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory); + assertEquals(applicationContext, container.getApplicationContext()); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory); + } + + /** + * Test method for {@link BasicTilesContainer#getAttributeContext(Request)}. + */ + @Test + public void testGetAttributeContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + assertEquals(attributeContext, container.getAttributeContext(request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#getAttributeContext(Request)}. + */ + @Test + public void testGetAttributeContextNew() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope).times(2); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque).times(2); + expect(deque.isEmpty()).andReturn(true); + deque.push(isA(BasicAttributeContext.class)); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + assertTrue(container.getAttributeContext(request) instanceof BasicAttributeContext); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#prepare(String, Request)}. + */ + @Test + public void testPrepare() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + + expect(preparerFactory.getPreparer("preparer", request)).andReturn(preparer); + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + preparer.execute(request, attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer); + container.prepare("preparer", request); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer); + } + + /** + * Test method for {@link BasicTilesContainer#prepare(String, Request)}. + */ + @Test(expected = NoSuchPreparerException.class) + public void testPrepareException() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(preparerFactory.getPreparer("preparer", request)).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + try { + container.prepare("preparer", request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, + request, requestScope, deque, attributeContext); + } + } + + @Test + public void testRenderStringRequest() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + Renderer renderer = createMock(Renderer.class); + Definition definition = createMock(Definition.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + + expect(definitionsFactory.getDefinition("definition", request)).andReturn(definition); + expect(request.getContext("request")).andReturn(requestScope).times(3); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque).times(3); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + expect(attributeContext.getPreparer()).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(attributeContext.getLocalAttributeNames()).andReturn(null); + expect(attributeContext.getCascadedAttributeNames()).andReturn(null); + expect(definition.getTemplateAttribute()).andReturn(templateAttribute); + expect(rendererFactory.getRenderer("template")).andReturn(renderer); + deque.push(isA(BasicAttributeContext.class)); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/my/template.jsp"); + renderer.render("/my/template.jsp", request); + expect(deque.pop()).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, renderer, definition); + container.render("definition", request); + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, renderer, definition); + } + + @Test(expected = NoSuchDefinitionException.class) + public void testRenderStringRequestException() { + Request request = createMock(Request.class); + + expect(definitionsFactory.getDefinition("definition", request)).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + try { + container.render("definition", request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory); + } + } + + @Test + public void testRenderAttributeRequest() throws IOException { + Request request = createMock(Request.class); + Attribute templateAttribute = createMock(Attribute.class); + Renderer renderer = createMock(Renderer.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(rendererFactory.getRenderer("renderer")).andReturn(renderer); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/mytemplate.jsp"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + renderer.render("/mytemplate.jsp", request); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute, renderer); + container.render(templateAttribute, request); + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute, renderer); + } + + @Test(expected = CannotRenderException.class) + public void testRenderAttributeRequestException1() throws IOException { + Request request = createMock(Request.class); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + try { + container.render((Attribute) null, request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, + request); + } + } + + @Test(expected = NoSuchRendererException.class) + public void testRenderAttributeRequestException2() throws IOException { + Request request = createMock(Request.class); + Attribute templateAttribute = createMock(Attribute.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + expect(rendererFactory.getRenderer("renderer")).andThrow(new NoSuchRendererException("Boom!")); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute); + try { + container.render(templateAttribute, request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, + request, templateAttribute); + } + } + + @Test(expected = CannotRenderException.class) + public void testRenderAttributeRequestException3() throws IOException { + Request request = createMock(Request.class); + Attribute templateAttribute = createMock(Attribute.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + Renderer renderer = createMock(Renderer.class); + + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + expect(rendererFactory.getRenderer("renderer")).andReturn(renderer); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn(1); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute); + try { + container.render(templateAttribute, request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, + request, templateAttribute); + } + } + + @Test(expected = NoSuchRendererException.class) + public void testRenderAttributeRequestException() throws IOException { + Request request = createMock(Request.class); + Attribute templateAttribute = createMock(Attribute.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + expect(rendererFactory.getRenderer("renderer")).andThrow(new NoSuchRendererException("Boom!")); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute); + try { + container.render(templateAttribute, request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, + request, templateAttribute); + } + } + + @Test + public void testEvaluate() { + Request request = createMock(Request.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + Attribute templateAttribute = createMock(Attribute.class); + + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn(1); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute, evaluator); + assertEquals(1, container.evaluate(templateAttribute, request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute, evaluator); + } + + /** + * Test method for {@link BasicTilesContainer#isValidDefinition(String, Request)}. + */ + @Test + public void testIsValidDefinition() { + Request request = createMock(Request.class); + Definition definition = createMock(Definition.class); + + expect(definitionsFactory.getDefinition("definition", request)).andReturn(definition); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, definition); + assertTrue(container.isValidDefinition("definition", request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, definition); + } + + /** + * Test method for {@link BasicTilesContainer#isValidDefinition(String, Request)}. + */ + @Test + public void testIsValidDefinitionNull() { + Request request = createMock(Request.class); + + expect(definitionsFactory.getDefinition("definition", request)).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + assertFalse(container.isValidDefinition("definition", request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + } + + /** + * Test method for {@link BasicTilesContainer#isValidDefinition(String, Request)}. + */ + @Test + public void testIsValidDefinitionException() { + Request request = createMock(Request.class); + + expect(definitionsFactory.getDefinition("definition", request)) + .andThrow(new NoSuchDefinitionException("Boom!")); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + assertFalse(container.isValidDefinition("definition", request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + } + + /** + * Test method for {@link BasicTilesContainer#getDefinition(String, Request)}. + */ + @Test + public void testGetDefinition() { + Request request = createMock(Request.class); + Definition definition = createMock(Definition.class); + + expect(definitionsFactory.getDefinition("definition", request)).andReturn(definition); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, definition); + assertEquals(definition, container.getDefinition("definition", request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, definition); + } + + /** + * Test method for {@link BasicTilesContainer#getContextStack(Request)}. + */ + @Test + public void testGetContextStack() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque); + assertEquals(deque, container.getContextStack(request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque); + } + + /** + * Test method for {@link BasicTilesContainer#getContextStack(Request)}. + */ + @Test + public void testGetContextStackNew() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(null); + expect(requestScope.put(eq(ATTRIBUTE_CONTEXT_STACK), isA(LinkedList.class))).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope); + assertTrue(container.getContextStack(request) instanceof LinkedList); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope); + } + + @Test + public void testPushContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + deque.push(attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + container.pushContext(attributeContext, request); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#popContext(Request)}. + */ + @Test + public void testPopContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.pop()).andReturn(attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + assertEquals(attributeContext, container.popContext(request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#getContext(Request)}. + */ + @Test + public void testGetContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + assertEquals(attributeContext, container.getContext(request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#getContext(Request)}. + */ + @Test + public void testGetContextNull() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(true); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque); + assertNull(container.getContext(request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque); + } + + @Test + public void testRenderRequestDefinition() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + Renderer renderer = createMock(Renderer.class); + Definition definition = createMock(Definition.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + + expect(request.getContext("request")).andReturn(requestScope).times(3); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque).times(3); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + expect(attributeContext.getPreparer()).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(attributeContext.getLocalAttributeNames()).andReturn(null); + expect(attributeContext.getCascadedAttributeNames()).andReturn(null); + expect(definition.getTemplateAttribute()).andReturn(templateAttribute); + expect(rendererFactory.getRenderer("template")).andReturn(renderer); + deque.push(isA(BasicAttributeContext.class)); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/my/template.jsp"); + renderer.render("/my/template.jsp", request); + expect(deque.pop()).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, renderer, definition); + container.render(definition, request); + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, renderer, definition); + } + + @Test(expected = CannotRenderException.class) + public void testRenderRequestDefinitionException() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + Renderer renderer = createMock(Renderer.class); + Definition definition = createMock(Definition.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + + expect(request.getContext("request")).andReturn(requestScope).times(3); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque).times(3); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + expect(attributeContext.getPreparer()).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(attributeContext.getLocalAttributeNames()).andReturn(null); + expect(attributeContext.getCascadedAttributeNames()).andReturn(null); + expect(definition.getTemplateAttribute()).andReturn(templateAttribute); + expect(rendererFactory.getRenderer("template")).andReturn(renderer); + deque.push(isA(BasicAttributeContext.class)); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/mytemplate.jsp"); + renderer.render("/mytemplate.jsp", request); + expectLastCall().andThrow(new IOException()); + expect(deque.pop()).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, renderer, definition); + try { + container.render(definition, request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, + request, requestScope, deque, attributeContext, preparer, + renderer, definition); + } + } + + @Test + public void testRenderRequestAttributeContext() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + Attribute templateAttribute = createMock(Attribute.class); + Renderer renderer = createMock(Renderer.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(attributeContext.getPreparer()).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(rendererFactory.getRenderer("renderer")).andReturn(renderer); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/mytemplate.jsp"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + renderer.render("/mytemplate.jsp", request); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, templateAttribute, renderer); + container.render(request, attributeContext); + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, templateAttribute, renderer); + } + + @Test(expected = CannotRenderException.class) + public void testRenderRequestAttributeContextException() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute templateAttribute = createMock(Attribute.class); + Renderer renderer = createMock(Renderer.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(attributeContext.getPreparer()).andReturn("preparer").times(2); + expect(preparerFactory.getPreparer("preparer", request)).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(rendererFactory.getRenderer("renderer")).andReturn(renderer); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/mytemplate.jsp"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + renderer.render("/mytemplate.jsp", request); + expectLastCall().andThrow(new IOException()); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, templateAttribute, renderer); + try { + container.render(request, attributeContext); + } finally { + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, + request, requestScope, deque, attributeContext, + templateAttribute, renderer); + } + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/CannotRenderExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/CannotRenderExceptionTest.java new file mode 100644 index 0000000000..77fb1202b1 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/CannotRenderExceptionTest.java @@ -0,0 +1,54 @@ +/* + * 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.apache.tiles.core.impl; + +import org.apache.tiles.request.render.CannotRenderException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link CannotRenderException}. + */ +public class CannotRenderExceptionTest { + + /** + * Test method for {@link CannotRenderException#CannotRenderException(String)}. + */ + @Test + public void testCannotRenderExceptionString() { + CannotRenderException exception = new CannotRenderException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link CannotRenderException#CannotRenderException(String, Throwable)}. + */ + @Test + public void testCannotRenderExceptionStringThrowable() { + Throwable cause = new Throwable(); + CannotRenderException exception = new CannotRenderException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/DefaultLocaleResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/DefaultLocaleResolverTest.java new file mode 100644 index 0000000000..8b678ddb11 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/DefaultLocaleResolverTest.java @@ -0,0 +1,58 @@ +/* + * 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.apache.tiles.core.impl; + +import org.apache.tiles.core.locale.impl.DefaultLocaleResolver; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.Locale; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertSame; + +/** + * Tests {@link DefaultLocaleResolver}. + */ +public class DefaultLocaleResolverTest { + + /** + * Test method for {@link DefaultLocaleResolver#resolveLocale(Request)}. + */ + @Test + public void testResolveLocale() { + Request request = createMock(Request.class); + Map sessionScope = createMock(Map.class); + Locale locale = Locale.ITALY; + + expect(request.getContext("session")).andReturn(sessionScope); + expect(sessionScope.get(DefaultLocaleResolver.LOCALE_KEY)).andReturn(null); + expect(request.getRequestLocale()).andReturn(locale); + + replay(request, sessionScope); + DefaultLocaleResolver resolver = new DefaultLocaleResolver(); + assertSame(locale, resolver.resolveLocale(request)); + verify(request, sessionScope); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/InvalidTemplateExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/InvalidTemplateExceptionTest.java new file mode 100644 index 0000000000..60e0e0bb49 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/InvalidTemplateExceptionTest.java @@ -0,0 +1,53 @@ +/* + * 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.apache.tiles.core.impl; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link InvalidTemplateException}. + */ +public class InvalidTemplateExceptionTest { + + /** + * Test method for {@link InvalidTemplateException#InvalidTemplateException(String)}. + */ + @Test + public void testInvalidTemplateExceptionString() { + InvalidTemplateException exception = new InvalidTemplateException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link InvalidTemplateException#InvalidTemplateException(Throwable)}. + */ + @Test + public void testInvalidTemplateExceptionThrowable() { + Throwable cause = new Throwable(); + InvalidTemplateException exception = new InvalidTemplateException(cause); + assertEquals(cause.toString(), exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainerTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainerTest.java new file mode 100644 index 0000000000..d32fcfa2d6 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainerTest.java @@ -0,0 +1,305 @@ +/* + * 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.apache.tiles.core.impl.mgmt; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link CachingTilesContainer}. + * + * @version $Rev$ $Date$ + */ +public class CachingTilesContainerTest { + + /** + * The default name of the attribute in which storing custom definitions. + */ + private static final String DEFAULT_DEFINITIONS_ATTRIBUTE_NAME = + "org.apache.tiles.impl.mgmt.DefinitionManager.DEFINITIONS"; + + /** + * The wrapped Tiles container. + */ + private TilesContainer wrapped; + + /** + * The Tiles container to test. + */ + private CachingTilesContainer container; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + wrapped = createMock(TilesContainer.class); + container = new CachingTilesContainer(wrapped); + } + + @Test + public void testCachingTilesContainer() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + TilesContainer wrapped = createMock(TilesContainer.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definitions.get("definition")).andReturn(definition); + + replay(wrapped, request, definitions, scope, definition); + CachingTilesContainer container = new CachingTilesContainer(wrapped); + assertSame(definition, container.getDefinition("definition", request)); + verify(wrapped, request, definitions, scope, definition); + } + + @Test + public void testGetDefinition() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn( + definitions); + expect(definitions.get("definition")).andReturn(definition); + + replay(wrapped, request, definitions, scope, definition); + assertSame(definition, container.getDefinition("definition", request)); + verify(wrapped, request, definitions, scope, definition); + } + + @Test + public void testGetDefinitionContainer() { + Request request = createMock(Request.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn( + null); + expect(wrapped.getDefinition("definition", request)).andReturn( + definition); + + replay(wrapped, request, scope, definition); + assertSame(definition, container.getDefinition("definition", request)); + verify(wrapped, request, scope, definition); + } + + @Test + public void testIsValidDefinition() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definitions.get("definition")).andReturn(definition); + + replay(wrapped, request, definitions, scope, definition); + assertTrue(container.isValidDefinition("definition", request)); + verify(wrapped, request, definitions, scope, definition); + } + + @Test + public void testIsValidDefinitionContainer() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definitions.get("definition")).andReturn(null); + expect(wrapped.isValidDefinition("definition", request)).andReturn(true); + + replay(wrapped, request, definitions, scope); + assertTrue(container.isValidDefinition("definition", request)); + verify(wrapped, request, definitions, scope); + } + + @Test + public void testRegister() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definition.getName()).andReturn(null); + expect(definitions.containsKey("$anonymousMutableDefinition1")).andReturn(false); + definition.setName("$anonymousMutableDefinition1"); + expect(definition.isExtending()).andReturn(true); + // trick to test resolve definition separately. + expect(definition.isExtending()).andReturn(false); + expect(definition.getName()).andReturn("$anonymousMutableDefinition1"); + expect(definitions.put("$anonymousMutableDefinition1", definition)).andReturn(null); + + replay(wrapped, request, definitions, scope, definition); + container.register(definition, request); + verify(wrapped, request, definitions, scope, definition); + } + + @Test + public void testRegisterInheritance() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + Definition parent = createMock(Definition.class); + Definition grandparent = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope).anyTimes(); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn( + definitions).anyTimes(); + expect(definition.getName()).andReturn(null); + expect(definitions.containsKey("$anonymousMutableDefinition1")) + .andReturn(false); + definition.setName("$anonymousMutableDefinition1"); + expect(definition.isExtending()).andReturn(true); + // trick to test resolve definition separately. + expect(definition.isExtending()).andReturn(true); + expect(definition.getExtends()).andReturn("parent"); + expect(definitions.get("parent")).andReturn(parent); + expect(parent.isExtending()).andReturn(true); + expect(parent.getExtends()).andReturn("grandparent"); + expect(definition.getName()).andReturn("$anonymousMutableDefinition1"); + expect(definitions.get("grandparent")).andReturn(null); + expect(wrapped.getDefinition("grandparent", request)).andReturn( + grandparent); + parent.inherit(grandparent); + definition.inherit(parent); + expect(definitions.put("$anonymousMutableDefinition1", definition)) + .andReturn(null); + + replay(wrapped, request, definitions, scope, definition, parent, + grandparent); + container.register(definition, request); + verify(wrapped, request, definitions, scope, definition, parent, + grandparent); + } + + @Test(expected = NoSuchDefinitionException.class) + public void testRegisterInheritanceFail() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope).anyTimes(); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn( + definitions).anyTimes(); + expect(definition.getName()).andReturn(null); + expect(definitions.containsKey("$anonymousMutableDefinition1")) + .andReturn(false); + definition.setName("$anonymousMutableDefinition1"); + expect(definition.isExtending()).andReturn(true); + // trick to test resolve definition separately. + expect(definition.isExtending()).andReturn(true); + expect(definition.getExtends()).andReturn("parent"); + expect(definitions.get("parent")).andReturn(null); + expect(wrapped.getDefinition("parent", request)).andReturn(null); + expect(definition.getName()).andReturn("$anonymousMutableDefinition1"); + + replay(wrapped, request, definitions, scope, definition); + try { + container.register(definition, request); + } finally { + verify(wrapped, request, definitions, scope, definition); + } + } + + @Test + public void testRegisterCreateDefinitions() { + Request request = createMock(Request.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope).anyTimes(); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn( + null); + expect(scope.put(eq(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME), isA(HashMap.class))).andReturn(null); + expect(definition.getName()).andReturn(null); + definition.setName("$anonymousMutableDefinition1"); + expect(definition.isExtending()).andReturn(true); + // trick to test resolve definition separately. + expect(definition.isExtending()).andReturn(false); + expect(definition.getName()).andReturn("$anonymousMutableDefinition1"); + + replay(wrapped, request, scope, definition); + container.register(definition, request); + verify(wrapped, request, scope, definition); + } + + @Test + public void testRender() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definitions.get("definition")).andReturn(definition); + container.render(definition, request); + + replay(wrapped, request, definitions, scope, definition); + container.render("definition", request); + verify(wrapped, request, definitions, scope, definition); + } + + @Test(expected = NoSuchDefinitionException.class) + public void testRenderFail() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definitions.get("definition")).andReturn(null); + expect(wrapped.getDefinition("definition", request)).andReturn(null); + + replay(wrapped, request, definitions, scope); + try { + container.render("definition", request); + } finally { + verify(wrapped, request, definitions, scope); + } + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/renderer/DefinitionRendererTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/renderer/DefinitionRendererTest.java new file mode 100644 index 0000000000..70e6fba58a --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/renderer/DefinitionRendererTest.java @@ -0,0 +1,106 @@ +/* + * 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.apache.tiles.core.renderer; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.CannotRenderException; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link DefinitionRenderer}. + */ +public class DefinitionRendererTest { + + /** + * The renderer. + */ + private DefinitionRenderer renderer; + + /** + * The container. + */ + private TilesContainer container; + + /** + * {@inheritDoc} + */ + @Before + public void setUp() { + container = createMock(TilesContainer.class); + renderer = new DefinitionRenderer(container); + } + + /** + * Tests + * {@link DefinitionRenderer#render(String, Request)}. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test + public void testWrite() throws IOException { + Request requestContext = createMock(Request.class); + container.render("my.definition", requestContext); + replay(requestContext, container); + renderer.render("my.definition", requestContext); + verify(requestContext, container); + } + + /** + * Tests + * {@link DefinitionRenderer#render(String, Request)}. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test(expected = CannotRenderException.class) + public void testRenderException() throws IOException { + Request requestContext = createMock(Request.class); + replay(requestContext, container); + try { + renderer.render(null, requestContext); + } finally { + verify(requestContext, container); + } + } + + /** + * Tests + * {@link DefinitionRenderer#isRenderable(String, Request)} + * . + */ + @Test + public void testIsRenderable() { + Request requestContext = createMock(Request.class); + expect(container.isValidDefinition("my.definition", requestContext)).andReturn(Boolean.TRUE); + replay(requestContext, container); + assertTrue(renderer.isRenderable("my.definition", requestContext)); + assertFalse(renderer.isRenderable(null, requestContext)); + verify(requestContext, container); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/startup/AbstractTilesInitializerTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/startup/AbstractTilesInitializerTest.java new file mode 100644 index 0000000000..fa7789132b --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/startup/AbstractTilesInitializerTest.java @@ -0,0 +1,130 @@ +/* + * 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.apache.tiles.core.startup; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.core.factory.AbstractTilesContainerFactory; +import org.apache.tiles.request.ApplicationAccess; +import org.apache.tiles.request.ApplicationContext; +import org.junit.Before; +import org.junit.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link AbstractTilesInitializer}. + * + * @version $Rev$ $Date$ + */ +public class AbstractTilesInitializerTest { + + /** + * A mock Tiles container factory. + */ + private AbstractTilesContainerFactory containerFactory; + + /** + * The object to test. + */ + private AbstractTilesInitializer initializer; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + containerFactory = createMock(AbstractTilesContainerFactory.class); + initializer = new AbstractTilesInitializer() { + + @Override + protected AbstractTilesContainerFactory createContainerFactory( + ApplicationContext context) { + return containerFactory; + } + }; + } + + /** + * Test method for {@link AbstractTilesInitializer#initialize(ApplicationContext)}. + */ + @Test + public void testInitialize() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map scope = createMock(Map.class); + + expect(containerFactory.createContainer(context)).andReturn(container); + expect(context.getApplicationScope()).andReturn(scope).anyTimes(); + expect(scope.put(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE, + context)).andReturn(null); + expect(scope.put(TilesAccess.CONTAINER_ATTRIBUTE, container)).andReturn(null); + expect(scope.remove(TilesAccess.CONTAINER_ATTRIBUTE)).andReturn(container); + + replay(containerFactory, context, container, scope); + initializer.initialize(context); + initializer.destroy(); + verify(containerFactory, context, container, scope); + } + + /** + * Test method for {@link AbstractTilesInitializer#createTilesApplicationContext(ApplicationContext)}. + */ + @Test + public void testCreateTilesApplicationContext() { + ApplicationContext context = createMock(ApplicationContext.class); + replay(containerFactory, context); + assertEquals(context, initializer.createTilesApplicationContext(context)); + verify(containerFactory, context); + } + + /** + * Test method for {@link AbstractTilesInitializer#getContainerKey(ApplicationContext)}. + */ + @Test + public void testGetContainerKey() { + ApplicationContext context = createMock(ApplicationContext.class); + replay(containerFactory, context); + assertNull(initializer.getContainerKey(context)); + verify(containerFactory, context); + } + + /** + * Test method for {@link AbstractTilesInitializer#createContainer(ApplicationContext)}. + */ + @Test + public void testCreateContainer() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + + expect(containerFactory.createContainer(context)).andReturn(container); + + replay(containerFactory, context, container); + assertEquals(container, initializer.createContainer(context)); + verify(containerFactory, context, container); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/util/CombinedBeanInfoTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/util/CombinedBeanInfoTest.java new file mode 100644 index 0000000000..b1108d3bda --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/util/CombinedBeanInfoTest.java @@ -0,0 +1,93 @@ +/* + * 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.apache.tiles.core.util; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.reflect.ClassUtil; +import org.junit.Before; +import org.junit.Test; + +import java.beans.FeatureDescriptor; +import java.beans.PropertyDescriptor; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link CombinedBeanInfo}. + */ +public class CombinedBeanInfoTest { + + /** + * The bean info to test. + */ + private CombinedBeanInfo beanInfo; + + /** + * The property descriptors. + */ + private List descriptors; + + /** + * The map of property descriptors for request. + */ + private Map requestMap; + + /** + * The map of property descriptors for application. + */ + private Map applicationMap; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + beanInfo = new CombinedBeanInfo(Request.class, ApplicationContext.class); + requestMap = new LinkedHashMap<>(); + ClassUtil.collectBeanInfo(Request.class, requestMap); + applicationMap = new LinkedHashMap<>(); + ClassUtil.collectBeanInfo(ApplicationContext.class, applicationMap); + descriptors = new ArrayList<>(); + descriptors.addAll(requestMap.values()); + descriptors.addAll(applicationMap.values()); + } + + @Test + public void testGetDescriptors() { + assertEquals(descriptors, beanInfo.getDescriptors()); + } + + @Test + public void testGetMappedDescriptors() { + assertEquals(requestMap, beanInfo.getMappedDescriptors(Request.class)); + assertEquals(applicationMap, beanInfo.getMappedDescriptors(ApplicationContext.class)); + } + + @Test + public void testGetProperties() { + assertEquals(requestMap.keySet(), beanInfo.getProperties(Request.class)); + assertEquals(applicationMap.keySet(), beanInfo.getProperties(ApplicationContext.class)); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/ELAttributeEvaluatorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/ELAttributeEvaluatorTest.java new file mode 100644 index 0000000000..8c1c794bab --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/ELAttributeEvaluatorTest.java @@ -0,0 +1,189 @@ +/* + * 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.apache.tiles.el; + +import com.sun.el.ExpressionFactoryImpl; +import junit.framework.TestCase; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.easymock.EasyMock; + +import javax.el.ArrayELResolver; +import javax.el.BeanELResolver; +import javax.el.CompositeELResolver; +import javax.el.ELResolver; +import javax.el.ListELResolver; +import javax.el.MapELResolver; +import javax.el.ResourceBundleELResolver; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * Tests {@link ELAttributeEvaluator}. + */ +public class ELAttributeEvaluatorTest extends TestCase { + + /** + * The evaluator to test. + */ + private ELAttributeEvaluator evaluator; + + /** + * The request object to use. + */ + private Request request; + + /** {@inheritDoc} */ + @Override + protected void setUp() throws Exception { + super.setUp(); + evaluator = new ELAttributeEvaluator(); + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + requestScope.put("paulaBean", new PaulaBean()); + request = EasyMock.createMock(Request.class); + EasyMock.expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + EasyMock.expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + EasyMock.expect(request.getContext("application")).andReturn( + applicationScope).anyTimes(); + EasyMock.expect(request.getAvailableScopes()).andReturn( + Arrays.asList("request", "session", "application")).anyTimes(); + ApplicationContext applicationContext = EasyMock + .createMock(ApplicationContext.class); + EasyMock.expect(request.getApplicationContext()).andReturn( + applicationContext).anyTimes(); + EasyMock.replay(request, applicationContext); + + evaluator.setExpressionFactory(new ExpressionFactoryImpl()); + ELResolver elResolver = new CompositeELResolver() { + { + BeanELResolver beanElResolver = new BeanELResolver(false); + add(new ScopeELResolver()); + add(new TilesContextELResolver(beanElResolver)); + add(new TilesContextBeanELResolver()); + add(new ArrayELResolver(false)); + add(new ListELResolver(false)); + add(new MapELResolver(false)); + add(new ResourceBundleELResolver()); + add(beanElResolver); + } + }; + evaluator.setResolver(elResolver); + } + + /** + * Tests + * {@link ELAttributeEvaluator#evaluate(Attribute, Request)}. + */ + public void testEvaluate() { + Attribute attribute = new Attribute(); + attribute.setExpressionObject(new Expression("${requestScope.object1}")); + assertEquals("The value is not correct", "value", evaluator.evaluate( + attribute, request)); + attribute.setExpressionObject(new Expression("${sessionScope.object2}")); + assertEquals("The value is not correct", 1, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("${applicationScope.object3}")); + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("${object1}")); + assertEquals("The value is not correct", "value", evaluator.evaluate( + attribute, request)); + attribute.setExpressionObject(new Expression("${object2}")); + assertEquals("The value is not correct", 1, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("${object3}")); + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("${paulaBean.paula}")); + assertEquals("The value is not correct", "Brillant", evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("String literal")); + assertEquals("The value is not correct", "String literal", evaluator + .evaluate(attribute, request)); + attribute.setValue(2); + assertEquals("The value is not correct", 2, evaluator + .evaluate(attribute, request)); + attribute.setValue("${object1}"); + assertEquals("The value has been evaluated", "${object1}", evaluator + .evaluate(attribute, request)); + } + + /** + * Tests + * {@link ELAttributeEvaluator#evaluate(String, Request)}. + */ + public void testEvaluateString() { + String expression = "${requestScope.object1}"; + assertEquals("The value is not correct", "value", evaluator.evaluate( + expression, request)); + expression = "${sessionScope.object2}"; + assertEquals("The value is not correct", 1, evaluator + .evaluate(expression, request)); + expression = "${applicationScope.object3}"; + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(expression, request)); + expression = "${object1}"; + assertEquals("The value is not correct", "value", evaluator.evaluate( + expression, request)); + expression = "${object2}"; + assertEquals("The value is not correct", 1, evaluator + .evaluate(expression, request)); + expression = "${object3}"; + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(expression, request)); + expression = "${paulaBean.paula}"; + assertEquals("The value is not correct", "Brillant", evaluator + .evaluate(expression, request)); + expression = "String literal"; + assertEquals("The value is not correct", expression, evaluator + .evaluate(expression, request)); + } + + /** + * This is The Brillant Paula Bean (sic) just like it was posted to: + * http://thedailywtf.com/Articles/The_Brillant_Paula_Bean.aspx + * I hope that there is no copyright on it. + */ + public static class PaulaBean { + + /** + * Paula is brillant, really. + */ + private final String paula = "Brillant"; + + /** + * Returns brillant. + * + * @return "Brillant". + */ + public String getPaula() { + return paula; + } + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/ELContextImplTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/ELContextImplTest.java new file mode 100644 index 0000000000..b9a835318f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/ELContextImplTest.java @@ -0,0 +1,120 @@ +/* + * 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.apache.tiles.el; + +import org.junit.Before; +import org.junit.Test; + +import javax.el.ELResolver; +import javax.el.FunctionMapper; +import javax.el.ValueExpression; +import javax.el.VariableMapper; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link ELContextImpl}. + */ +public class ELContextImplTest { + + /** + * The EL context to test. + */ + private ELContextImpl context; + + /** + * The EL resolver. + */ + private ELResolver resolver; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + resolver = createMock(ELResolver.class); + context = new ELContextImpl(resolver); + } + + /** + * Test method for {@link ELContextImpl#getELResolver()}. + */ + @Test + public void testGetELResolver() { + replay(resolver); + assertEquals(resolver, context.getELResolver()); + verify(resolver); + } + + /** + * Test method for {@link ELContextImpl#setFunctionMapper(FunctionMapper)}. + */ + @Test + public void testSetFunctionMapper() { + FunctionMapper functionMapper = createMock(FunctionMapper.class); + + replay(resolver, functionMapper); + context.setFunctionMapper(functionMapper); + assertEquals(functionMapper, context.getFunctionMapper()); + verify(resolver, functionMapper); + } + + /** + * Test method for {@link ELContextImpl#setVariableMapper(VariableMapper)}. + */ + @Test + public void testSetVariableMapper() { + VariableMapper variableMapper = createMock(VariableMapper.class); + + replay(resolver, variableMapper); + context.setVariableMapper(variableMapper); + assertEquals(variableMapper, context.getVariableMapper()); + verify(resolver, variableMapper); + } + + /** + * Tests {@link ELContextImpl#getFunctionMapper()}. + */ + @Test + public void testNullFunctionMapper() { + replay(resolver); + FunctionMapper functionMapper = context.getFunctionMapper(); + assertNull(functionMapper.resolveFunction("whatever", "it_IT")); + verify(resolver); + } + + /** + * Tests {@link ELContextImpl#getVariableMapper()}. + */ + @Test + public void testVariableMapperImpl() { + ValueExpression expression = createMock(ValueExpression.class); + + replay(resolver, expression); + VariableMapper variableMapper = context.getVariableMapper(); + assertNull(variableMapper.resolveVariable("whatever")); + variableMapper.setVariable("var", expression); + assertEquals(expression, variableMapper.resolveVariable("var")); + verify(resolver, expression); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/JspExpressionFactoryFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/JspExpressionFactoryFactoryTest.java new file mode 100644 index 0000000000..b7092e5304 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/JspExpressionFactoryFactoryTest.java @@ -0,0 +1,84 @@ +/* + * 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.apache.tiles.el; + +import org.apache.tiles.request.ApplicationContext; +import org.junit.Test; + +import javax.el.ExpressionFactory; +import javax.servlet.ServletContext; +import javax.servlet.jsp.JspApplicationContext; +import javax.servlet.jsp.JspFactory; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link JspExpressionFactoryFactory}. + */ +public class JspExpressionFactoryFactoryTest { + + /** + * Test method for {@link JspExpressionFactoryFactory#getExpressionFactory()}. + */ + @Test + public void testGetExpressionFactory() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ServletContext servletContext = createMock(ServletContext.class); + JspFactory jspFactory = createMock(JspFactory.class); + JspApplicationContext jspApplicationContext = createMock(JspApplicationContext.class); + ExpressionFactory expressionFactory = createMock(ExpressionFactory.class); + + expect(applicationContext.getContext()).andReturn(servletContext); + expect(jspFactory.getJspApplicationContext(servletContext)).andReturn(jspApplicationContext); + expect(jspApplicationContext.getExpressionFactory()).andReturn(expressionFactory); + + replay(applicationContext, servletContext, jspFactory, + jspApplicationContext, expressionFactory); + JspFactory.setDefaultFactory(jspFactory); + JspExpressionFactoryFactory factory = new JspExpressionFactoryFactory(); + factory.setApplicationContext(applicationContext); + assertEquals(expressionFactory, factory.getExpressionFactory()); + verify(applicationContext, servletContext, jspFactory, + jspApplicationContext, expressionFactory); + } + + /** + * Test method for {@link JspExpressionFactoryFactory#getExpressionFactory()}. + */ + @Test(expected = IllegalArgumentException.class) + public void testSetApplicationContextIllegal() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Integer servletContext = 1; + + expect(applicationContext.getContext()).andReturn(servletContext); + + replay(applicationContext); + try { + JspExpressionFactoryFactory factory = new JspExpressionFactoryFactory(); + factory.setApplicationContext(applicationContext); + } finally { + verify(applicationContext); + } + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/ScopeELResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/ScopeELResolverTest.java new file mode 100644 index 0000000000..bdd8d799e5 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/ScopeELResolverTest.java @@ -0,0 +1,175 @@ +/* + * 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.apache.tiles.el; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import javax.el.ELContext; +import java.beans.FeatureDescriptor; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ScopeELResolver}. + */ +public class ScopeELResolverTest { + + /** + * The resolver to test. + */ + private ScopeELResolver resolver; + + /** + * {@inheritDoc} + */ + @Before + public void setUp() { + resolver = new ScopeELResolver(); + } + + /** + * Tests {@link ScopeELResolver#getCommonPropertyType(ELContext, Object)}. + */ + @Test + public void testGetCommonPropertyType() { + ELContext elContext = createMock(ELContext.class); + + replay(elContext); + assertNull(resolver.getCommonPropertyType(elContext, 1)); + assertEquals(Map.class, resolver.getCommonPropertyType(elContext, null)); + verify(elContext); + } + + /** + * Tests {@link ScopeELResolver#getFeatureDescriptors(ELContext, Object)}. + */ + @Test + public void testGetFeatureDescriptors() { + ELContext elContext = createMock(ELContext.class); + Request request = createMock(Request.class); + + expect(elContext.getContext(Request.class)).andReturn(request); + expect(request.getAvailableScopes()).andReturn(Arrays.asList("one", "two")); + + replay(elContext, request); + assertFalse(resolver.getFeatureDescriptors(elContext, 1).hasNext()); + Iterator descriptors = resolver.getFeatureDescriptors(elContext, null); + FeatureDescriptor descriptor = descriptors.next(); + assertEquals("oneScope", descriptor.getName()); + descriptor = descriptors.next(); + assertEquals("twoScope", descriptor.getName()); + assertFalse(descriptors.hasNext()); + verify(elContext, request); + } + + /** + * Test method for + * {@link ScopeELResolver#getType(ELContext, Object, Object)}. + */ + @Test + public void testGetType() { + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ELContext context = new ELContextImpl(resolver); + replay(request, applicationContext); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + assertNull(resolver.getType(context, 1, "whatever")); + assertEquals("The requestScope object is not a map.", Map.class, + resolver.getType(context, null, "requestScope")); + assertEquals("The sessionScope object is not a map.", Map.class, + resolver.getType(context, null, "sessionScope")); + assertEquals("The applicationScope object is not a map.", Map.class, + resolver.getType(context, null, "applicationScope")); + } + + /** + * Test method for + * {@link ScopeELResolver#getValue(ELContext, Object, Object)}. + */ + @Test + public void testGetValue() { + Map requestScope = new HashMap<>(); + requestScope.put("objectKey", "objectValue"); + Map sessionScope = new HashMap<>(); + sessionScope.put("sessionObjectKey", "sessionObjectValue"); + Map applicationScope = new HashMap<>(); + applicationScope.put("applicationObjectKey", "applicationObjectValue"); + Request request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope); + expect(request.getContext("session")).andReturn(sessionScope); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getContext("application")).andReturn(applicationScope); + ELContext context = new ELContextImpl(resolver); + replay(request, applicationContext); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + assertNull(resolver.getValue(context, 1, "whatever")); + assertEquals("The requestScope map does not correspond", requestScope, + resolver.getValue(context, null, "requestScope")); + assertEquals("The sessionScope map does not correspond", sessionScope, + resolver.getValue(context, null, "sessionScope")); + assertEquals("The applicationScope map does not correspond", + applicationScope, resolver.getValue(context, null, + "applicationScope")); + } + + /** + * Tests {@link ScopeELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test + public void testIsReadOnly() { + ELContext elContext = createMock(ELContext.class); + + replay(elContext); + assertTrue(resolver.isReadOnly(elContext, null, "whatever")); + verify(elContext); + } + + /** + * Tests {@link ScopeELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test(expected = NullPointerException.class) + public void testIsReadOnlyNPE() { + resolver.isReadOnly(null, null, "whatever"); + } + + /** + * Tests {@link ScopeELResolver#setValue(ELContext, Object, Object, Object)}. + */ + @Test + public void testSetValue() { + // Just to complete code coverage! + resolver.setValue(null, null, null, null); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextBeanELResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextBeanELResolverTest.java new file mode 100644 index 0000000000..5a1214ec2d --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextBeanELResolverTest.java @@ -0,0 +1,299 @@ +/* + * 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.apache.tiles.el; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import javax.el.ELContext; +import java.beans.FeatureDescriptor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TilesContextBeanELResolver}. + */ +public class TilesContextBeanELResolverTest { + + /** + * The resolver to test. + */ + private TilesContextBeanELResolver resolver; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + resolver = new TilesContextBeanELResolver(); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#getCommonPropertyType(ELContext, Object)}. + */ + @Test + public void testGetCommonPropertyType() { + Class clazz = resolver.getCommonPropertyType(null, null); + assertEquals("The class is not correct", String.class, clazz); + clazz = resolver.getCommonPropertyType(null, "Base object"); + assertNull("The class for non root objects must be null", clazz); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#getFeatureDescriptors(ELContext, Object)}. + */ + @Test + public void testGetFeatureDescriptors() { + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + Request request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getContext("application")).andReturn( + applicationScope).anyTimes(); + expect(request.getAvailableScopes()).andReturn( + Arrays.asList("request", "session", "application")) + .anyTimes(); + replay(request, applicationContext); + + ELContext context = new ELContextImpl(resolver); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + + List expected = new ArrayList<>(); + resolver.collectBeanInfo(requestScope, expected); + resolver.collectBeanInfo(sessionScope, expected); + resolver.collectBeanInfo(applicationScope, expected); + Iterator featureIt = resolver.getFeatureDescriptors( + context, null); + Iterator expectedIt = expected.iterator(); + while (featureIt.hasNext() && expectedIt.hasNext()) { + FeatureDescriptor expectedDescriptor = expectedIt.next(); + FeatureDescriptor descriptor = featureIt.next(); + assertEquals("The feature is not the same", expectedDescriptor + .getDisplayName(), descriptor.getDisplayName()); + assertEquals("The feature is not the same", expectedDescriptor + .getName(), descriptor.getName()); + assertEquals("The feature is not the same", expectedDescriptor + .getShortDescription(), descriptor.getShortDescription()); + assertEquals("The feature is not the same", expectedDescriptor + .getValue("type"), descriptor.getValue("type")); + assertEquals("The feature is not the same", expectedDescriptor + .getValue("resolvableAtDesignTime"), descriptor + .getValue("resolvableAtDesignTime")); + assertEquals("The feature is not the same", expectedDescriptor + .isExpert(), descriptor.isExpert()); + assertEquals("The feature is not the same", expectedDescriptor + .isHidden(), descriptor.isHidden()); + assertEquals("The feature is not the same", expectedDescriptor + .isPreferred(), descriptor.isPreferred()); + } + assertTrue("The feature descriptors are not of the same size", + !featureIt.hasNext() && !expectedIt.hasNext()); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#getType(ELContext, Object, Object)}. + */ + @Test + public void testGetType() { + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + Request request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getContext("application")).andReturn( + applicationScope).anyTimes(); + expect(request.getAvailableScopes()).andReturn( + Arrays.asList("request", "session", "application")) + .anyTimes(); + replay(request, applicationContext); + + ELContext context = new ELContextImpl(resolver); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + + assertEquals("The type is not correct", String.class, resolver.getType( + context, null, "object1")); + assertEquals("The type is not correct", Integer.class, resolver.getType( + context, null, "object2")); + assertEquals("The type is not correct", Float.class, resolver.getType( + context, null, "object3")); + assertNull(resolver.getType(context, 1, "whatever")); + assertNull(resolver.getType(context, null, "object4")); + verify(request, applicationContext); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#getValue(ELContext, Object, Object)}. + */ + @Test + public void testGetValue() { + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + Request request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getContext("application")).andReturn( + applicationScope).anyTimes(); + expect(request.getAvailableScopes()).andReturn( + Arrays.asList("request", "session", "application")) + .anyTimes(); + replay(request, applicationContext); + + ELContext context = new ELContextImpl(resolver); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + + assertEquals("The value is not correct", "value", resolver.getValue( + context, null, "object1")); + assertEquals("The value is not correct", 1, resolver + .getValue(context, null, "object2")); + assertEquals("The value is not correct", 2.0F, resolver + .getValue(context, null, "object3")); + assertNull(resolver.getValue(context, 1, "whatever")); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test + public void testIsReadOnlyELContextObjectObject() { + ELContext context = new ELContextImpl(resolver); + assertTrue("The value is not read only", resolver.isReadOnly(context, + null, null)); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test(expected = NullPointerException.class) + public void testIsReadOnlyNPE() { + resolver.isReadOnly(null, null, null); + } + + /** + * Tests {@link TilesContextBeanELResolver#setValue(ELContext, Object, Object, Object)}. + */ + @Test + public void testSetValue() { + // Just to complete code coverage! + resolver.setValue(null, null, null, null); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#findObjectByProperty(ELContext, Object)}. + */ + @Test + public void testFindObjectByProperty() { + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + Request request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getContext("application")).andReturn( + applicationScope).anyTimes(); + expect(request.getAvailableScopes()).andReturn( + Arrays.asList("request", "session", "application")) + .anyTimes(); + replay(request, applicationContext); + + ELContext context = new ELContextImpl(resolver); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + + assertEquals("The value is not correct", "value", resolver + .findObjectByProperty(context, "object1")); + assertEquals("The value is not correct", 1, resolver + .findObjectByProperty(context, "object2")); + assertEquals("The value is not correct", 2.0F, resolver + .findObjectByProperty(context, "object3")); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#getObject(Map, String)}. + */ + @Test + public void testGetObject() { + Map map = new HashMap<>(); + map.put("object1", "value"); + assertEquals("The value is not correct", "value", resolver.getObject( + map, "object1")); + assertNull("The value is not null", resolver.getObject(map, "object2")); + assertNull("The value is not null", resolver.getObject(null, "object1")); + } + + /** + * Tests {@link TilesContextBeanELResolver#collectBeanInfo(Map, List)}. + */ + @Test + public void testCollectBeanInfoEmpty() { + resolver.collectBeanInfo(null, null); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextELResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextELResolverTest.java new file mode 100644 index 0000000000..c3685aaf9d --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextELResolverTest.java @@ -0,0 +1,189 @@ +/* + * 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.apache.tiles.el; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.reflect.ClassUtil; +import org.junit.Before; +import org.junit.Test; + +import javax.el.ELContext; +import javax.el.ELResolver; +import java.beans.FeatureDescriptor; +import java.beans.PropertyDescriptor; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TilesContextELResolver}. + */ +public class TilesContextELResolverTest { + + /** + * The bean resolver. + */ + private ELResolver beanElResolver; + + /** + * The resolver to test. + */ + private TilesContextELResolver resolver; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + beanElResolver = createMock(ELResolver.class); + resolver = new TilesContextELResolver(beanElResolver); + } + + /** + * Test method for + * {@link TilesContextELResolver#getCommonPropertyType(ELContext, Object)}. + */ + @Test + public void testGetCommonPropertyTypeELContextObject() { + replay(beanElResolver); + Class clazz = resolver.getCommonPropertyType(null, null); + assertEquals("The class is not correct", String.class, clazz); + clazz = resolver.getCommonPropertyType(null, "Base object"); + assertNull("The class for non root objects must be null", clazz); + verify(beanElResolver); + } + + /** + * Test method for + * {@link TilesContextELResolver#getFeatureDescriptors(ELContext, Object)}. + */ + @Test + public void testGetFeatureDescriptorsELContextObject() { + replay(beanElResolver); + assertNull(resolver.getFeatureDescriptors(null, 1)); + Map expected = new LinkedHashMap<>(); + ClassUtil.collectBeanInfo(Request.class, expected); + ClassUtil.collectBeanInfo(ApplicationContext.class, expected); + Iterator featureIt = resolver.getFeatureDescriptors( + null, null); + Iterator expectedIt = expected.values().iterator(); + while (featureIt.hasNext() && expectedIt.hasNext()) { + assertEquals("The feature is not the same", expectedIt.next(), + featureIt.next()); + } + assertTrue("The feature descriptors are not of the same size", + !featureIt.hasNext() && !expectedIt.hasNext()); + verify(beanElResolver); + } + + /** + * Tests {@link TilesContextBeanELResolver#getType(ELContext, Object, Object)}. + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + @Test + public void testGetType() { + ELContext elContext = createMock(ELContext.class); + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + expect(elContext.getContext(Request.class)).andReturn(request); + expect(elContext.getContext(ApplicationContext.class)).andReturn(applicationContext); + expect(beanElResolver.getType(elContext, request, "responseCommitted")).andReturn((Class) Boolean.class); + expect(beanElResolver.getType(elContext, applicationContext, "initParams")).andReturn((Class) Map.class); + elContext.setPropertyResolved(true); + expectLastCall().times(2); + + replay(beanElResolver, elContext, request, applicationContext); + assertNull(resolver.getType(elContext, 1, "whatever")); + assertEquals(Boolean.class, resolver.getType(elContext, null, "responseCommitted")); + assertEquals(Map.class, resolver.getType(elContext, null, "initParams")); + verify(beanElResolver, elContext, request, applicationContext); + } + + /** + * Tests {@link TilesContextBeanELResolver#getValue(ELContext, Object, Object)}. + */ + @Test + public void testGetValue() { + ELContext elContext = createMock(ELContext.class); + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + @SuppressWarnings("rawtypes") + Map map = createMock(Map.class); + + expect(elContext.getContext(Request.class)).andReturn(request); + expect(elContext.getContext(ApplicationContext.class)).andReturn(applicationContext); + expect(beanElResolver.getValue(elContext, request, "responseCommitted")).andReturn(true); + expect(beanElResolver.getValue(elContext, applicationContext, "initParams")).andReturn(map); + elContext.setPropertyResolved(true); + expectLastCall().times(2); + + replay(beanElResolver, elContext, request, applicationContext, map); + assertNull(resolver.getValue(elContext, 1, "whatever")); + assertEquals(true, resolver.getValue(elContext, null, "responseCommitted")); + assertEquals(map, resolver.getValue(elContext, null, "initParams")); + verify(beanElResolver, elContext, request, applicationContext, map); + } + + /** + * Test method for + * {@link TilesContextELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test + public void testIsReadOnly() { + replay(beanElResolver); + ELContext context = new ELContextImpl(resolver); + assertTrue("The value is not read only", resolver.isReadOnly(context, + null, null)); + verify(beanElResolver); + } + + /** + * Test method for + * {@link TilesContextELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test(expected = NullPointerException.class) + public void testIsReadOnlyNPE() { + replay(beanElResolver); + try { + resolver.isReadOnly(null, null, null); + } finally { + verify(beanElResolver); + } + } + + /** + * Tests {@link TilesContextELResolver#setValue(ELContext, Object, Object, Object)}. + */ + @Test + public void testSetValue() { + // Just to complete code coverage! + resolver.setValue(null, null, null, null); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/AnyScopePropertyAccessorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/AnyScopePropertyAccessorTest.java new file mode 100644 index 0000000000..c7f3465cca --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/AnyScopePropertyAccessorTest.java @@ -0,0 +1,152 @@ +/* + * 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.apache.tiles.ognl; + +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link AnyScopePropertyAccessor}. + */ +public class AnyScopePropertyAccessorTest { + + /** + * The accessor to test. + */ + private AnyScopePropertyAccessor accessor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + accessor = new AnyScopePropertyAccessor(); + } + + /** + * Test method for {@link AnyScopePropertyAccessor#getProperty(Map, Object, Object)}. + */ + @Test + public void testGetProperty() { + Request request = createMock(Request.class); + Map oneScope = createMock(Map.class); + Map twoScope = createMock(Map.class); + + expect(request.getAvailableScopes()).andReturn(Arrays.asList("one", "two")).anyTimes(); + expect(request.getContext("one")).andReturn(oneScope).anyTimes(); + expect(request.getContext("two")).andReturn(twoScope).anyTimes(); + expect(oneScope.containsKey("name1")).andReturn(true); + expect(oneScope.get("name1")).andReturn("value1"); + expect(oneScope.containsKey("name2")).andReturn(false); + expect(oneScope.containsKey("name3")).andReturn(false); + expect(twoScope.containsKey("name2")).andReturn(true); + expect(twoScope.get("name2")).andReturn("value2"); + expect(twoScope.containsKey("name3")).andReturn(false); + + replay(request, oneScope, twoScope); + assertEquals("value1", accessor.getProperty(null, request, "name1")); + assertEquals("value2", accessor.getProperty(null, request, "name2")); + assertNull(accessor.getProperty(null, request, "name3")); + verify(request, oneScope, twoScope); + } + + @Test + public void testGetSourceAccessor() { + Request request = createMock(Request.class); + Map oneScope = createMock(Map.class); + Map twoScope = createMock(Map.class); + + expect(request.getAvailableScopes()).andReturn(Arrays.asList("one", "two")).anyTimes(); + expect(request.getContext("one")).andReturn(oneScope).anyTimes(); + expect(request.getContext("two")).andReturn(twoScope).anyTimes(); + expect(oneScope.containsKey("name1")).andReturn(true); + expect(oneScope.containsKey("name2")).andReturn(false); + expect(oneScope.containsKey("name3")).andReturn(false); + expect(twoScope.containsKey("name2")).andReturn(true); + expect(twoScope.containsKey("name3")).andReturn(false); + + replay(request, oneScope, twoScope); + assertEquals(".getContext(\"one\").get(index)", accessor.getSourceAccessor(null, request, "name1")); + assertEquals(".getContext(\"two\").get(index)", accessor.getSourceAccessor(null, request, "name2")); + assertNull(accessor.getSourceAccessor(null, request, "name3")); + verify(request, oneScope, twoScope); + } + + @Test + public void testGetSourceSetter() { + Request request = createMock(Request.class); + Map oneScope = createMock(Map.class); + Map twoScope = createMock(Map.class); + + expect(request.getAvailableScopes()).andReturn(Arrays.asList("one", "two")).anyTimes(); + expect(request.getContext("one")).andReturn(oneScope).anyTimes(); + expect(request.getContext("two")).andReturn(twoScope).anyTimes(); + expect(oneScope.containsKey("name1")).andReturn(true); + expect(oneScope.containsKey("name2")).andReturn(false); + expect(oneScope.containsKey("name3")).andReturn(false); + expect(twoScope.containsKey("name2")).andReturn(true); + expect(twoScope.containsKey("name3")).andReturn(false); + + replay(request, oneScope, twoScope); + assertEquals(".getContext(\"one\").put(index, target)", accessor.getSourceSetter(null, request, "name1")); + assertEquals(".getContext(\"two\").put(index, target)", accessor.getSourceSetter(null, request, "name2")); + assertEquals(".getContext(\"one\").put(index, target)", accessor.getSourceSetter(null, request, "name3")); + verify(request, oneScope, twoScope); + } + + /** + * Test method for {@link AnyScopePropertyAccessor#setProperty(Map, Object, Object, Object)}. + */ + @Test + public void testSetProperty() { + Request request = createMock(Request.class); + Map oneScope = createMock(Map.class); + Map twoScope = createMock(Map.class); + + expect(request.getAvailableScopes()).andReturn(Arrays.asList("one", "two")).anyTimes(); + expect(request.getContext("one")).andReturn(oneScope).anyTimes(); + expect(request.getContext("two")).andReturn(twoScope).anyTimes(); + expect(oneScope.containsKey("name1")).andReturn(true); + expect(oneScope.put("name1", "otherValue1")).andReturn("value1"); + expect(oneScope.containsKey("name2")).andReturn(false); + expect(oneScope.containsKey("name3")).andReturn(false); + expect(twoScope.containsKey("name2")).andReturn(true); + expect(twoScope.put("name2", "otherValue2")).andReturn("value2"); + expect(twoScope.containsKey("name3")).andReturn(false); + expect(oneScope.put("name3", "otherValue3")).andReturn(null); + + replay(request, oneScope, twoScope); + accessor.setProperty(null, request, "name1", "otherValue1"); + accessor.setProperty(null, request, "name2", "otherValue2"); + accessor.setProperty(null, request, "name3", "otherValue3"); + verify(request, oneScope, twoScope); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/DelegatePropertyAccessorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/DelegatePropertyAccessorTest.java new file mode 100644 index 0000000000..fc5470d740 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/DelegatePropertyAccessorTest.java @@ -0,0 +1,111 @@ +/* + * 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.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.OgnlException; +import ognl.PropertyAccessor; +import org.junit.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link DelegatePropertyAccessor}. + */ +public class DelegatePropertyAccessorTest { + + /** + * Test method for {@link DelegatePropertyAccessor#getProperty(Map, Object, Object)}. + * + * @throws OgnlException If something goes wrong. + */ + @Test + public void testGetProperty() throws OgnlException { + PropertyAccessorDelegateFactory factory = createMock(PropertyAccessorDelegateFactory.class); + PropertyAccessor mockAccessor = createMock(PropertyAccessor.class); + Map context = createMock(Map.class); + expect(factory.getPropertyAccessor("property", 1)).andReturn(mockAccessor); + expect(mockAccessor.getProperty(context, 1, "property")).andReturn("value"); + + replay(factory, mockAccessor, context); + PropertyAccessor accessor = new DelegatePropertyAccessor<>(factory); + assertEquals("value", accessor.getProperty(context, 1, "property")); + verify(factory, mockAccessor, context); + } + + /** + * Test method for {@link DelegatePropertyAccessor#setProperty(Map, Object, Object, Object)}. + * + * @throws OgnlException If something goes wrong. + */ + @Test + public void testSetProperty() throws OgnlException { + PropertyAccessorDelegateFactory factory = createMock(PropertyAccessorDelegateFactory.class); + PropertyAccessor mockAccessor = createMock(PropertyAccessor.class); + Map context = createMock(Map.class); + expect(factory.getPropertyAccessor("property", 1)).andReturn(mockAccessor); + mockAccessor.setProperty(context, 1, "property", "value"); + + replay(factory, mockAccessor, context); + PropertyAccessor accessor = new DelegatePropertyAccessor<>(factory); + accessor.setProperty(context, 1, "property", "value"); + verify(factory, mockAccessor, context); + } + + /** + * Test method for {@link DelegatePropertyAccessor#getSourceAccessor(OgnlContext, Object, Object)}. + */ + @Test + public void testGetSourceAccessor() { + PropertyAccessorDelegateFactory factory = createMock(PropertyAccessorDelegateFactory.class); + PropertyAccessor mockAccessor = createMock(PropertyAccessor.class); + OgnlContext context = createMock(OgnlContext.class); + expect(factory.getPropertyAccessor("property", 1)).andReturn(mockAccessor); + expect(mockAccessor.getSourceAccessor(context, 1, "property")).andReturn("method"); + + replay(factory, mockAccessor, context); + PropertyAccessor accessor = new DelegatePropertyAccessor<>(factory); + assertEquals("method", accessor.getSourceAccessor(context, 1, "property")); + verify(factory, mockAccessor, context); + } + + /** + * Test method for {@link DelegatePropertyAccessor#getSourceSetter(OgnlContext, Object, Object)}. + */ + @Test + public void testGetSourceSetter() { + PropertyAccessorDelegateFactory factory = createMock(PropertyAccessorDelegateFactory.class); + PropertyAccessor mockAccessor = createMock(PropertyAccessor.class); + OgnlContext context = createMock(OgnlContext.class); + expect(factory.getPropertyAccessor("property", 1)).andReturn(mockAccessor); + expect(mockAccessor.getSourceSetter(context, 1, "property")).andReturn("method"); + + replay(factory, mockAccessor, context); + PropertyAccessor accessor = new DelegatePropertyAccessor<>(factory); + assertEquals("method", accessor.getSourceSetter(context, 1, "property")); + verify(factory, mockAccessor, context); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessorTest.java new file mode 100644 index 0000000000..0425d3c1c6 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessorTest.java @@ -0,0 +1,106 @@ +/* + * 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.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.OgnlException; +import ognl.PropertyAccessor; +import org.junit.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link NestedObjectDelegatePropertyAccessor}. + */ +public class NestedObjectDelegatePropertyAccessorTest { + + /** + * Test method for {@link NestedObjectDelegatePropertyAccessor#getProperty(Map, Object, Object)}. + * @throws OgnlException If something goes wrong. + */ + @Test + public void testGetProperty() throws OgnlException { + NestedObjectExtractor nestedObjectExtractor = createMock(NestedObjectExtractor.class); + PropertyAccessor propertyAccessor = createMock(PropertyAccessor.class); + Map context = createMock(Map.class); + expect(propertyAccessor.getProperty(context, "nested", "property")).andReturn("value"); + expect(nestedObjectExtractor.getNestedObject(1)).andReturn("nested"); + + replay(nestedObjectExtractor, propertyAccessor, context); + PropertyAccessor accessor = new NestedObjectDelegatePropertyAccessor<>(nestedObjectExtractor, propertyAccessor); + assertEquals("value", accessor.getProperty(context, 1, "property")); + verify(nestedObjectExtractor, propertyAccessor, context); + } + + /** + * Test method for {@link NestedObjectDelegatePropertyAccessor#setProperty(Map, Object, Object, Object)}. + * @throws OgnlException If something goes wrong. + */ + @Test + public void testSetProperty() throws OgnlException { + NestedObjectExtractor nestedObjectExtractor = createMock(NestedObjectExtractor.class); + PropertyAccessor propertyAccessor = createMock(PropertyAccessor.class); + Map context = createMock(Map.class); + propertyAccessor.setProperty(context, "nested", "property", "value"); + expect(nestedObjectExtractor.getNestedObject(1)).andReturn("nested"); + + replay(nestedObjectExtractor, propertyAccessor, context); + PropertyAccessor accessor = new NestedObjectDelegatePropertyAccessor<>(nestedObjectExtractor, propertyAccessor); + accessor.setProperty(context, 1, "property", "value"); + verify(nestedObjectExtractor, propertyAccessor, context); + } + + /** + * Test method for {@link NestedObjectDelegatePropertyAccessor#getSourceAccessor(OgnlContext, Object, Object)}. + */ + @Test + public void testGetSourceAccessor() { + NestedObjectExtractor nestedObjectExtractor = createMock(NestedObjectExtractor.class); + PropertyAccessor propertyAccessor = createMock(PropertyAccessor.class); + OgnlContext context = createMock(OgnlContext.class); + expect(propertyAccessor.getSourceAccessor(context, "nested", "property")).andReturn("method"); + expect(nestedObjectExtractor.getNestedObject(1)).andReturn("nested"); + + replay(nestedObjectExtractor, propertyAccessor, context); + PropertyAccessor accessor = new NestedObjectDelegatePropertyAccessor<>(nestedObjectExtractor, propertyAccessor); + assertEquals("method", accessor.getSourceAccessor(context, 1, "property")); + verify(nestedObjectExtractor, propertyAccessor, context); + } + + /** + * Test method for {@link NestedObjectDelegatePropertyAccessor#getSourceSetter(OgnlContext, Object, Object)}. + */ + @Test + public void testGetSourceSetter() { + NestedObjectExtractor nestedObjectExtractor = createMock(NestedObjectExtractor.class); + PropertyAccessor propertyAccessor = createMock(PropertyAccessor.class); + OgnlContext context = createMock(OgnlContext.class); + expect(propertyAccessor.getSourceSetter(context, "nested", "property")).andReturn("method"); + expect(nestedObjectExtractor.getNestedObject(1)).andReturn("nested"); + + replay(nestedObjectExtractor, propertyAccessor, context); + PropertyAccessor accessor = new NestedObjectDelegatePropertyAccessor<>(nestedObjectExtractor, propertyAccessor); + assertEquals("method", accessor.getSourceSetter(context, 1, "property")); + verify(nestedObjectExtractor, propertyAccessor, context); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/OGNLAttributeEvaluatorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/OGNLAttributeEvaluatorTest.java new file mode 100644 index 0000000000..fbfe2081b8 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/OGNLAttributeEvaluatorTest.java @@ -0,0 +1,229 @@ +/* + * $Id$ + * + * 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.apache.tiles.ognl; + +import ognl.OgnlException; +import ognl.OgnlRuntime; +import ognl.PropertyAccessor; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.apache.tiles.core.evaluator.EvaluationException; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link OGNLAttributeEvaluator}. + * + * @version $Rev$ $Date$$ + */ +public class OGNLAttributeEvaluatorTest { + + /** + * The evaluator to test. + */ + private OGNLAttributeEvaluator evaluator; + + /** + * The request object to use. + */ + private Request request; + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * Sets up the test. + * + * @throws OgnlException If something goes wrong. + */ + @Before + public void setUp() throws OgnlException { + PropertyAccessor objectPropertyAccessor = OgnlRuntime.getPropertyAccessor(Object.class); + PropertyAccessor applicationContextPropertyAccessor = new NestedObjectDelegatePropertyAccessor<>( + new TilesApplicationContextNestedObjectExtractor(), + objectPropertyAccessor + ); + PropertyAccessor anyScopePropertyAccessor = new AnyScopePropertyAccessor(); + PropertyAccessor scopePropertyAccessor = new ScopePropertyAccessor(); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, + applicationContextPropertyAccessor, + anyScopePropertyAccessor, + scopePropertyAccessor + ); + PropertyAccessor tilesRequestAccessor = new DelegatePropertyAccessor<>(factory); + OgnlRuntime.setPropertyAccessor(Request.class, tilesRequestAccessor); + evaluator = new OGNLAttributeEvaluator(); + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + requestScope.put("paulaBean", new PaulaBean()); + request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + expect(request.getContext("application")).andReturn(applicationScope) + .anyTimes(); + expect(request.getAvailableScopes()).andReturn(Arrays.asList("request", "session", "application")) + .anyTimes(); + applicationContext = createMock(ApplicationContext.class); + expect(request.getApplicationContext()).andReturn(applicationContext) + .anyTimes(); + expect(applicationContext.getApplicationScope()).andReturn(applicationScope) + .anyTimes(); + replay(request, applicationContext); + } + + /** + * Tears down the test. + */ + @After + public void tearDown() { + verify(request, applicationContext); + } + + /** + * Tests + * {@link OGNLAttributeEvaluator#evaluate(Attribute, Request)}. + */ + @Test + public void testEvaluate() { + Attribute attribute = new Attribute(); + attribute.setExpressionObject(new Expression("requestScope.object1")); + assertEquals("The value is not correct", "value", evaluator.evaluate( + attribute, request)); + attribute.setExpressionObject(new Expression("sessionScope.object2")); + assertEquals("The value is not correct", 1, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("applicationScope.object3")); + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("object1")); + assertEquals("The value is not correct", "value", evaluator.evaluate( + attribute, request)); + attribute.setExpressionObject(new Expression("object2")); + assertEquals("The value is not correct", 1, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("object3")); + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("paulaBean.paula")); + assertEquals("The value is not correct", "Brillant", evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("'String literal'")); + assertEquals("The value is not correct", "String literal", evaluator + .evaluate(attribute, request)); + attribute.setValue(2); + assertEquals("The value is not correct", 2, evaluator + .evaluate(attribute, request)); + attribute.setValue("object1"); + assertEquals("The value has been evaluated", "object1", evaluator + .evaluate(attribute, request)); + } + + /** + * Tests {@link OGNLAttributeEvaluator#evaluate(String, Request)}. + */ + @Test + public void testEvaluateString() { + String expression = "requestScope.object1"; + assertEquals("The value is not correct", "value", evaluator.evaluate( + expression, request)); + expression = "sessionScope.object2"; + assertEquals("The value is not correct", 1, evaluator + .evaluate(expression, request)); + expression = "applicationScope.object3"; + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(expression, request)); + expression = "object1"; + assertEquals("The value is not correct", "value", evaluator.evaluate( + expression, request)); + expression = "object2"; + assertEquals("The value is not correct", 1, evaluator + .evaluate(expression, request)); + expression = "object3"; + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(expression, request)); + expression = "paulaBean.paula"; + assertEquals("The value is not correct", "Brillant", evaluator + .evaluate(expression, request)); + expression = "'String literal'"; + assertEquals("The value is not correct", "String literal", evaluator + .evaluate(expression, request)); + } + + /** + * Tests {@link OGNLAttributeEvaluator#evaluate(String, Request)}. + */ + @Test(expected = IllegalArgumentException.class) + public void testEvaluateNull() { + evaluator.evaluate((String) null, request); + } + + /** + * Tests {@link OGNLAttributeEvaluator#evaluate(String, Request)}. + */ + @Test(expected = EvaluationException.class) + public void testEvaluateOgnlException() { + evaluator.evaluate("wrong|||!!!!yes###", request); + } + + /** + * This is The Brillant Paula Bean (sic) just like it was posted to: + * http://thedailywtf.com/Articles/The_Brillant_Paula_Bean.aspx I hope that + * there is no copyright on it. + */ + public static class PaulaBean { + + /** + * Paula is brillant, really. + */ + private final String paula = "Brillant"; + + /** + * Returns brillant. + * + * @return "Brillant". + */ + public String getPaula() { + return paula; + } + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/ScopePropertyAccessorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/ScopePropertyAccessorTest.java new file mode 100644 index 0000000000..86b29449c7 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/ScopePropertyAccessorTest.java @@ -0,0 +1,91 @@ +/* + * 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.apache.tiles.ognl; + +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link ScopePropertyAccessor}. + */ +public class ScopePropertyAccessorTest { + + /** + * The accessor to test. + */ + private ScopePropertyAccessor accessor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + accessor = new ScopePropertyAccessor(); + } + + /** + * Test method for {@link ScopePropertyAccessor#getProperty(Map, Object, Object)}. + */ + @Test + public void testGetProperty() { + Request request = createMock(Request.class); + Map oneScope = createMock(Map.class); + + expect(request.getContext("one")).andReturn(oneScope); + + replay(request); + assertEquals(oneScope, accessor.getProperty(null, request, "oneScope")); + assertNull(accessor.getProperty(null, request, "whatever")); + verify(request); + } + + @Test + public void testGetSourceAccessor() { + Request request = createMock(Request.class); + + replay(request); + assertEquals(".getContext(\"one\")", accessor.getSourceAccessor(null, request, "oneScope")); + assertNull(accessor.getSourceAccessor(null, request, "whatever")); + verify(request); + } + + @Test + public void testGetSourceSetter() { + assertNull(accessor.getSourceSetter(null, null, "whatever")); + } + + /** + * Test method for {@link ScopePropertyAccessor#setProperty(Map, Object, Object, Object)}. + */ + @Test + public void testSetProperty() { + accessor.setProperty(null, null, "whatever", "whateverValue"); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractorTest.java new file mode 100644 index 0000000000..b791a646ce --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractorTest.java @@ -0,0 +1,51 @@ +/* + * 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.apache.tiles.ognl; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link TilesApplicationContextNestedObjectExtractor}. + */ +public class TilesApplicationContextNestedObjectExtractorTest { + + /** + * Tests {@link TilesApplicationContextNestedObjectExtractor#getNestedObject(Request)}. + */ + @Test + public void testGetNestedObject() { + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getApplicationContext()).andReturn(applicationContext); + + replay(request, applicationContext); + NestedObjectExtractor extractor = new TilesApplicationContextNestedObjectExtractor(); + assertEquals(applicationContext, extractor.getNestedObject(request)); + verify(request, applicationContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactoryTest.java new file mode 100644 index 0000000000..8a70ae2205 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactoryTest.java @@ -0,0 +1,189 @@ +/* + * 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.apache.tiles.ognl; + +import ognl.PropertyAccessor; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link TilesContextPropertyAccessorDelegateFactory}. + */ +public class TilesContextPropertyAccessorDelegateFactoryTest { + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorRequest() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(objectPropertyAccessor, factory.getPropertyAccessor("writer", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + } + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorApplication() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(applicationContextPropertyAccessor, factory.getPropertyAccessor("initParams", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + } + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorRequestScope() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(requestScopePropertyAccessor, factory.getPropertyAccessor("attribute", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + } + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorSessionScope() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(requestScopePropertyAccessor, factory.getPropertyAccessor("attribute", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + } + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorApplicationScope() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request, applicationContext); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(requestScopePropertyAccessor, factory.getPropertyAccessor("attribute", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request, applicationContext); + } + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorRequestScopeDefault() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request, applicationContext); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(requestScopePropertyAccessor, factory.getPropertyAccessor("attribute", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request, applicationContext); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractClientRequestTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractClientRequestTest.java new file mode 100644 index 0000000000..338270d119 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractClientRequestTest.java @@ -0,0 +1,155 @@ +/* + * 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.apache.tiles.request; + +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link AbstractClientRequest}. + */ +public class AbstractClientRequestTest { + + /** + * The request to test. + */ + private AbstractClientRequest request; + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * The application scope. + */ + private Map applicationScope; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + applicationContext = createMock(ApplicationContext.class); + applicationScope = new HashMap<>(); + request = createMockBuilder(AbstractClientRequest.class).withConstructor(applicationContext).createMock(); + + expect(applicationContext.getApplicationScope()).andReturn(applicationScope).anyTimes(); + } + + /** + * Test method for {@link AbstractClientRequest#dispatch(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testDispatch() throws IOException { + Map requestScope = new HashMap<>(); + + expect(request.getContext(Request.REQUEST_SCOPE)).andReturn(requestScope).anyTimes(); + request.doForward("/my/path.html"); + request.doInclude("/my/path2.html"); + + replay(request, applicationContext); + request.dispatch("/my/path.html"); + request.dispatch("/my/path2.html"); + verify(request, applicationContext); + } + + /** + * Test method for {@link AbstractClientRequest#include(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testInclude() throws IOException { + Map requestScope = new HashMap<>(); + + expect(request.getContext(Request.REQUEST_SCOPE)).andReturn(requestScope).anyTimes(); + request.doInclude("/my/path2.html"); + + replay(request, applicationContext); + request.include("/my/path2.html"); + assertTrue((Boolean) request.getContext(Request.REQUEST_SCOPE).get(AbstractRequest.FORCE_INCLUDE_ATTRIBUTE_NAME)); + verify(request, applicationContext); + } + + /** + * Test method for {@link AbstractClientRequest#getApplicationContext()}. + */ + @Test + public void testGetApplicationContext() { + replay(request, applicationContext); + assertEquals(applicationContext, request.getApplicationContext()); + verify(request, applicationContext); + } + + /** + * Test method for {@link AbstractClientRequest#getContext(String)}. + */ + @Test + public void testGetContext() { + Map scope = createMock(Map.class); + + expect(request.getContext("myScope")).andReturn(scope); + + replay(request, applicationContext, scope); + assertEquals(scope, request.getContext("myScope")); + verify(request, applicationContext, scope); + } + + /** + * Test method for {@link AbstractClientRequest#getAvailableScopes()}. + */ + @Test + public void testGetAvailableScopes() { + String[] scopes = new String[]{"one", "two", "three"}; + + expect(request.getAvailableScopes()).andReturn(Arrays.asList(scopes)); + + replay(request, applicationContext); + assertArrayEquals(scopes, request.getAvailableScopes().toArray()); + verify(request, applicationContext); + } + + /** + * Test method for {@link AbstractClientRequest#getApplicationScope()}. + */ + @Test + public void testGetApplicationScope() { + replay(request, applicationContext); + assertEquals(applicationScope, request.getApplicationScope()); + verify(request, applicationContext); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractRequestTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractRequestTest.java new file mode 100644 index 0000000000..e0e3dd0c37 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractRequestTest.java @@ -0,0 +1,54 @@ +/* + * 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.apache.tiles.request; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link AbstractRequest}. + */ +public class AbstractRequestTest { + + /** + * Test method for {@link AbstractRequest#setForceInclude(boolean)}. + */ + @Test + public void testSetForceInclude() { + AbstractRequest request = createMockBuilder(AbstractRequest.class).createMock(); + Map scope = new HashMap<>(); + + expect(request.getContext(Request.REQUEST_SCOPE)).andReturn(scope).anyTimes(); + + replay(request); + assertFalse(request.isForceInclude()); + request.setForceInclude(true); + assertTrue(request.isForceInclude()); + verify(request); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractViewRequestTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractViewRequestTest.java new file mode 100644 index 0000000000..bf650240df --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractViewRequestTest.java @@ -0,0 +1,119 @@ +/* + * 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.apache.tiles.request; + +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link AbstractViewRequest}. + */ +public class AbstractViewRequestTest { + + /** + * The request to test. + */ + private AbstractViewRequest request; + + /** + * The internal request. + */ + private DispatchRequest wrappedRequest; + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + wrappedRequest = createMock(DispatchRequest.class); + request = createMockBuilder(AbstractViewRequest.class).withConstructor(wrappedRequest).createMock(); + applicationContext = createMock(ApplicationContext.class); + Map applicationScope = new HashMap<>(); + + expect(wrappedRequest.getApplicationContext()).andReturn(applicationContext).anyTimes(); + expect(applicationContext.getApplicationScope()).andReturn(applicationScope).anyTimes(); + } + + /** + * Test method for {@link AbstractViewRequest#dispatch(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testDispatch() throws IOException { + Map requestScope = new HashMap<>(); + + expect(request.getContext(Request.REQUEST_SCOPE)).andReturn(requestScope); + wrappedRequest.include("/my/path.html"); + + replay(wrappedRequest, request, applicationContext); + request.dispatch("/my/path.html"); + assertTrue((Boolean) requestScope.get(AbstractRequest.FORCE_INCLUDE_ATTRIBUTE_NAME)); + verify(wrappedRequest, request, applicationContext); + } + + /** + * Test method for {@link AbstractViewRequest#include(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testInclude() throws IOException { + Map requestScope = new HashMap<>(); + + expect(request.getContext(Request.REQUEST_SCOPE)).andReturn(requestScope); + wrappedRequest.include("/my/path.html"); + + replay(wrappedRequest, request, applicationContext); + request.include("/my/path.html"); + assertTrue((Boolean) requestScope.get(AbstractRequest.FORCE_INCLUDE_ATTRIBUTE_NAME)); + verify(wrappedRequest, request, applicationContext); + } + + /** + * Test method for {@link AbstractViewRequest#doInclude(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testDoInclude() throws IOException { + wrappedRequest.include("/my/path.html"); + + replay(wrappedRequest, request, applicationContext); + request.doInclude("/my/path.html"); + verify(wrappedRequest, request, applicationContext); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/ApplicationAccessTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/ApplicationAccessTest.java new file mode 100644 index 0000000000..08b5ec27f9 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/ApplicationAccessTest.java @@ -0,0 +1,51 @@ +/* + * 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.apache.tiles.request; + +import org.junit.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link ApplicationAccess}. + */ +public class ApplicationAccessTest { + + /** + * Test method for {@link ApplicationAccess#register(ApplicationContext)}. + */ + @Test + public void testRegister() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map applicationScope = createMock(Map.class); + + expect(applicationContext.getApplicationScope()).andReturn(applicationScope); + expect(applicationScope.put(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE, applicationContext)).andReturn(null); + + replay(applicationContext, applicationScope); + ApplicationAccess.register(applicationContext); + verify(applicationContext, applicationScope); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/DispatchRequestWrapperTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/DispatchRequestWrapperTest.java new file mode 100644 index 0000000000..2fa6a96d03 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/DispatchRequestWrapperTest.java @@ -0,0 +1,90 @@ +/* + * 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.apache.tiles.request; + +import org.junit.Test; + +import java.io.IOException; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link DispatchRequestWrapper}. + */ +public class DispatchRequestWrapperTest { + + protected DispatchRequest createMockRequest() { + return createMock(DispatchRequest.class); + } + + protected DispatchRequestWrapper createRequestWrapper(Request wrappedRequest) { + return new DispatchRequestWrapper((DispatchRequest) wrappedRequest); + } + + /** + * Test method for {@link DispatchRequestWrapper#dispatch(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testDispatch() throws IOException { + DispatchRequest wrappedRequest = createMockRequest(); + + wrappedRequest.dispatch("/my/path.html"); + + replay(wrappedRequest); + DispatchRequestWrapper request = createRequestWrapper(wrappedRequest); + request.dispatch("/my/path.html"); + verify(wrappedRequest); + } + + /** + * Test method for {@link DispatchRequestWrapper#include(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testInclude() throws IOException { + DispatchRequest wrappedRequest = createMockRequest(); + + wrappedRequest.include("/my/path.html"); + + replay(wrappedRequest); + DispatchRequestWrapper request = createRequestWrapper(wrappedRequest); + request.include("/my/path.html"); + verify(wrappedRequest); + } + + /** + * Test method for {@link DispatchRequestWrapper#setContentType(String)}. + */ + @Test + public void testSetContentType() { + DispatchRequest wrappedRequest = createMockRequest(); + + wrappedRequest.setContentType("text/html"); + + replay(wrappedRequest); + DispatchRequestWrapper request = createRequestWrapper(wrappedRequest); + request.setContentType("text/html"); + verify(wrappedRequest); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/NotAvailableFeatureExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/NotAvailableFeatureExceptionTest.java new file mode 100644 index 0000000000..f1d6caf51a --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/NotAvailableFeatureExceptionTest.java @@ -0,0 +1,41 @@ +/* + * 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.apache.tiles.request; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link NotAvailableFeatureException}. + */ +public class NotAvailableFeatureExceptionTest { + + /** + * Test method for {@link NotAvailableFeatureException#NotAvailableFeatureException(String, Throwable)}. + */ + @Test + public void testNotAvailableFeatureExceptionStringThrowable() { + Throwable cause = new Throwable(); + NotAvailableFeatureException exception = new NotAvailableFeatureException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/RequestExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/RequestExceptionTest.java new file mode 100644 index 0000000000..b8a699c456 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/RequestExceptionTest.java @@ -0,0 +1,53 @@ +/* + * 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.apache.tiles.request; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link RequestException}. + */ +public class RequestExceptionTest { + + /** + * Test method for {@link RequestException#RequestException(String)}. + */ + @Test + public void testRequestExceptionString() { + RequestException exception = new RequestException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link RequestException#RequestException(String, Throwable)}. + */ + @Test + public void testRequestExceptionStringThrowable() { + Throwable cause = new Throwable(); + RequestException exception = new RequestException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/AddableParameterMapTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/AddableParameterMapTest.java new file mode 100644 index 0000000000..a06d9bb818 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/AddableParameterMapTest.java @@ -0,0 +1,112 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasAddableKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link AddableParameterMap}. + */ +public class AddableParameterMapTest { + + /** + * The object to test. + */ + private AddableParameterMap map; + + /** + * The extractor to use. + */ + private HasAddableKeys extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasAddableKeys.class); + map = new AddableParameterMap(extractor); + } + + /** + * Test method for {@link AddableParameterMap#entrySet()}. + */ + @Test + public void testEntrySet() { + Set> entrySet = map.entrySet(); + MapEntry entry1 = new MapEntry<>("one", "value1", false); + MapEntry entry2 = new MapEntry<>("two", "value2", false); + List> entries = new ArrayList<>(2); + entries.add(entry1); + entries.add(entry2); + + extractor.setValue("one", "value1"); + expectLastCall().times(2); + extractor.setValue("two", "value2"); + replay(extractor); + entrySet.add(entry1); + entrySet.addAll(entries); + verify(extractor); + } + + /** + * Test method for {@link AddableParameterMap#put(String, String)}. + */ + @Test + public void testPut() { + expect(extractor.getValue("one")).andReturn(null); + extractor.setValue("one", "value1"); + + replay(extractor); + assertNull(map.put("one", "value1")); + verify(extractor); + } + + /** + * Test method for {@link AddableParameterMap#putAll(Map)}. + */ + @Test + public void testPutAll() { + Map map = new HashMap<>(); + map.put("one", "value1"); + map.put("two", "value2"); + + extractor.setValue("one", "value1"); + extractor.setValue("two", "value2"); + + replay(extractor); + this.map.putAll(map); + verify(extractor); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/CollectionUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/CollectionUtilTest.java new file mode 100644 index 0000000000..39f2867609 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/CollectionUtilTest.java @@ -0,0 +1,59 @@ +/* + * 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.apache.tiles.request.collection; + +import org.junit.Test; + +import java.util.Enumeration; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +public class CollectionUtilTest { + + @Test + public void testKey() { + assertEquals("1", CollectionUtil.key(1)); + assertEquals("hello", CollectionUtil.key("hello")); + } + + @Test(expected = IllegalArgumentException.class) + public void testKeyException() { + CollectionUtil.key(null); + } + + @Test + public void testEnumerationSize() { + Enumeration enumeration = createMock(Enumeration.class); + + expect(enumeration.hasMoreElements()).andReturn(true); + expect(enumeration.nextElement()).andReturn(1); + expect(enumeration.hasMoreElements()).andReturn(true); + expect(enumeration.nextElement()).andReturn(1); + expect(enumeration.hasMoreElements()).andReturn(false); + + replay(enumeration); + assertEquals(2, CollectionUtil.enumerationSize(enumeration)); + verify(enumeration); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesCollectionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesCollectionTest.java new file mode 100644 index 0000000000..36f9bd2e09 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesCollectionTest.java @@ -0,0 +1,398 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link HeaderValuesMap#values()}. + */ +public class HeaderValuesCollectionTest { + + /** + * The extractor to use. + */ + private EnumeratedValuesExtractor extractor; + + /** + * The map to test. + */ + private HeaderValuesMap map; + + /** + * The collection. + */ + private Collection coll; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(EnumeratedValuesExtractor.class); + map = new HeaderValuesMap(extractor); + coll = map.values(); + } + + /** + * Tests {@link Collection#add(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + coll.add(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + coll.addAll(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + coll.clear(); + } + + /** + * Tests {@link Collection#contains(Object)}. + */ + @Test + public void testContainsValue() { + assertFalse(map.containsValue(1)); + + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + assertTrue(coll.contains(new String[]{"value2", "value3"})); + verify(extractor, keys, values1, values2); + } + + /** + * Tests {@link Collection#contains(Object)}. + */ + @Test + public void testContainsValueFalse() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + assertFalse(coll.contains(new String[]{"value2", "value4"})); + verify(extractor, keys, values1, values2); + } + + @Test + public void testContainsAll() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys).times(2); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValues("one")).andReturn(values1).times(2); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + List coll = new ArrayList<>(); + coll.add(new String[]{"value1"}); + coll.add(new String[]{"value2", "value3"}); + assertTrue(this.coll.containsAll(coll)); + verify(extractor, keys, values1, values2); + } + + @Test + public void testContainsAllFalse() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + + replay(extractor, keys, values1, values2); + List coll = new ArrayList<>(); + coll.add(new String[]{"value4"}); + assertFalse(this.coll.containsAll(coll)); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link Collection#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(coll.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#iterator()}. + */ + @Test + public void testIterator() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(extractor.getValues("two")).andReturn(values2); + + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values2); + Iterator entryIt = coll.iterator(); + assertTrue(entryIt.hasNext()); + assertArrayEquals(new String[]{"value2", "value3"}, entryIt.next()); + verify(extractor, keys, values2); + } + + /** + * Test method for {@link Collection#iterator()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testIteratorRemove() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + try { + replay(extractor, keys); + coll.iterator().remove(); + } finally { + verify(extractor, keys); + } + } + + /** + * Tests {@link Collection#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + coll.remove(null); + } + + /** + * Tests {@link Collection#removeAll(Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + coll.removeAll(null); + } + + /** + * Tests {@link Collection#retainAll(Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRetainAll() { + coll.retainAll(null); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, coll.size()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#toArray()}. + */ + @Test + public void testToArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + String[][] entryArray = new String[2][]; + entryArray[0] = new String[]{"value1"}; + entryArray[1] = new String[]{"value2", "value3"}; + + replay(extractor, keys, values1, values2); + assertArrayEquals(entryArray, coll.toArray()); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link Collection#toArray(Object[])}. + */ + @Test + public void testToArrayTArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + String[][] entryArray = new String[2][]; + entryArray[0] = new String[]{"value1"}; + entryArray[1] = new String[]{"value2", "value3"}; + String[][] realArray = new String[2][]; + + replay(extractor, keys, values1, values2); + assertArrayEquals(entryArray, coll.toArray(realArray)); + verify(extractor, keys, values1, values2); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapEntrySetTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapEntrySetTest.java new file mode 100644 index 0000000000..77218414d3 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapEntrySetTest.java @@ -0,0 +1,337 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link HeaderValuesMap entry set}. + */ +public class HeaderValuesMapEntrySetTest { + + /** + * The extractor to use. + */ + private EnumeratedValuesExtractor extractor; + + /** + * The set to test. + */ + private Set> entrySet; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(EnumeratedValuesExtractor.class); + HeaderValuesMap map = new HeaderValuesMap(extractor); + entrySet = map.entrySet(); + } + + /** + * Tests {@link Set#add(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + entrySet.add(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + entrySet.addAll(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + entrySet.clear(); + } + + /** + * Tests {@link Set#contains(Object)}. + */ + @Test + public void testContains() { + Map.Entry entry = createMock(Map.Entry.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(entry.getKey()).andReturn("two"); + expect(entry.getValue()).andReturn(new String[]{"value2", "value3"}); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, entry, values2); + assertTrue(entrySet.contains(entry)); + verify(extractor, entry, values2); + } + + @Test + public void testContainsAll() { + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + Map.Entry entry1 = createMock(Map.Entry.class); + Map.Entry entry2 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn(new String[]{"value1"}); + expect(entry2.getKey()).andReturn("two"); + expect(entry2.getValue()).andReturn(new String[]{"value2", "value3"}); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, values1, values2, entry1, entry2); + List> coll = new ArrayList<>(); + coll.add(entry1); + coll.add(entry2); + assertTrue(entrySet.containsAll(coll)); + verify(extractor, values1, values2, entry1, entry2); + } + + @Test + public void testContainsAllFalse() { + Enumeration values1 = createMock(Enumeration.class); + Map.Entry entry1 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn(new String[]{"value4"}); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + + replay(extractor, values1, entry1); + List> coll = new ArrayList<>(); + coll.add(entry1); + assertFalse(entrySet.containsAll(coll)); + verify(extractor, values1, entry1); + } + + /** + * Test method for {@link Set#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(entrySet.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test + public void testIterator() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values2); + Iterator> entryIt = entrySet.iterator(); + assertTrue(entryIt.hasNext()); + MapEntryArrayValues entry = new MapEntryArrayValues<>("two", new String[]{"value2", "value3"}, false); + assertEquals(entry, entryIt.next()); + verify(extractor, keys, values2); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testIteratorRemove() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + try { + replay(extractor, keys); + entrySet.iterator().remove(); + } finally { + verify(extractor, keys); + } + } + + /** + * Tests {@link Set#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + entrySet.remove(null); + } + + /** + * Tests {@link Set#removeAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + entrySet.removeAll(null); + } + + /** + * Tests {@link Set#retainAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRetainAll() { + entrySet.retainAll(null); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, entrySet.size()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#toArray()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testToArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + MapEntryArrayValues[] entryArray = new MapEntryArrayValues[2]; + entryArray[0] = new MapEntryArrayValues<>("one", new String[]{"value1"}, false); + entryArray[1] = new MapEntryArrayValues<>("two", new String[]{"value2", "value3"}, false); + + replay(extractor, keys, values1, values2); + assertArrayEquals(entryArray, entrySet.toArray()); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link Set#toArray(Object[])}. + */ + @Test + @SuppressWarnings("unchecked") + public void testToArrayTArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + MapEntryArrayValues[] entryArray = new MapEntryArrayValues[2]; + entryArray[0] = new MapEntryArrayValues<>("one", new String[]{"value1"}, false); + entryArray[1] = new MapEntryArrayValues<>("two", new String[]{"value2", "value3"}, false); + MapEntryArrayValues[] realArray = new MapEntryArrayValues[2]; + + replay(extractor, keys, values1, values2); + assertArrayEquals(entryArray, entrySet.toArray(realArray)); + verify(extractor, keys, values1, values2); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapTest.java new file mode 100644 index 0000000000..aaf0ef6025 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapTest.java @@ -0,0 +1,337 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.util.Enumeration; +import java.util.HashMap; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link HeaderValuesMap}. + */ +public class HeaderValuesMapTest { + + /** + * The extractor to use. + */ + private EnumeratedValuesExtractor extractor; + + /** + * The map to test. + */ + private HeaderValuesMap map; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(EnumeratedValuesExtractor.class); + map = new HeaderValuesMap(extractor); + } + + /** + * Test method for {@link HeaderValuesMap#hashCode()}. + */ + @Test + public void testHashCode() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + assertEquals( + ("one".hashCode() ^ "value1".hashCode()) + + ("two".hashCode() ^ ("value2".hashCode() + "value3" + .hashCode())), + map.hashCode()); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link HeaderValuesMap#clear()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + map.clear(); + } + + /** + * Test method for {@link HeaderValuesMap#containsKey(Object)}. + */ + @Test + public void testContainsKey() { + expect(extractor.getValue("one")).andReturn("value1"); + expect(extractor.getValue("two")).andReturn(null); + + replay(extractor); + assertTrue(map.containsKey("one")); + assertFalse(map.containsKey("two")); + verify(extractor); + } + + /** + * Test method for {@link HeaderValuesMap#containsValue(Object)}. + */ + @Test + public void testContainsValue() { + assertFalse(map.containsValue(1)); + + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + assertTrue(map.containsValue(new String[]{"value2", "value3"})); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link HeaderValuesMap#containsValue(Object)}. + */ + @Test + public void testContainsValueFalse() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + assertFalse(map.containsValue(new String[]{"value2", "value4"})); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link HeaderValuesMap#equals(Object)}. + */ + @Test + public void testEqualsObject() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + EnumeratedValuesExtractor otherExtractor = createMock(EnumeratedValuesExtractor.class); + Enumeration otherValues1 = createMock(Enumeration.class); + Enumeration otherValues2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + expect(otherExtractor.getValues("one")).andReturn(otherValues1); + expect(otherValues1.hasMoreElements()).andReturn(true); + expect(otherValues1.nextElement()).andReturn("value1"); + expect(otherValues1.hasMoreElements()).andReturn(false); + + expect(otherExtractor.getValues("two")).andReturn(otherValues2); + expect(otherValues2.hasMoreElements()).andReturn(true); + expect(otherValues2.nextElement()).andReturn("value2"); + expect(otherValues2.hasMoreElements()).andReturn(true); + expect(otherValues2.nextElement()).andReturn("value3"); + expect(otherValues2.hasMoreElements()).andReturn(false); + + replay(extractor, otherExtractor, keys, values1, values2, otherValues1, otherValues2); + HeaderValuesMap otherMap = new HeaderValuesMap(otherExtractor); + assertTrue(map.equals(otherMap)); + verify(extractor, otherExtractor, keys, values1, values2, otherValues1, otherValues2); + } + + /** + * Test method for {@link HeaderValuesMap#get(Object)}. + */ + @Test + public void testGet() { + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, values2); + assertArrayEquals(new String[]{"value2", "value3"}, map.get("two")); + verify(extractor, values2); + } + + /** + * Test method for {@link HeaderValuesMap#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(map.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link HeaderValuesMap#isEmpty()}. + */ + @Test + public void testIsEmptyTrue() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertTrue(map.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link HeaderValuesMap#keySet()}. + */ + @Test + public void testKeySet() { + replay(extractor); + assertTrue(map.keySet() instanceof KeySet); + verify(extractor); + } + + /** + * Test method for {@link HeaderValuesMap#put(String, String[])}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testPut() { + map.put("one", new String[]{"value1", "value2"}); + } + + /** + * Test method for {@link HeaderValuesMap#putAll(java.util.Map)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testPutAll() { + map.putAll(new HashMap<>()); + } + + /** + * Test method for {@link HeaderValuesMap#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + map.remove("one"); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, map.size()); + verify(extractor, keys); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/KeySetTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/KeySetTest.java new file mode 100644 index 0000000000..452bb51231 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/KeySetTest.java @@ -0,0 +1,283 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link KeySet}. + */ +public class KeySetTest { + + /** + * The extractor to use. + */ + private HasKeys extractor; + + /** + * The key set. + */ + private Set entrySet; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasKeys.class); + entrySet = new KeySet(extractor); + } + + /** + * Tests {@link Set#add(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + entrySet.add(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + entrySet.addAll(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + entrySet.clear(); + } + + /** + * Tests {@link Set#contains(Object)}. + */ + @Test + public void testContains() { + expect(extractor.getValue("one")).andReturn(1); + + replay(extractor); + assertTrue(entrySet.contains("one")); + verify(extractor); + } + + /** + * Tests {@link Set#contains(Object)}. + */ + @Test + public void testContainsFalse() { + expect(extractor.getValue("one")).andReturn(null); + + replay(extractor); + assertFalse(entrySet.contains("one")); + verify(extractor); + } + + @Test + public void testContainsAll() { + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(1); + + replay(extractor); + List coll = new ArrayList(); + coll.add("one"); + coll.add("two"); + assertTrue(entrySet.containsAll(coll)); + verify(extractor); + } + + @Test + public void testContainsAllFalse() { + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(null); + + replay(extractor); + List coll = new ArrayList<>(); + coll.add("one"); + coll.add("two"); + assertFalse(entrySet.containsAll(coll)); + verify(extractor); + } + + /** + * Test method for {@link Set#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(entrySet.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#isEmpty()}. + */ + @Test + public void testIsEmptyTrue() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertTrue(entrySet.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test + public void testIterator() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + replay(extractor, keys, values2); + Iterator entryIt = entrySet.iterator(); + assertTrue(entryIt.hasNext()); + assertEquals("two", entryIt.next()); + verify(extractor, keys, values2); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testIteratorRemove() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + try { + replay(extractor, keys); + entrySet.iterator().remove(); + } finally { + verify(extractor, keys); + } + } + + /** + * Tests {@link Set#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + entrySet.remove(null); + } + + /** + * Tests {@link Set#removeAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + entrySet.removeAll(null); + } + + /** + * Tests {@link Set#retainAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRetainAll() { + entrySet.retainAll(null); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, entrySet.size()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#toArray()}. + */ + @Test + public void testToArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + replay(extractor, keys, values1, values2); + assertArrayEquals(new String[]{"one", "two"}, entrySet.toArray()); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link Set#toArray(Object[])}. + */ + @Test + public void testToArrayTArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + String[] realArray = new String[2]; + assertArrayEquals(new String[]{"one", "two"}, entrySet.toArray(realArray)); + verify(extractor, keys, values1, values2); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryArrayValuesTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryArrayValuesTest.java new file mode 100644 index 0000000000..97045cd104 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryArrayValuesTest.java @@ -0,0 +1,76 @@ +/* + * 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.apache.tiles.request.collection; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +/** + * Tests {@link MapEntryArrayValues}. + */ +public class MapEntryArrayValuesTest { + + /** + * Test method for {@link MapEntryArrayValues#hashCode()}. + */ + @Test + public void testHashCode() { + MapEntryArrayValues entry = new MapEntryArrayValues<>("key", new String[]{"value1", "value2"}, false); + assertEquals("key".hashCode() ^ ("value1".hashCode() + "value2".hashCode()), entry.hashCode()); + entry = new MapEntryArrayValues<>(null, new String[]{"value1", "value2"}, false); + assertEquals(("value1".hashCode() + "value2".hashCode()), entry.hashCode()); + entry = new MapEntryArrayValues<>("key", null, false); + assertEquals("key".hashCode(), entry.hashCode()); + entry = new MapEntryArrayValues<>(null, null, false); + assertEquals(0, entry.hashCode()); + } + + /** + * Test method for {@link MapEntryArrayValues#equals(Object)}. + */ + @Test + public void testEqualsObject() { + MapEntryArrayValues entry = new MapEntryArrayValues<>("key", new String[]{"value1", "value2"}, false); + assertNotEquals(null, entry); + MapEntryArrayValues entry2 = new MapEntryArrayValues<>("key", new String[]{"value1", "value2"}, false); + assertEquals(entry, entry2); + entry2 = new MapEntryArrayValues<>("key", null, false); + assertNotEquals(entry, entry2); + entry2 = new MapEntryArrayValues<>("key2", new String[]{"value1", "value2"}, false); + assertNotEquals(entry, entry2); + entry2 = new MapEntryArrayValues<>("key", new String[]{"value1", "value3"}, false); + assertNotEquals(entry, entry2); + entry = new MapEntryArrayValues<>(null, new String[]{"value1", "value2"}, false); + entry2 = new MapEntryArrayValues<>(null, new String[]{"value1", "value2"}, false); + assertEquals(entry, entry2); + entry = new MapEntryArrayValues<>("key", null, false); + entry2 = new MapEntryArrayValues<>("key", null, false); + assertEquals(entry, entry2); + entry2 = new MapEntryArrayValues<>("key", new String[]{"value1", "value2"}, false); + assertNotEquals(entry, entry2); + entry = new MapEntryArrayValues<>(null, new String[]{null, "value2"}, false); + entry2 = new MapEntryArrayValues<>(null, new String[]{null, "value2"}, false); + assertEquals(entry, entry2); + entry2 = new MapEntryArrayValues<>(null, new String[]{"value1", "value2"}, false); + assertNotEquals(entry, entry2); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryTest.java new file mode 100644 index 0000000000..31406b0570 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryTest.java @@ -0,0 +1,106 @@ +/* + * 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.apache.tiles.request.collection; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +/** + * Tests {@link MapEntry}. + */ +public class MapEntryTest { + + /** + * Test method for {@link MapEntry#hashCode()}. + */ + @Test + public void testHashCode() { + MapEntry entry = new MapEntry<>("key", "value", false); + assertEquals("key".hashCode() ^ "value".hashCode(), entry.hashCode()); + entry = new MapEntry<>(null, "value", false); + assertEquals("value".hashCode(), entry.hashCode()); + entry = new MapEntry<>("key", null, false); + assertEquals("key".hashCode(), entry.hashCode()); + entry = new MapEntry<>(null, null, false); + assertEquals(0, entry.hashCode()); + } + + /** + * Test method for {@link MapEntry#getKey()}. + */ + @Test + public void testGetKey() { + MapEntry entry = new MapEntry<>("key", "value", false); + assertEquals("key", entry.getKey()); + } + + /** + * Test method for {@link MapEntry#getValue()}. + */ + @Test + public void testGetValue() { + MapEntry entry = new MapEntry<>("key", "value", false); + assertEquals("value", entry.getValue()); + } + + /** + * Test method for {@link MapEntry#setValue(Object)}. + */ + @Test + public void testSetValue() { + MapEntry entry = new MapEntry<>("key", "value", true); + assertEquals("value", entry.getValue()); + entry.setValue("value2"); + assertEquals("value2", entry.getValue()); + } + + /** + * Test method for {@link MapEntry#setValue(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testSetValueException() { + MapEntry entry = new MapEntry<>("key", "value", false); + assertEquals("value", entry.getValue()); + entry.setValue("value2"); + } + + /** + * Test method for {@link MapEntry#equals(Object)}. + */ + @Test + public void testEqualsObject() { + MapEntry entry = new MapEntry<>("key", "value", false); + assertNotEquals(null, entry); + MapEntry entry2 = new MapEntry<>("key", "value", false); + assertEquals(entry, entry2); + entry2 = new MapEntry<>("key2", "value", false); + assertNotEquals(entry, entry2); + entry2 = new MapEntry<>("key", "value2", false); + assertNotEquals(entry, entry2); + entry = new MapEntry<>(null, "value", false); + entry2 = new MapEntry<>(null, "value", false); + assertEquals(entry, entry2); + entry = new MapEntry<>("key", null, false); + entry2 = new MapEntry<>("key", null, false); + assertEquals(entry, entry2); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapEntrySetTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapEntrySetTest.java new file mode 100644 index 0000000000..ad44d03796 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapEntrySetTest.java @@ -0,0 +1,294 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ReadOnlyEnumerationMap#entrySet()}. + */ +public class ReadOnlyEnumerationMapEntrySetTest { + + /** + * The extractor to use. + */ + private HasKeys extractor; + + /** + * The set to test. + */ + private Set> entrySet; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasKeys.class); + ReadOnlyEnumerationMap map = new ReadOnlyEnumerationMap<>(extractor); + entrySet = map.entrySet(); + } + + /** + * Tests {@link Set#add(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + entrySet.add(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + entrySet.addAll(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + entrySet.clear(); + } + + /** + * Tests {@link Set#contains(Object)}. + */ + @Test + public void testContains() { + Map.Entry entry = createMock(Map.Entry.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(entry.getKey()).andReturn("two"); + expect(entry.getValue()).andReturn(2); + + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, entry, values2); + assertTrue(entrySet.contains(entry)); + verify(extractor, entry, values2); + } + + @Test + public void testContainsAll() { + Map.Entry entry1 = createMock(Map.Entry.class); + Map.Entry entry2 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn(1); + expect(entry2.getKey()).andReturn("two"); + expect(entry2.getValue()).andReturn(2); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, entry1, entry2); + List> coll = new ArrayList<>(); + coll.add(entry1); + coll.add(entry2); + assertTrue(entrySet.containsAll(coll)); + verify(extractor, entry1, entry2); + } + + @Test + public void testContainsAllFalse() { + Map.Entry entry1 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn("value4"); + + expect(extractor.getValue("one")).andReturn(1); + + replay(extractor, entry1); + List> coll = new ArrayList<>(); + coll.add(entry1); + assertFalse(entrySet.containsAll(coll)); + verify(extractor, entry1); + } + + /** + * Test method for {@link Set#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(entrySet.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test + public void testIterator() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + Iterator> entryIt = entrySet.iterator(); + assertTrue(entryIt.hasNext()); + MapEntry entry = new MapEntry<>("two", 2, false); + assertEquals(entry, entryIt.next()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testIteratorRemove() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + try { + replay(extractor, keys); + entrySet.iterator().remove(); + } finally { + verify(extractor, keys); + } + } + + /** + * Tests {@link Set#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + entrySet.remove(null); + } + + /** + * Tests {@link Set#removeAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + entrySet.removeAll(null); + } + + /** + * Tests {@link Set#retainAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRetainAll() { + entrySet.retainAll(null); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, entrySet.size()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#toArray()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testToArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + MapEntry[] entryArray = new MapEntry[2]; + entryArray[0] = new MapEntry<>("one", 1, false); + entryArray[1] = new MapEntry<>("two", 2, false); + + replay(extractor, keys, values1, values2); + assertArrayEquals(entryArray, entrySet.toArray()); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link Set#toArray(Object[])}. + */ + @SuppressWarnings("unchecked") + @Test + public void testToArrayTArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + MapEntry[] entryArray = new MapEntry[2]; + entryArray[0] = new MapEntry<>("one", 1, false); + entryArray[1] = new MapEntry<>("two", 2, false); + + replay(extractor, keys, values1, values2); + MapEntry[] realArray = new MapEntry[2]; + assertArrayEquals(entryArray, entrySet.toArray(realArray)); + verify(extractor, keys, values1, values2); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapTest.java new file mode 100644 index 0000000000..be32456913 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapTest.java @@ -0,0 +1,306 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.Enumeration; +import java.util.HashMap; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ReadOnlyEnumerationMap}. + */ +public class ReadOnlyEnumerationMapTest { + + /** + * The extractor to use. + */ + private HasKeys extractor; + + /** + * The map to test. + */ + private ReadOnlyEnumerationMap map; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasKeys.class); + map = new ReadOnlyEnumerationMap<>(extractor); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#clear()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + map.clear(); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#containsKey(Object)}. + */ + @Test + public void testContainsKey() { + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(null); + + replay(extractor); + assertTrue(map.containsKey("one")); + assertFalse(map.containsKey("two")); + verify(extractor); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#containsValue(Object)}. + */ + @Test + public void testContainsValue() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + assertTrue(map.containsValue(2)); + verify(extractor, keys); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#containsValue(Object)}. + */ + @Test + public void testContainsValueFalse() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(1); + + replay(extractor, keys); + assertFalse(map.containsValue(3)); + verify(extractor, keys); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#get(Object)}. + */ + @Test + public void testGet() { + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor); + assertEquals(new Integer(2), map.get("two")); + verify(extractor); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(map.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#isEmpty()}. + */ + @Test + public void testIsEmptyTrue() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertTrue(map.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#keySet()}. + */ + @Test + public void testKeySet() { + replay(extractor); + assertTrue(map.keySet() instanceof KeySet); + verify(extractor); + } + + @Test(expected = UnsupportedOperationException.class) + public void testPut() { + map.put("one", 1); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#putAll(java.util.Map)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testPutAll() { + map.putAll(new HashMap<>()); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + map.remove("one"); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, map.size()); + verify(extractor, keys); + } + + @Test + public void testHashCode() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("first"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("second"); + expect(keys.hasMoreElements()).andReturn(false); + + Integer value1 = 1; + + expect(extractor.getValue("first")).andReturn(value1); + expect(extractor.getValue("second")).andReturn(null); + + replay(extractor, keys); + assertEquals(("first".hashCode() ^ value1.hashCode()) + ("second".hashCode()), map.hashCode()); + verify(extractor, keys); + } + + @Test + public void testEqualsObject() { + HasKeys otherRequest = createMock(HasKeys.class); + ReadOnlyEnumerationMap otherMap = createMockBuilder(ReadOnlyEnumerationMap.class).withConstructor(otherRequest).createMock(); + Enumeration keys = createMock(Enumeration.class); + Enumeration otherKeys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(otherRequest.getKeys()).andReturn(otherKeys); + + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("first"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("second"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("first")).andReturn(1); + expect(extractor.getValue("second")).andReturn(2); + + expect(otherKeys.hasMoreElements()).andReturn(true); + expect(otherKeys.nextElement()).andReturn("first"); + expect(otherKeys.hasMoreElements()).andReturn(true); + expect(otherKeys.nextElement()).andReturn("second"); + expect(otherKeys.hasMoreElements()).andReturn(false); + + expect(otherRequest.getValue("first")).andReturn(1); + expect(otherRequest.getValue("second")).andReturn(2); + + replay(extractor, otherRequest, otherMap, keys, otherKeys); + assertEquals(map, otherMap); + verify(extractor, otherRequest, otherMap, keys, otherKeys); + } + + @Test + public void testEqualsObjectFalse() { + HasKeys otherRequest = createMock(HasKeys.class); + ReadOnlyEnumerationMap otherMap = createMockBuilder(ReadOnlyEnumerationMap.class).withConstructor(otherRequest).createMock(); + Enumeration keys = createMock(Enumeration.class); + Enumeration otherKeys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(otherRequest.getKeys()).andReturn(otherKeys); + + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("first"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("second"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("first")).andReturn(1); + expect(extractor.getValue("second")).andReturn(2); + + expect(otherKeys.hasMoreElements()).andReturn(true); + expect(otherKeys.nextElement()).andReturn("first"); + expect(otherKeys.hasMoreElements()).andReturn(true); + expect(otherKeys.nextElement()).andReturn("second"); + expect(otherKeys.hasMoreElements()).andReturn(false); + + expect(otherRequest.getValue("first")).andReturn(1); + expect(otherRequest.getValue("second")).andReturn(3); + + replay(extractor, otherRequest, otherMap, keys, otherKeys); + assertNotEquals(map, otherMap); + verify(extractor, otherRequest, otherMap, keys, otherKeys); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapValuesCollectionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapValuesCollectionTest.java new file mode 100644 index 0000000000..b37dbdc037 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapValuesCollectionTest.java @@ -0,0 +1,312 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ReadOnlyEnumerationMap#values()}. + */ +public class ReadOnlyEnumerationMapValuesCollectionTest { + + /** + * The extractor to use. + */ + private HasKeys extractor; + + /** + * The collection to test. + */ + private Collection coll; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasKeys.class); + ReadOnlyEnumerationMap map = new ReadOnlyEnumerationMap<>(extractor); + coll = map.values(); + } + + /** + * Tests {@link Collection#add(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + coll.add(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + coll.addAll(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + coll.clear(); + } + + /** + * Tests {@link Collection#contains(Object)}. + */ + @Test + public void testContainsValue() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + assertTrue(coll.contains(2)); + verify(extractor, keys); + } + + /** + * Tests {@link Collection#contains(Object)}. + */ + @Test + public void testContainsValueFalse() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + assertFalse(coll.contains(3)); + verify(extractor, keys); + } + + @Test + public void testContainsAll() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + List coll = new ArrayList<>(); + coll.add(1); + coll.add(2); + assertTrue(this.coll.containsAll(coll)); + verify(extractor, keys); + } + + @Test + public void testContainsAllFalse() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + List coll = new ArrayList<>(); + coll.add(3); + assertFalse(this.coll.containsAll(coll)); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(coll.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#iterator()}. + */ + @Test + public void testIterator() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + Iterator entryIt = coll.iterator(); + assertTrue(entryIt.hasNext()); + assertEquals(new Integer(2), entryIt.next()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#iterator()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testIteratorRemove() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + try { + replay(extractor, keys); + coll.iterator().remove(); + } finally { + verify(extractor, keys); + } + } + + /** + * Tests {@link Collection#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + coll.remove(null); + } + + /** + * Tests {@link Collection#removeAll(Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + coll.removeAll(null); + } + + /** + * Tests {@link Collection#retainAll(Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRetainAll() { + coll.retainAll(null); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, coll.size()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#toArray()}. + */ + @Test + public void testToArray() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + Integer[] entryArray = new Integer[]{1, 2}; + + replay(extractor, keys); + assertArrayEquals(entryArray, coll.toArray()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#toArray(Object[])}. + */ + @Test + public void testToArrayTArray() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + Integer[] entryArray = new Integer[]{1, 2}; + + replay(extractor, keys); + Integer[] realArray = new Integer[2]; + assertArrayEquals(entryArray, coll.toArray(realArray)); + verify(extractor, keys); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/RemovableKeySetTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/RemovableKeySetTest.java new file mode 100644 index 0000000000..e60b02ed6b --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/RemovableKeySetTest.java @@ -0,0 +1,129 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasRemovableKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link RemovableKeySet}. + */ +public class RemovableKeySetTest { + + /** + * The extractor to use. + */ + private HasRemovableKeys extractor; + + /** + * The key set to test. + */ + private RemovableKeySet entrySet; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasRemovableKeys.class); + entrySet = new RemovableKeySet(extractor); + } + + /** + * Test method for {@link RemovableKeySet#remove(Object)}. + */ + @Test + public void testRemove() { + expect(extractor.getValue("one")).andReturn(1); + extractor.removeValue("one"); + + replay(extractor); + assertTrue(entrySet.remove("one")); + verify(extractor); + } + + /** + * Test method for {@link RemovableKeySet#remove(Object)}. + */ + @Test + public void testRemoveNoEffect() { + expect(extractor.getValue("one")).andReturn(null); + + replay(extractor); + assertFalse(entrySet.remove("one")); + verify(extractor); + } + + /** + * Test method for {@link RemovableKeySet#removeAll(java.util.Collection)}. + */ + @Test + public void testRemoveAll() { + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + extractor.removeValue("one"); + extractor.removeValue("two"); + + replay(extractor); + List coll = new ArrayList<>(); + coll.add("one"); + coll.add("two"); + assertTrue(entrySet.removeAll(coll)); + verify(extractor); + } + + /** + * Test method for {@link RemovableKeySet#retainAll(java.util.Collection)}. + */ + @Test + public void testRetainAll() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("three"); + expect(keys.hasMoreElements()).andReturn(false); + + extractor.removeValue("three"); + + replay(extractor, keys); + List coll = new ArrayList<>(); + coll.add("one"); + coll.add("two"); + assertTrue(entrySet.retainAll(coll)); + verify(extractor, keys); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapEntrySetTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapEntrySetTest.java new file mode 100644 index 0000000000..c8ceea4379 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapEntrySetTest.java @@ -0,0 +1,234 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.AttributeExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ScopeMap#entrySet()}. + */ +public class ScopeMapEntrySetTest { + + /** + * The extractor to use. + */ + private AttributeExtractor extractor; + + /** + * The entry set to test. + */ + private Set> entrySet; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(AttributeExtractor.class); + ScopeMap map = new ScopeMap(extractor); + entrySet = map.entrySet(); + } + + /** + * Tests {@link Set#add(Object)}. + */ + @Test + public void testAdd() { + Map.Entry entry = createMock(Map.Entry.class); + + expect(entry.getKey()).andReturn("one"); + expect(entry.getValue()).andReturn(1); + expect(extractor.getValue("one")).andReturn(null); + + extractor.setValue("one", 1); + + replay(extractor, entry); + assertTrue(entrySet.add(entry)); + verify(extractor, entry); + } + + /** + * Tests {@link Set#add(Object)}. + */ + @Test + public void testAddNoEffect() { + Map.Entry entry = createMock(Map.Entry.class); + + expect(entry.getKey()).andReturn("one"); + expect(entry.getValue()).andReturn(1); + expect(extractor.getValue("one")).andReturn(1); + + replay(extractor, entry); + assertFalse(entrySet.add(entry)); + verify(extractor, entry); + } + + /** + * Tests {@link Set#addAll(java.util.Collection)}. + */ + @Test + public void testAddAll() { + Map.Entry entry1 = createMock(Map.Entry.class); + Map.Entry entry2 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn(1); + expect(entry2.getKey()).andReturn("two"); + expect(entry2.getValue()).andReturn(2); + expect(extractor.getValue("one")).andReturn(null); + expect(extractor.getValue("two")).andReturn(null); + + extractor.setValue("one", 1); + extractor.setValue("two", 2); + + replay(extractor, entry1, entry2); + List> coll = new ArrayList<>(); + coll.add(entry1); + coll.add(entry2); + assertTrue(entrySet.addAll(coll)); + verify(extractor, entry1, entry2); + } + + /** + * Test method for {@link ScopeMap#clear()}. + */ + @Test + public void testClear() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + extractor.removeValue("one"); + extractor.removeValue("two"); + + replay(extractor, keys); + entrySet.clear(); + verify(extractor, keys); + } + + /** + * Tests {@link Set#remove(Object)}. + */ + @Test + public void testRemove() { + Map.Entry entry = createMock(Map.Entry.class); + + expect(entry.getKey()).andReturn("one"); + expect(entry.getValue()).andReturn(1); + expect(extractor.getValue("one")).andReturn(1); + extractor.removeValue("one"); + + replay(extractor, entry); + assertTrue(entrySet.remove(entry)); + verify(extractor, entry); + } + + /** + * Tests {@link Set#remove(Object)}. + */ + @Test + public void testRemoveNoEffect() { + Map.Entry entry = createMock(Map.Entry.class); + + expect(entry.getKey()).andReturn("one"); + expect(extractor.getValue("one")).andReturn(null); + + replay(extractor, entry); + assertFalse(entrySet.remove(entry)); + verify(extractor, entry); + } + + /** + * Tests {@link Set#addAll(java.util.Collection)}. + */ + @Test + public void testRemoveAll() { + Map.Entry entry1 = createMock(Map.Entry.class); + Map.Entry entry2 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn(1); + expect(entry2.getKey()).andReturn("two"); + expect(entry2.getValue()).andReturn(2); + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + extractor.removeValue("one"); + extractor.removeValue("two"); + + replay(extractor, entry1, entry2); + List> coll = new ArrayList<>(); + coll.add(entry1); + coll.add(entry2); + assertTrue(entrySet.removeAll(coll)); + verify(extractor, entry1, entry2); + } + + /** + * Tests {@link Set#addAll(java.util.Collection)}. + */ + @Test + public void testRetainAll() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("three"); + expect(keys.hasMoreElements()).andReturn(false); + + Map.Entry entry1 = new MapEntry<>("one", 1, false); + Map.Entry entry2 = new MapEntry<>("two", 2, false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(3); + expect(extractor.getValue("three")).andReturn(4); + extractor.removeValue("two"); + extractor.removeValue("three"); + + replay(extractor, keys); + List> coll = new ArrayList<>(); + coll.add(entry1); + coll.add(entry2); + assertTrue(entrySet.retainAll(coll)); + verify(extractor, keys); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapTest.java new file mode 100644 index 0000000000..09853bcaef --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapTest.java @@ -0,0 +1,135 @@ +/* + * 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.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.AttributeExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ScopeMap}. + */ +public class ScopeMapTest { + + /** + * The map tot est. + */ + private ScopeMap map; + + /** + * The extractor to use. + */ + private AttributeExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(AttributeExtractor.class); + map = new ScopeMap(extractor); + } + + /** + * Test method for {@link ScopeMap#clear()}. + */ + @Test + public void testClear() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + extractor.removeValue("one"); + extractor.removeValue("two"); + + replay(extractor, keys); + map.clear(); + verify(extractor, keys); + } + + /** + * Test method for {@link ScopeMap#keySet()}. + */ + @Test + public void testKeySet() { + replay(extractor); + assertTrue(map.keySet() instanceof RemovableKeySet); + verify(extractor); + } + + /** + * Test method for {@link ScopeMap#put(String, Object)}. + */ + @Test + public void testPutStringObject() { + expect(extractor.getValue("one")).andReturn(null); + extractor.setValue("one", 1); + + replay(extractor); + assertNull(map.put("one", 1)); + verify(extractor); + } + + /** + * Test method for {@link ScopeMap#putAll(Map)}. + */ + @Test + public void testPutAllMapOfQextendsStringQextendsObject() { + Map items = new LinkedHashMap<>(); + items.put("one", 1); + items.put("two", 2); + + extractor.setValue("one", 1); + extractor.setValue("two", 2); + + replay(extractor); + map.putAll(items); + verify(extractor); + } + + /** + * Test method for {@link ScopeMap#remove(Object)}. + */ + @Test + public void testRemoveObject() { + expect(extractor.getValue("one")).andReturn(1); + extractor.removeValue("one"); + + replay(extractor); + assertEquals(1, map.remove("one")); + verify(extractor); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/locale/LocaleUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/LocaleUtilTest.java new file mode 100644 index 0000000000..202a68c481 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/LocaleUtilTest.java @@ -0,0 +1,42 @@ +/* + * 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.apache.tiles.request.locale; + +import junit.framework.TestCase; + +import java.util.Locale; + +/** + * Tests {@link LocaleUtil}. + */ +public class LocaleUtilTest extends TestCase { + + /** + * Test method for {@link LocaleUtil#getParentLocale(Locale)}. + */ + public void testGetParentLocale() { + assertNull("The parent locale of NULL_LOCALE is not correct", LocaleUtil.getParentLocale(Locale.ROOT)); + assertEquals("The parent locale of 'en' is not correct", Locale.ROOT, LocaleUtil.getParentLocale(Locale.ENGLISH)); + assertEquals("The parent locale of 'en_US' is not correct", Locale.ENGLISH, LocaleUtil.getParentLocale(Locale.US)); + Locale locale = new Locale("es", "ES", "Traditional_WIN"); + Locale parentLocale = new Locale("es", "ES"); + assertEquals("The parent locale of 'es_ES_Traditional_WIN' is not correct", parentLocale, LocaleUtil.getParentLocale(locale)); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java new file mode 100644 index 0000000000..48bd0a21bb --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java @@ -0,0 +1,131 @@ +/* + * 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.apache.tiles.request.locale; + +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; + +/** + * Tests PostfixedApplicationResource. + */ +public class PostfixedApplicationResourceTest { + + private static class TestApplicationResource extends PostfixedApplicationResource { + public TestApplicationResource(String path, Locale locale) { + super(path, locale); + } + + public TestApplicationResource(String localePath) { + super(localePath); + } + + @Override + public InputStream getInputStream() throws IOException { + return null; + } + + @Override + public long getLastModified() throws IOException { + return 0; + } + + } + + /** + * Test getLocalePath(String path, Locale locale). + */ + @Test + public void testGetLocalePath() { + TestApplicationResource resource = new TestApplicationResource("/my test/path_fr.html"); + assertEquals("/my test/path.html", resource.getLocalePath(null)); + assertEquals("/my test/path.html", resource.getLocalePath(Locale.ROOT)); + assertEquals("/my test/path_it.html", resource.getLocalePath(Locale.ITALIAN)); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath(Locale.ITALY)); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath(new Locale("en", "GB", "scotland"))); + } + + @Test + public void testBuildFromString() { + TestApplicationResource resource = new TestApplicationResource("/my test/path_en_GB_scotland.html"); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en", "GB", "scotland"), resource.getLocale()); + resource = new TestApplicationResource("/my test/path_it_IT.html"); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALY, resource.getLocale()); + resource = new TestApplicationResource("/my test/path_it.html"); + assertEquals("/my test/path_it.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALIAN, resource.getLocale()); + resource = new TestApplicationResource("/my test/path.html"); + assertEquals("/my test/path.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new TestApplicationResource("/my test/path_zz.html"); + assertEquals("/my test/path_zz.html", resource.getLocalePath()); + assertEquals("/my test/path_zz.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new TestApplicationResource("/my test/path_en_ZZ.html"); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + resource = new TestApplicationResource("/my test/path_tiles.html"); + assertEquals("/my test/path_tiles.html", resource.getLocalePath()); + assertEquals("/my test/path_tiles.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new TestApplicationResource("/my test/path_longwordthatbreaksISO639.html"); + assertEquals("/my test/path_longwordthatbreaksISO639.html", resource.getLocalePath()); + assertEquals("/my test/path_longwordthatbreaksISO639.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new TestApplicationResource("/my test/path_en_tiles.html"); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + resource = new TestApplicationResource("/my test/path_en_longwordthatbreaksISO3166.html"); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + } + + @Test + public void testBuildFromStringAndLocale() { + TestApplicationResource resource = new TestApplicationResource("/my test/path.html", new Locale("en", "GB", "scotland")); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en", "GB", "scotland"), resource.getLocale()); + resource = new TestApplicationResource("/my test/path.html", Locale.ITALY); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALY, resource.getLocale()); + resource = new TestApplicationResource("/my test/path.html", Locale.ITALIAN); + assertEquals("/my test/path_it.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALIAN, resource.getLocale()); + resource = new TestApplicationResource("/my test/path.html", Locale.ROOT); + assertEquals("/my test/path.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java new file mode 100644 index 0000000000..964ca1b739 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java @@ -0,0 +1,201 @@ +/* + * 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.apache.tiles.request.locale; + +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; +import java.util.Locale; + +import static java.lang.System.setProperty; +import static java.lang.reflect.Modifier.FINAL; +import static org.apache.tiles.request.locale.URLApplicationResource.REMOTE_PROTOCOLS_PROPERTY; +import static org.apache.tiles.request.locale.URLApplicationResource.initRemoteProtocols; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests URLApplicationResource. + */ +public class URLApplicationResourceTest { + + private static final String EXPECTED_MESSAGE = "aMessage"; + + private static class TestUrlStreamHandler extends URLStreamHandler { + + @Override + protected URLConnection openConnection(final URL u) throws IOException { + throw new IOException(EXPECTED_MESSAGE); + } + } + + private static class TestURLStreamHandlerFactory implements URLStreamHandlerFactory { + + @Override + public URLStreamHandler createURLStreamHandler(final String protocol) { + if ("test1".equals(protocol) || "test2".equals(protocol)) { + return new TestUrlStreamHandler(); + } + return null; + } + } + + @BeforeClass + public static void setURLStreamHandlerFactory() { + URL.setURLStreamHandlerFactory(new TestURLStreamHandlerFactory()); + } + + @After + public void tearDown() { + setProperty(REMOTE_PROTOCOLS_PROPERTY, ""); + } + + /** + * Test getLocalePath(String path, Locale locale). + */ + @Test + public void testGetLocalePath() throws MalformedURLException { + URLApplicationResource resource = new URLApplicationResource("/my test/path_fr.html", new URL("file:///")); + assertEquals("/my test/path.html", resource.getLocalePath(null)); + assertEquals("/my test/path.html", resource.getLocalePath(Locale.ROOT)); + assertEquals("/my test/path_it.html", resource.getLocalePath(Locale.ITALIAN)); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath(Locale.ITALY)); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath(new Locale("en", "GB", "scotland"))); + } + + @Test + public void testBuildFromString() throws MalformedURLException { + URLApplicationResource resource = new URLApplicationResource("/my test/path_en_GB_scotland.html", new URL("file:///")); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en", "GB", "scotland"), resource.getLocale()); + resource = new URLApplicationResource("/my test/path_it_IT.html", new URL("file:///")); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALY, resource.getLocale()); + resource = new URLApplicationResource("/my test/path_it.html", new URL("file:///")); + assertEquals("/my test/path_it.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALIAN, resource.getLocale()); + resource = new URLApplicationResource("/my test/path.html", new URL("file:///")); + assertEquals("/my test/path.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new URLApplicationResource("/my test/path_zz.html", new URL("file:///")); + assertEquals("/my test/path_zz.html", resource.getLocalePath()); + assertEquals("/my test/path_zz.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new URLApplicationResource("/my test/path_en_ZZ.html", new URL("file:///")); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + resource = new URLApplicationResource("/my test/path_tiles.html", new URL("file:///")); + assertEquals("/my test/path_tiles.html", resource.getLocalePath()); + assertEquals("/my test/path_tiles.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new URLApplicationResource("/my test/path_longwordthatbreaksISO639.html", new URL("file:///")); + assertEquals("/my test/path_longwordthatbreaksISO639.html", resource.getLocalePath()); + assertEquals("/my test/path_longwordthatbreaksISO639.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new URLApplicationResource("/my test/path_en_tiles.html", new URL("file:///")); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + resource = new URLApplicationResource("/my test/path_en_longwordthatbreaksISO3166.html", new URL("file:///")); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + } + + @Test + public void testBuildFromStringAndLocale() throws MalformedURLException { + URLApplicationResource resource = new URLApplicationResource("/my test/path.html", new Locale("en", "GB", "scotland"), new URL("file:///")); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en", "GB", "scotland"), resource.getLocale()); + resource = new URLApplicationResource("/my test/path.html", Locale.ITALY, new URL("file:///")); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALY, resource.getLocale()); + resource = new URLApplicationResource("/my test/path.html", Locale.ITALIAN, new URL("file:///")); + assertEquals("/my test/path_it.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALIAN, resource.getLocale()); + resource = new URLApplicationResource("/my test/path.html", Locale.ROOT, new URL("file:///")); + assertEquals("/my test/path.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + } + + @Test + public void testGetLastModified() throws IOException { + URL url = getClass().getClassLoader().getResource("org/apache/tiles/request/locale/resource.txt"); + assertNotNull(url); + URLApplicationResource resource = new URLApplicationResource("org/apache/tiles/request/locale/resource.txt", url); + assertTrue(resource.getLastModified() > 0); + } + + @Test + public void testGetLastModifiedWithSpace() throws IOException { + URL url = getClass().getClassLoader().getResource("org/apache/tiles/request/locale/resource with space.txt"); + assertNotNull(url); + URLApplicationResource resource = new URLApplicationResource("org/apache/tiles/request/locale/resource with space.txt", url); + assertTrue(resource.getLastModified() > 0); + } + + @Test + public void testGetInputStream() throws IOException { + URL url = getClass().getClassLoader().getResource("org/apache/tiles/request/locale/resource.txt"); + assertNotNull(url); + URLApplicationResource resource = new URLApplicationResource("org/apache/tiles/request/locale/resource.txt", url); + InputStream is = resource.getInputStream(); + assertNotNull(is); + is.close(); + } + + @Test + public void testGetInputStreamWithSpace() throws IOException { + URL url = getClass().getClassLoader().getResource("org/apache/tiles/request/locale/resource with space.txt"); + assertNotNull(url); + URLApplicationResource resource = new URLApplicationResource("org/apache/tiles/request/locale/resource with space.txt", url); + InputStream is = resource.getInputStream(); + assertNotNull(is); + is.close(); + } + + @Test(expected = FileNotFoundException.class) + public void testLocalProtocol() throws IOException { + URL url = new URL("file://foo/bar.txt"); + URLApplicationResource resource = new URLApplicationResource("org/apache/tiles/request/locale/resource.txt", url); + resource.getInputStream(); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/CannotInstantiateObjectExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/CannotInstantiateObjectExceptionTest.java new file mode 100644 index 0000000000..b170ca4e78 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/CannotInstantiateObjectExceptionTest.java @@ -0,0 +1,41 @@ +/* + * 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.apache.tiles.request.reflect; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link CannotInstantiateObjectException}. + */ +public class CannotInstantiateObjectExceptionTest { + + /** + * Test method for {@link CannotInstantiateObjectException#CannotInstantiateObjectException(String, Throwable)}. + */ + @Test + public void testCannotInstantiateObjectExceptionStringThrowable() { + Throwable cause = new Throwable(); + CannotInstantiateObjectException exception = new CannotInstantiateObjectException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/ClassUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/ClassUtilTest.java new file mode 100644 index 0000000000..db01a2414f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/ClassUtilTest.java @@ -0,0 +1,175 @@ +/* + * 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.apache.tiles.request.reflect; + +import org.junit.Test; + +import java.beans.PropertyDescriptor; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link ClassUtil}. + */ +public class ClassUtilTest { + + /** + * The size of descriptor map. + */ + private static final int MAP_SIZE = 3; + + /** + * Test method for {@link ClassUtil#collectBeanInfo(Class, Map)}. + */ + @Test + public void testCollectBeanInfo() { + Map name2descriptor = new HashMap<>(); + ClassUtil.collectBeanInfo(TestInterface.class, name2descriptor); + assertEquals(MAP_SIZE, name2descriptor.size()); + PropertyDescriptor descriptor = name2descriptor.get("value"); + assertEquals("value", descriptor.getName()); + assertEquals(int.class, descriptor.getPropertyType()); + assertNotNull(descriptor.getReadMethod()); + assertNotNull(descriptor.getWriteMethod()); + descriptor = name2descriptor.get("value2"); + assertEquals("value2", descriptor.getName()); + assertEquals(long.class, descriptor.getPropertyType()); + assertNotNull(descriptor.getReadMethod()); + assertNull(descriptor.getWriteMethod()); + descriptor = name2descriptor.get("value3"); + assertEquals("value3", descriptor.getName()); + assertEquals(String.class, descriptor.getPropertyType()); + assertNull(descriptor.getReadMethod()); + assertNotNull(descriptor.getWriteMethod()); + } + + /** + * Test method for {@link ClassUtil#getClass(String, Class)}. + * @throws ClassNotFoundException If something goes wrong. + */ + @Test + public void testGetClass() throws ClassNotFoundException { + assertEquals(TestInterface.class, ClassUtil.getClass( + TestInterface.class.getName(), Object.class)); + } + + /** + * Test method for {@link ClassUtil#getClass(String, Class)}. + * @throws ClassNotFoundException If something goes wrong. + */ + @Test(expected = ClassNotFoundException.class) + public void testGetClassException() throws ClassNotFoundException { + ClassUtil.getClass("this.class.does.not.Exist", Object.class); + } + + /** + * Test method for {@link ClassUtil#instantiate(String, boolean)}. + */ + @Test + public void testInstantiate() { + assertNotNull(ClassUtil.instantiate(TestClass.class.getName(), true)); + assertNull(ClassUtil.instantiate("this.class.does.not.Exist", true)); + } + + /** + * Test method for {@link ClassUtil#instantiate(String, boolean)}. + */ + @Test + public void testInstantiateOneParameter() { + assertNotNull(ClassUtil.instantiate(TestClass.class.getName())); + } + + /** + * Test method for {@link ClassUtil#instantiate(String)}. + */ + @Test(expected = CannotInstantiateObjectException.class) + public void testInstantiateOneParameterException() { + assertNotNull(ClassUtil.instantiate("this.class.does.not.Exist")); + } + + /** + * Test method for {@link ClassUtil#instantiate(String)}. + */ + @Test(expected = CannotInstantiateObjectException.class) + public void testInstantiateInstantiationException() { + ClassUtil.instantiate(TestInterface.class.getName()); + } + + /** + * Test method for {@link ClassUtil#instantiate(String)}. + */ + @Test(expected = CannotInstantiateObjectException.class) + public void testInstantiateIllegalAccessException() { + ClassUtil.instantiate(TestPrivateClass.class.getName()); + } + + /** + * Interface to be used as test. + * + * @version $Rev$ $Date$ + */ + public interface TestInterface { + + /** + * The value. + * + * @return The value. + */ + int getValue(); + + /** + * The value. + * + * @param value The value. + */ + void setValue(int value); + + /** + * The value. + * + * @return The value. + */ + long getValue2(); + + /** + * The value. + * + * @param value3 The value. + */ + @SuppressWarnings("unused") + void setValue3(String value3); + } + + /** + * A test static class. + */ + public static class TestClass { + } + + /** + * A test static private class. + */ + private static class TestPrivateClass { + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/render/BasicRendererFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/render/BasicRendererFactoryTest.java new file mode 100644 index 0000000000..c133b4cb20 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/render/BasicRendererFactoryTest.java @@ -0,0 +1,100 @@ +/* + * 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.apache.tiles.request.render; + +import org.apache.tiles.request.ApplicationContext; +import org.junit.Before; +import org.junit.Test; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertSame; + +/** + * Basic renderer factory implementation. + */ +public class BasicRendererFactoryTest { + + /** + * The renderer factory. + */ + private BasicRendererFactory rendererFactory; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + rendererFactory = new BasicRendererFactory(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + replay(applicationContext); + } + + /** + * Tests execution and + * {@link BasicRendererFactory#getRenderer(String)}. + */ + @Test + public void testInitAndGetRenderer() { + Renderer renderer1 = createMock(Renderer.class); + Renderer renderer2 = createMock(Renderer.class); + Renderer renderer3 = createMock(Renderer.class); + Renderer renderer4 = createMock(Renderer.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + replay(renderer1, renderer2, renderer3, renderer4, applicationContext); + rendererFactory.registerRenderer("string", renderer1); + rendererFactory.registerRenderer("test", renderer2); + rendererFactory.registerRenderer("test2", renderer3); + rendererFactory.setDefaultRenderer(renderer4); + Renderer renderer = rendererFactory.getRenderer("string"); + assertSame(renderer1, renderer); + renderer = rendererFactory.getRenderer("test"); + assertSame(renderer2, renderer); + renderer = rendererFactory.getRenderer("test2"); + assertSame(renderer3, renderer); + renderer = rendererFactory.getRenderer(null); + assertSame(renderer4, renderer); + verify(renderer1, renderer2, renderer3, renderer4, applicationContext); + } + + /** + * Tests execution and + * {@link BasicRendererFactory#getRenderer(String)}. + */ + @Test(expected = NoSuchRendererException.class) + public void testGetRendererException() { + Renderer renderer1 = createMock(Renderer.class); + Renderer renderer2 = createMock(Renderer.class); + Renderer renderer3 = createMock(Renderer.class); + Renderer renderer4 = createMock(Renderer.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + replay(renderer1, renderer2, renderer3, renderer4, applicationContext); + rendererFactory.registerRenderer("string", renderer1); + rendererFactory.registerRenderer("test", renderer2); + rendererFactory.registerRenderer("test2", renderer3); + rendererFactory.setDefaultRenderer(renderer4); + try { + rendererFactory.getRenderer("nothing"); + } finally { + verify(renderer1, renderer2, renderer3, renderer4, applicationContext); + } + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/render/ChainedDelegateRendererTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/render/ChainedDelegateRendererTest.java new file mode 100644 index 0000000000..31daf7fe1f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/render/ChainedDelegateRendererTest.java @@ -0,0 +1,178 @@ +/* + * 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.apache.tiles.request.render; + +import org.apache.tiles.request.Request; +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringWriter; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link ChainedDelegateRenderer}. + */ +public class ChainedDelegateRendererTest { + + /** + * The renderer. + */ + private ChainedDelegateRenderer renderer; + + /** + * A mock string attribute renderer. + */ + private Renderer stringRenderer; + + /** + * A mock template attribute renderer. + */ + private Renderer templateRenderer; + + /** + * A mock definition attribute renderer. + */ + private Renderer definitionRenderer; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + stringRenderer = createMock(Renderer.class); + templateRenderer = createMock(Renderer.class); + definitionRenderer = createMock(Renderer.class); + renderer = new ChainedDelegateRenderer(); + renderer.addAttributeRenderer(definitionRenderer); + renderer.addAttributeRenderer(templateRenderer); + renderer.addAttributeRenderer(stringRenderer); + } + + /** + * Tests + * {@link ChainedDelegateRenderer#render(String, Request)} + * writing a definition. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test + public void testWriteDefinition() throws IOException { + Request requestContext = EasyMock.createMock(Request.class); + + expect(definitionRenderer.isRenderable("my.definition", requestContext)).andReturn(Boolean.TRUE); + definitionRenderer.render("my.definition", requestContext); + + replay(requestContext, stringRenderer, templateRenderer, definitionRenderer); + renderer.render("my.definition", requestContext); + verify(requestContext, stringRenderer, templateRenderer, definitionRenderer); + } + + /** + * Tests + * {@link ChainedDelegateRenderer#render(String, Request)} + * writing a definition. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test(expected = NullPointerException.class) + public void testWriteNull() throws IOException { + StringWriter writer = new StringWriter(); + Request requestContext = EasyMock.createMock(Request.class); + + replay(requestContext, stringRenderer, templateRenderer, definitionRenderer); + try { + renderer.render(null, requestContext); + } finally { + writer.close(); + verify(requestContext, stringRenderer, templateRenderer, definitionRenderer); + } + } + + /** + * Tests + * {@link ChainedDelegateRenderer#render(String, Request)} + * writing a definition. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test(expected = CannotRenderException.class) + public void testWriteNotRenderable() throws IOException { + StringWriter writer = new StringWriter(); + Request requestContext = EasyMock.createMock(Request.class); + + expect(definitionRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.FALSE); + expect(templateRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.FALSE); + expect(stringRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.FALSE); + + replay(requestContext, stringRenderer, templateRenderer, definitionRenderer); + try { + renderer.render("Result", requestContext); + } finally { + writer.close(); + verify(requestContext, stringRenderer, templateRenderer, definitionRenderer); + } + } + + /** + * Tests + * {@link ChainedDelegateRenderer#render(String, Request)} + * writing a string. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test + public void testWriteString() throws IOException { + Request requestContext = EasyMock.createMock(Request.class); + expect(definitionRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.FALSE); + expect(templateRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.FALSE); + expect(stringRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.TRUE); + stringRenderer.render("Result", requestContext); + + replay(requestContext, stringRenderer, templateRenderer, definitionRenderer); + renderer.render("Result", requestContext); + verify(requestContext, stringRenderer, templateRenderer, definitionRenderer); + } + + /** + * Tests + * {@link ChainedDelegateRenderer#render(String, Request)} + * writing a template. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test + public void testWriteTemplate() throws IOException { + StringWriter writer = new StringWriter(); + Request requestContext = EasyMock.createMock(Request.class); + templateRenderer.render("/myTemplate.jsp", requestContext); + expect(definitionRenderer.isRenderable("/myTemplate.jsp", requestContext)).andReturn(Boolean.FALSE); + expect(templateRenderer.isRenderable("/myTemplate.jsp", requestContext)).andReturn(Boolean.TRUE); + + replay(requestContext, stringRenderer, templateRenderer, definitionRenderer); + renderer.render("/myTemplate.jsp", requestContext); + writer.close(); + verify(requestContext, stringRenderer, templateRenderer, definitionRenderer); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/render/DispatchRendererTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/render/DispatchRendererTest.java new file mode 100644 index 0000000000..7f158ce69f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/render/DispatchRendererTest.java @@ -0,0 +1,74 @@ +/* + * 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.apache.tiles.request.render; + +import org.apache.tiles.request.DispatchRequest; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link DispatchRenderer}. + */ +public class DispatchRendererTest { + + /** + * The renderer. + */ + private DispatchRenderer renderer; + + @Before + public void setUp() { + renderer = new DispatchRenderer(); + } + + @Test + public void testWrite() throws IOException { + DispatchRequest requestContext = createMock(DispatchRequest.class); + requestContext.dispatch("/myTemplate.jsp"); + replay(requestContext); + renderer.render("/myTemplate.jsp", requestContext); + verify(requestContext); + } + + @Test(expected = CannotRenderException.class) + public void testWriteNull() throws IOException { + DispatchRequest requestContext = createMock(DispatchRequest.class); + replay(requestContext); + renderer.render(null, requestContext); + verify(requestContext); + } + + @Test + public void testIsRenderable() { + Request requestContext = createMock(DispatchRequest.class); + replay(requestContext); + assertTrue(renderer.isRenderable("/myTemplate.jsp", requestContext)); + assertFalse(renderer.isRenderable(null, requestContext)); + verify(requestContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/render/NoSuchRendererExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/render/NoSuchRendererExceptionTest.java new file mode 100644 index 0000000000..5c51a730c3 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/render/NoSuchRendererExceptionTest.java @@ -0,0 +1,42 @@ +/* + * 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.apache.tiles.request.render; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link NoSuchRendererException}. + */ +public class NoSuchRendererExceptionTest { + + /** + * Test method for {@link NoSuchRendererException#NoSuchRendererException(String)}. + */ + @Test + public void testNoSuchRendererExceptionString() { + NoSuchRendererException exception = new NoSuchRendererException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/render/StringRendererTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/render/StringRendererTest.java new file mode 100644 index 0000000000..cce4710af6 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/render/StringRendererTest.java @@ -0,0 +1,79 @@ +/* + * 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.apache.tiles.request.render; + +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringWriter; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link StringRenderer}. + */ +public class StringRendererTest { + + /** + * The renderer. + */ + private StringRenderer renderer; + + @Before + public void setUp() { + renderer = new StringRenderer(); + } + + /** + * Tests + * {@link StringRenderer#render(String, Request)}. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test + public void testWrite() throws IOException { + StringWriter writer = new StringWriter(); + Request requestContext = createMock(Request.class); + expect(requestContext.getWriter()).andReturn(writer); + replay(requestContext); + renderer.render("Result", requestContext); + writer.close(); + assertEquals("Not written 'Result'", "Result", writer.toString()); + verify(requestContext); + } + + /** + * Tests + * {@link StringRenderer#isRenderable(String, Request)}. + */ + @Test + public void testIsRenderable() { + Request requestContext = createMock(Request.class); + replay(requestContext); + assertTrue(renderer.isRenderable("Result", requestContext)); + verify(requestContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/AddAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/AddAttributeModelTest.java new file mode 100644 index 0000000000..86da99995e --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/AddAttributeModelTest.java @@ -0,0 +1,111 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link AddAttributeModel}. + */ +public class AddAttributeModelTest { + + /** + * The model to test. + */ + private AddAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new AddAttributeModel(); + } + + /** + * Test method for {@link AddAttributeModel + * #execute(java.lang.Object, java.lang.String, java.lang.String, java.lang.String, + * Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + Request request = createMock(Request.class); + ModelBody modelBody = createMock(ModelBody.class); + Deque composeStack = new ArrayDeque<>(); + ListAttribute listAttribute = new ListAttribute(); + Attribute attribute; + composeStack.push(listAttribute); + Map requestScope = new HashMap<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + + expect(request.getContext("request")).andReturn(requestScope).times(2); + expect(modelBody.evaluateAsString()).andReturn(null); + expect(modelBody.evaluateAsString()).andReturn("myBody"); + + replay(request, modelBody); + model.execute("myValue", "myExpression", "myRole", "myType", + request, modelBody); + List attributes = listAttribute.getValue(); + assertEquals(1, attributes.size()); + attribute = attributes.iterator().next(); + assertEquals("myValue", attribute.getValue()); + assertEquals("myExpression", attribute.getExpressionObject().getExpression()); + assertEquals("myRole", attribute.getRole()); + assertEquals("myType", attribute.getRenderer()); + + composeStack.clear(); + listAttribute = new ListAttribute(); + attribute = new Attribute(); + composeStack.push(listAttribute); + composeStack.push(attribute); + + model.execute(null, "myExpression", "myRole", "myType", request, + modelBody); + attributes = listAttribute.getValue(); + assertEquals(1, attributes.size()); + attribute = attributes.iterator().next(); + assertEquals("myBody", attribute.getValue()); + assertEquals("myExpression", attribute.getExpressionObject() + .getExpression()); + assertEquals("myRole", attribute.getRole()); + assertEquals("myType", attribute.getRenderer()); + verify(request, modelBody); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/AddListAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/AddListAttributeModelTest.java new file mode 100644 index 0000000000..3bdf11f5f4 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/AddListAttributeModelTest.java @@ -0,0 +1,86 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link AddListAttributeModel}. + */ +public class AddListAttributeModelTest { + + /** + * The model to test. + */ + private AddListAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new AddListAttributeModel(); + } + + /** + * Test method for + * {@link AddListAttributeModel#execute(String, Request, ModelBody)} + * . + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + Deque composeStack = new ArrayDeque<>(); + Request request = createMock(Request.class); + Map requestScope = new HashMap<>(); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request, modelBody); + ListAttribute parent = new ListAttribute(); + composeStack.push(parent); + model.execute("myRole", request, modelBody); + assertEquals(1, composeStack.size()); + assertEquals(parent, composeStack.pop()); + assertEquals(1, parent.getValue().size()); + ListAttribute listAttribute = (ListAttribute) parent.getValue().get(0); + assertEquals("myRole", listAttribute.getRole()); + verify(request, modelBody); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/ComposeStackUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/ComposeStackUtilTest.java new file mode 100644 index 0000000000..cdfbab26e4 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/ComposeStackUtilTest.java @@ -0,0 +1,123 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.Date; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +/** + * Tests {@link ComposeStackUtil}. + */ +public class ComposeStackUtilTest { + + /** + * An integer value. + */ + private static final int INT_VALUE = 3; + + /** + * A long value. + */ + private static final long LONG_VALUE = 2L; + + /** + * Test method for {@link ComposeStackUtil + * #findAncestorWithClass(java.util.Stack, java.lang.Class)}. + */ + @Test + public void testFindAncestorWithClass() { + Deque composeStack = new ArrayDeque<>(); + Integer integerValue = 1; + Long longValue = LONG_VALUE; + String stringValue = "my value"; + Integer integerValue2 = INT_VALUE; + composeStack.push(integerValue); + composeStack.push(longValue); + composeStack.push(stringValue); + composeStack.push(integerValue2); + assertEquals(integerValue2, ComposeStackUtil.findAncestorWithClass(composeStack, Integer.class)); + assertEquals(longValue, ComposeStackUtil.findAncestorWithClass(composeStack, Long.class)); + assertEquals(stringValue, ComposeStackUtil.findAncestorWithClass(composeStack, String.class)); + assertEquals(integerValue2, ComposeStackUtil.findAncestorWithClass(composeStack, Object.class)); + assertNull(ComposeStackUtil.findAncestorWithClass(composeStack, Date.class)); + } + + /** + * Tests {@link ComposeStackUtil#getComposeStack(Request)}. + */ + @Test + public void testGetComposeStackNull() { + Request request = createMock(Request.class); + + Map requestScope = new HashMap<>(); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request); + assertSame(ComposeStackUtil.getComposeStack(request), + requestScope.get(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME)); + verify(request); + } + + /** + * Tests {@link ComposeStackUtil#getComposeStack(Request)}. + */ + @Test + public void testGetComposeStackNotNull() { + Request request = createMock(Request.class); + Deque composeStack = createMock(Deque.class); + + Map requestScope = new HashMap<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request, composeStack); + assertSame(composeStack, ComposeStackUtil.getComposeStack(request)); + verify(request, composeStack); + } + + /** + * Tests {@link ComposeStackUtil#getComposeStack(Request)}. + */ + @Test + public void testGetComposeStackNoNull() { + Request request = createMock(Request.class); + + Map requestScope = new HashMap<>(); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request); + assertSame(ComposeStackUtil.getComposeStack(request), + requestScope.get(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME)); + verify(request); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/DefaultAttributeResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/DefaultAttributeResolverTest.java new file mode 100644 index 0000000000..ad51c1f70e --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/DefaultAttributeResolverTest.java @@ -0,0 +1,155 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link DefaultAttributeResolver}. + */ +public class DefaultAttributeResolverTest { + + /** + * The resolver to test. + */ + private DefaultAttributeResolver resolver; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + resolver = new DefaultAttributeResolver(); + } + + /** + * Test method for {@link DefaultAttributeResolver + * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute, + * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String, + * java.lang.String, Request)}. + */ + @Test + public void testComputeAttributeInContext() { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + Attribute attribute = new Attribute("myValue", Expression.createExpression("myExpression", null), "myRole", "myRenderer"); + + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + + replay(container, attributeContext, request); + assertEquals(attribute, resolver.computeAttribute(container, null, "myName", null, false, null, null, null, request)); + verify(container, attributeContext, request); + } + + /** + * Test method for {@link DefaultAttributeResolver + * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute, + * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String, + * java.lang.String, Request)}. + */ + @Test + public void testComputeAttributeInCall() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + Attribute attribute = new Attribute("myValue", Expression.createExpression("myExpression", null), "myRole", "myRenderer"); + + replay(container, request); + assertEquals(attribute, resolver.computeAttribute(container, attribute, null, null, false, null, null, null, request)); + verify(container, request); + } + + /** + * Test method for {@link DefaultAttributeResolver + * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute, + * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String, + * java.lang.String, Request)}. + */ + @Test + public void testComputeAttributeDefault() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(null); + + replay(container, attributeContext, request); + Attribute attribute = resolver.computeAttribute(container, null, "myName", null, false, "defaultValue", "defaultRole", "defaultType", request); + assertEquals("defaultValue", attribute.getValue()); + assertEquals("defaultRole", attribute.getRole()); + assertEquals("defaultType", attribute.getRenderer()); + verify(container, attributeContext, request); + } + + /** + * Test method for {@link DefaultAttributeResolver + * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute, + * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String, + * java.lang.String, Request)}. + */ + @Test(expected = NoSuchAttributeException.class) + public void testComputeAttributeException() { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(null); + + replay(container, attributeContext, request); + resolver.computeAttribute(container, null, "myName", null, false, null, "defaultRole", "defaultType", request); + verify(container, attributeContext, request); + } + + /** + * Test method for {@link DefaultAttributeResolver + * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute, + * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String, + * java.lang.String, Request)}. + */ + @Test + public void testComputeAttributeIgnore() { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(null); + + replay(container, attributeContext, request); + assertNull(resolver.computeAttribute(container, null, "myName", null, true, null, "defaultRole", "defaultType", request)); + verify(container, attributeContext, request); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/DefinitionModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/DefinitionModelTest.java new file mode 100644 index 0000000000..44511452ff --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/DefinitionModelTest.java @@ -0,0 +1,98 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.api.mgmt.MutableTilesContainer; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.notNull; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Tests {@link DefinitionModel}. + */ +public class DefinitionModelTest { + + /** + * The model to test. + */ + private DefinitionModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new DefinitionModel(); + } + + /** + * Test method for {@link DefinitionModel + * #execute(java.lang.String, java.lang.String, + * java.lang.String, java.lang.String, java.lang.String, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + MutableTilesContainer container = createMock(MutableTilesContainer.class); + Request request = createMock(Request.class); + Deque composeStack = new ArrayDeque<>(); + Attribute attribute = new Attribute(); + composeStack.push(attribute); + Map requestScope = new HashMap<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + container.register(notNull(), eq(request)); + + replay(container, request, modelBody, applicationContext); + model.execute("myName", "myTemplate", "myRole", "myExtends", + "myPreparer", request, modelBody); + assertEquals(1, composeStack.size()); + attribute = (Attribute) composeStack.peek(); + assertNotNull(attribute); + assertEquals("definition", attribute.getRenderer()); + verify(container, request, modelBody, applicationContext); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/GetAsStringModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/GetAsStringModelTest.java new file mode 100644 index 0000000000..8a8bbeee1c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/GetAsStringModelTest.java @@ -0,0 +1,140 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link GetAsStringModel}. + */ +public class GetAsStringModelTest { + + /** + * The mock resolver. + */ + private AttributeResolver resolver; + + /** + * The model to test. + */ + private GetAsStringModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + resolver = createMock(AttributeResolver.class); + model = new GetAsStringModel(resolver); + } + + /** + * Test method for {@link GetAsStringModel + * #execute(boolean, java.lang.String, java.lang.String, + * java.lang.Object, java.lang.String, java.lang.String, java.lang.String, + * org.apache.tiles.Attribute, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Attribute attribute = createMock(Attribute.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + Writer writer = createMock(Writer.class); + Map requestScope = new HashMap<>(); + Deque composeStack = new ArrayDeque<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(request.getWriter()).andReturn(writer); + container.prepare("myPreparer", request); + expect(resolver.computeAttribute(container, attribute, "myName", "myRole", false, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(attribute); + expect(container.startContext(request)).andReturn(attributeContext); + expect(container.evaluate(attribute, request)).andReturn("myValue"); + writer.write("myValue"); + container.endContext(request); + + replay(resolver, container, writer, request, applicationContext, modelBody); + model.execute(false, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", attribute, request, modelBody); + verify(resolver, container, writer, request, applicationContext, modelBody); + } + + /** + * Test method for {@link GetAsStringModel + * #execute(boolean, java.lang.String, java.lang.String, + * java.lang.Object, java.lang.String, java.lang.String, java.lang.String, + * org.apache.tiles.Attribute, Request, ModelBody)} when ignore flag is set. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecuteIgnore() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + Writer writer = createMock(Writer.class); + Map requestScope = new HashMap<>(); + Deque composeStack = new ArrayDeque<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(request.getWriter()).andReturn(writer); + container.prepare("myPreparer", request); + expect(resolver.computeAttribute(container, null, "myName", "myRole", true, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(null); + expect(container.startContext(request)).andReturn(attributeContext); + container.endContext(request); + + replay(resolver, container, writer, request, applicationContext, modelBody); + model.execute(true, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", null, request, modelBody); + verify(resolver, container, writer, request, applicationContext, modelBody); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/ImportAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/ImportAttributeModelTest.java new file mode 100644 index 0000000000..73a10121ec --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/ImportAttributeModelTest.java @@ -0,0 +1,316 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link ImportAttributeModel}. + */ +public class ImportAttributeModelTest { + + /** + * The size of the attributes collection. + */ + private static final int ATTRIBUTES_SIZE = 4; + + /** + * The model to test. + */ + private ImportAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new ImportAttributeModel(); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteSingle() { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andReturn("myEvaluatedValue"); + + replay(container, attributeContext, request, applicationContext); + model.execute("myName", "request", null, false, request); + assertEquals(2, requestScope.size()); + assertEquals("myEvaluatedValue", requestScope.get("myName")); + verify(container, attributeContext, request, applicationContext); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteSingleToName() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andReturn("myEvaluatedValue"); + + replay(container, attributeContext, request, applicationContext); + model.execute("myName", "request", "myToName", false, request); + assertEquals(2, requestScope.size()); + assertEquals("myEvaluatedValue", requestScope.get("myToName")); + verify(container, attributeContext, request, applicationContext); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteAll() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute1 = new Attribute("myValue1"); + Attribute attribute2 = new Attribute("myValue2"); + Attribute attribute3 = new Attribute("myValue3"); + Set cascadedNames = new HashSet<>(); + cascadedNames.add("myName1"); + cascadedNames.add("myName2"); + Set localNames = new HashSet<>(); + localNames.add("myName1"); + localNames.add("myName3"); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getCascadedAttributeNames()).andReturn(cascadedNames); + expect(attributeContext.getLocalAttributeNames()).andReturn(localNames); + expect(attributeContext.getAttribute("myName1")).andReturn(attribute1).times(2); + expect(attributeContext.getAttribute("myName2")).andReturn(attribute2); + expect(attributeContext.getAttribute("myName3")).andReturn(attribute3); + expect(container.evaluate(attribute1, request)).andReturn("myEvaluatedValue1").times(2); + expect(container.evaluate(attribute2, request)).andReturn("myEvaluatedValue2"); + expect(container.evaluate(attribute3, request)).andReturn("myEvaluatedValue3"); + + replay(container, attributeContext, request, applicationContext); + model.execute(null, "request", null, false, request); + assertEquals(ATTRIBUTES_SIZE, requestScope.size()); + assertEquals("myEvaluatedValue1", requestScope.get("myName1")); + assertEquals("myEvaluatedValue2", requestScope.get("myName2")); + assertEquals("myEvaluatedValue3", requestScope.get("myName3")); + verify(container, attributeContext, request, applicationContext); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test(expected = NoSuchAttributeException.class) + public void testExecuteSingleNullAttributeException() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(null); + + replay(container, attributeContext, request, applicationContext); + try { + model.execute("myName", "request", null, false, request); + } finally { + verify(container, attributeContext, request, applicationContext); + } + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test(expected = NoSuchAttributeException.class) + public void testExecuteSingleNullAttributeValueException() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andReturn(null); + + replay(container, attributeContext, request, applicationContext); + try { + model.execute("myName", "request", null, false, request); + } finally { + verify(container, attributeContext, request, applicationContext); + } + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test(expected = RuntimeException.class) + public void testExecuteSingleRuntimeException() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andThrow(new RuntimeException()); + + replay(container, attributeContext, request, applicationContext); + try { + model.execute("myName", "request", null, false, request); + } finally { + verify(container, attributeContext, request, applicationContext); + } + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteSingleNullAttributeIgnore() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(null); + + replay(container, attributeContext, request, applicationContext); + model.execute("myName", "request", null, true, request); + verify(container, attributeContext, request, applicationContext); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteSingleNullAttributeValueIgnore() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andReturn(null); + + replay(container, attributeContext, request, applicationContext); + model.execute("myName", "request", null, true, request); + verify(container, attributeContext, request, applicationContext); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteSingleRuntimeIgnore() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andThrow(new RuntimeException()); + + replay(container, attributeContext, request, applicationContext); + model.execute("myName", "request", null, true, request); + verify(container, attributeContext, request, applicationContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/InsertAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertAttributeModelTest.java new file mode 100644 index 0000000000..e8a997ac02 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertAttributeModelTest.java @@ -0,0 +1,131 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link InsertAttributeModel}. + */ +public class InsertAttributeModelTest { + + /** + * The mock resolver. + */ + private AttributeResolver resolver; + + /** + * The model to test. + */ + private InsertAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + resolver = createMock(AttributeResolver.class); + model = new InsertAttributeModel(resolver); + } + + /** + * Test method for {@link InsertAttributeModel + * #execute(boolean, String, String, Object, String, String, String, + * Attribute, boolean, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + Attribute attribute = new Attribute("myValue"); + AttributeContext attributeContext = createMock(AttributeContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + + container.prepare("myPreparer", request); + expect(resolver.computeAttribute(container, attribute, "myName", "myRole", false, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(attribute); + expect(container.startContext(request)).andReturn(attributeContext); + container.endContext(request); + container.render(attribute, request); + + replay(resolver, container, request, applicationContext, modelBody); + model.execute(false, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", attribute, false, request, modelBody); + verify(resolver, container, request, applicationContext, modelBody); + } + + /** + * Test method for {@link InsertAttributeModel + * #execute(boolean, String, String, Object, String, String, String, + * Attribute, boolean, Request, ModelBody)} when ignore flag is set. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecuteIgnore() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Map requestScope = new HashMap<>(); + Deque composeStack = new ArrayDeque<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + + container.prepare("myPreparer", request); + expect(resolver.computeAttribute(container, null, "myName", "myRole", true, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(null); + expect(container.startContext(request)).andReturn(attributeContext); + container.endContext(request); + + replay(resolver, container, request, applicationContext, modelBody); + model.execute(true, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", null, false, request, modelBody); + verify(resolver, container, request, applicationContext, modelBody); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/InsertDefinitionModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertDefinitionModelTest.java new file mode 100644 index 0000000000..48d3fb492c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertDefinitionModelTest.java @@ -0,0 +1,90 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.notNull; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link InsertDefinitionModel}. + */ +public class InsertDefinitionModelTest { + + /** + * The model to test. + */ + private InsertDefinitionModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new InsertDefinitionModel(); + } + + /** + * Test method for {@link InsertDefinitionModel + * #execute(java.lang.String, java.lang.String, String, + * String, java.lang.String, java.lang.String, boolean, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.startContext(request)).andReturn(attributeContext); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + container.endContext(request); + attributeContext.setPreparer("myPreparer"); + attributeContext.setTemplateAttribute(notNull()); + container.render("myDefinitionName", request); + + replay(container, attributeContext, request, applicationContext, modelBody); + model.execute("myDefinitionName", "myTemplate", "myTemplateType", "myTemplateExpression", "myRole", "myPreparer", false, request, modelBody); + verify(container, attributeContext, request, applicationContext, modelBody); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/InsertTemplateModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertTemplateModelTest.java new file mode 100644 index 0000000000..840593d7e9 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertTemplateModelTest.java @@ -0,0 +1,89 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.notNull; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link InsertTemplateModel}. + */ +public class InsertTemplateModelTest { + + /** + * The model to test. + */ + private InsertTemplateModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new InsertTemplateModel(); + } + + /** + * Test method for {@link InsertTemplateModel + * #execute(String, String, String, String, String, boolean, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.startContext(request)).andReturn(attributeContext); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + container.endContext(request); + attributeContext.setPreparer("myPreparer"); + attributeContext.setTemplateAttribute(notNull()); + container.renderContext(request); + + replay(container, attributeContext, request, applicationContext, modelBody); + model.execute("myTemplate", "myTemplateType", "myTemplateExpression", "myRole", "myPreparer", false, request, modelBody); + verify(container, attributeContext, request, applicationContext, modelBody); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/PutAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/PutAttributeModelTest.java new file mode 100644 index 0000000000..572dcad597 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/PutAttributeModelTest.java @@ -0,0 +1,93 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.notNull; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link PutAttributeModel}. + */ +public class PutAttributeModelTest { + + /** + * The model to test. + */ + private PutAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new PutAttributeModel(); + } + + /** + * Test method for {@link PutAttributeModel + * #execute(String, Object, String, String, String, + * boolean, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecuteListAttribute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + ModelBody modelBody = createMock(ModelBody.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Deque composeStack = new ArrayDeque<>(); + ListAttribute listAttribute = new ListAttribute(); + composeStack.push(listAttribute); + Map requestScope = new HashMap<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + attributeContext.putAttribute(eq("myName"), notNull(), eq(false)); + expect(modelBody.evaluateAsString()).andReturn(null); + + replay(container, attributeContext, request, applicationContext, modelBody); + model.execute("myName", "myValue", "myExpression", "myRole", "myType", false, request, modelBody); + verify(container, attributeContext, request, applicationContext, modelBody); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/PutListAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/PutListAttributeModelTest.java new file mode 100644 index 0000000000..cd4708afc0 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/PutListAttributeModelTest.java @@ -0,0 +1,93 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link PutListAttributeModel}. + */ +public class PutListAttributeModelTest { + + /** + * The model to test. + */ + private PutListAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new PutListAttributeModel(); + } + + /** + * Test method for {@link PutListAttributeModel + * #execute(String, String, boolean, boolean, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + Deque composeStack = new ArrayDeque<>(); + Map requestScope = new HashMap<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + attributeContext.putAttribute(eq("myName"), isA(ListAttribute.class), eq(false)); + + replay(container, attributeContext, request, modelBody); + model.execute("myName", "myRole", false, false, request, modelBody); + assertEquals(0, composeStack.size()); + verify(container, attributeContext, request, modelBody); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/SetCurrentContainerModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/SetCurrentContainerModelTest.java new file mode 100644 index 0000000000..2ecda504f5 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/SetCurrentContainerModelTest.java @@ -0,0 +1,84 @@ +/* + * 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.apache.tiles.template; + +import org.apache.tiles.api.NoSuchContainerException; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link SetCurrentContainerModel}. + */ +public class SetCurrentContainerModelTest { + + /** + * Test method for {@link SetCurrentContainerModel#execute(String, Request)}. + */ + @Test + public void testSetCurrentContainer() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + attribs.put("myKey", container); + Map requestScope = new HashMap<>(); + + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + expect(request.getContext("request")).andReturn(requestScope); + expect(request.getApplicationContext()).andReturn(context); + replay(request, context, container); + SetCurrentContainerModel model = new SetCurrentContainerModel(); + model.execute("myKey", request); + assertEquals(container, requestScope.get(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME)); + verify(request, context, container); + } + + /** + * Test method for {@link SetCurrentContainerModel#execute(String, Request)}. + */ + @Test(expected = NoSuchContainerException.class) + public void testSetCurrentContainerException() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + Map attribs = new HashMap<>(); + + expect(request.getApplicationContext()).andReturn(context); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + replay(request, context); + try { + SetCurrentContainerModel model = new SetCurrentContainerModel(); + model.execute("myKey", request); + } finally { + verify(request, context); + } + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/web/jsp/taglib/UseAttributeTagTest.java b/plugins/tiles/src/test/java/org/apache/tiles/web/jsp/taglib/UseAttributeTagTest.java new file mode 100644 index 0000000000..48486746f7 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/web/jsp/taglib/UseAttributeTagTest.java @@ -0,0 +1,220 @@ +/* + * 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.apache.tiles.web.jsp.taglib; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.PageContext; +import javax.servlet.jsp.tagext.JspFragment; +import javax.servlet.jsp.tagext.JspTag; +import javax.servlet.jsp.tagext.TagData; +import javax.servlet.jsp.tagext.VariableInfo; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.ApplicationAccess; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.jsp.JspRequest; +import org.apache.tiles.web.jsp.taglib.UseAttributeTag; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests UseAttributeTag. + */ +public class UseAttributeTagTest { + + /** + * The tag to test. + */ + private UseAttributeTag tag; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + tag = new UseAttributeTag(); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#execute(org.apache.tiles.request.Request)}. + * + * @throws IOException + * @throws JspException + */ + @Test + public void testExecute() throws JspException, IOException { + JspFragment jspBody = createMock(JspFragment.class); + PageContext pageContext = createMock(PageContext.class); + JspTag parent = createMock(JspTag.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + HttpServletRequest httpServletRequest = createMock(HttpServletRequest.class); + HttpServletResponse httpServletResponse = createMock(HttpServletResponse.class); + Map applicationScope = createMock(Map.class); + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = createMock(Attribute.class); + expect(pageContext.getAttribute(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE, PageContext.APPLICATION_SCOPE)) + .andReturn(applicationContext); + expect(applicationContext.getApplicationScope()).andReturn(applicationScope).anyTimes(); + expect(pageContext.getRequest()).andReturn(httpServletRequest); + expect(pageContext.getResponse()).andReturn(httpServletResponse); + expect(pageContext.getAttribute(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, PageContext.REQUEST_SCOPE)) + .andReturn(container); + expect(container.getAttributeContext(isA(JspRequest.class))).andReturn(attributeContext); + expect(attributeContext.getAttribute("name")).andReturn(attribute); + expect(container.evaluate(isA(Attribute.class), isA(JspRequest.class))).andReturn(new Integer(1)); + pageContext.setAttribute("id", new Integer(1), PageContext.PAGE_SCOPE); + replay(jspBody, pageContext, parent, applicationContext, httpServletRequest, httpServletResponse, + applicationScope, container, attributeContext, attribute); + tag.setName("name"); + tag.setScope("page"); + tag.setId("id"); + tag.setIgnore(false); + tag.setJspContext(pageContext); + tag.setJspBody(jspBody); + tag.setParent(parent); + tag.doTag(); + verify(jspBody, pageContext, parent, applicationContext, httpServletRequest, httpServletResponse, container, + attributeContext, attribute); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#setId(java.lang.String)}. + */ + @Test + public void testSetId() { + tag.setId("id"); + assertEquals("id", tag.getId()); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#getScope()}. + */ + @Test + public void testGetScope() { + tag.setScope("scope"); + assertEquals("scope", tag.getScope()); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#setName(java.lang.String)}. + */ + @Test + public void testSetName() { + tag.setName("name"); + assertEquals("name", tag.getName()); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#setIgnore(boolean)}. + */ + @Test + public void testSetIgnore() { + tag.setIgnore(true); + assertTrue(tag.isIgnore()); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#setClassname(java.lang.String)}. + */ + @Test + public void testSetClassname() { + tag.setClassname("classname"); + assertEquals("classname", tag.getClassname()); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#getScriptingVariable()}. + */ + @Test + public void testGetScriptingVariable() { + tag.setName("name"); + assertEquals("name", tag.getScriptingVariable()); + tag.setId("id"); + assertEquals("id", tag.getScriptingVariable()); + } + + /** + * Tests {@link UseAttributeTag.Tei}. + */ + @Test + public void testTei() { + TagData tagData = createMock(TagData.class); + + expect(tagData.getAttributeString("classname")).andReturn("my.Clazz"); + expect(tagData.getAttributeString("id")).andReturn("id"); + + replay(tagData); + UseAttributeTag.Tei tei = new UseAttributeTag.Tei(); + VariableInfo[] infos = tei.getVariableInfo(tagData); + assertEquals(1, infos.length); + VariableInfo info = infos[0]; + assertEquals("id", info.getVarName()); + assertEquals("my.Clazz", info.getClassName()); + assertTrue(info.getDeclare()); + assertEquals(VariableInfo.AT_END, info.getScope()); + verify(tagData); + } + + /** + * Tests {@link UseAttributeTag.Tei}. + */ + @Test + public void testTeiDefaults() { + TagData tagData = createMock(TagData.class); + + expect(tagData.getAttributeString("classname")).andReturn(null); + expect(tagData.getAttributeString("id")).andReturn(null); + expect(tagData.getAttributeString("name")).andReturn("name"); + + replay(tagData); + UseAttributeTag.Tei tei = new UseAttributeTag.Tei(); + VariableInfo[] infos = tei.getVariableInfo(tagData); + assertEquals(1, infos.length); + VariableInfo info = infos[0]; + assertEquals("name", info.getVarName()); + assertEquals("java.lang.Object", info.getClassName()); + assertTrue(info.getDeclare()); + assertEquals(VariableInfo.AT_END, info.getScope()); + verify(tagData); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/web/startup/AbstractTilesListenerTest.java b/plugins/tiles/src/test/java/org/apache/tiles/web/startup/AbstractTilesListenerTest.java new file mode 100644 index 0000000000..dbf6f3ec2d --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/web/startup/AbstractTilesListenerTest.java @@ -0,0 +1,61 @@ +/* + * 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.apache.tiles.web.startup; + +import org.apache.tiles.core.startup.TilesInitializer; +import org.apache.tiles.request.servlet.ServletApplicationContext; +import org.junit.Test; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link AbstractTilesListener}. + */ +public class AbstractTilesListenerTest { + + /** + * Test method for {@link AbstractTilesListener#contextInitialized(ServletContextEvent)}. + */ + @Test + public void testContextInitialized() { + AbstractTilesListener listener = createMockBuilder(AbstractTilesListener.class).createMock(); + ServletContextEvent event = createMock(ServletContextEvent.class); + ServletContext servletContext = createMock(ServletContext.class); + TilesInitializer initializer = createMock(TilesInitializer.class); + + expect(event.getServletContext()).andReturn(servletContext); + expect(listener.createTilesInitializer()).andReturn(initializer); + initializer.initialize(isA(ServletApplicationContext.class)); + initializer.destroy(); + + replay(listener, event, servletContext, initializer); + listener.contextInitialized(event); + listener.contextDestroyed(event); + verify(listener, event, servletContext, initializer); + } + +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat new file mode 100644 index 0000000000..14e3fafc9b --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat @@ -0,0 +1,72 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.freemarker.test; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + * Documentation of the DoStuff class. + */ +public class DoStuffFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffTemplate model; + + /** + * Constructor. + * + * @param model + * The template model. + */ + public DoStuffFMModel(org.apache.tiles.autotag.template.DoStuffTemplate model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.freemarker.test.Runtime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.autotag.freemarker.test.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute( + runtime.getParameter("one", java.lang.String.class, null), + runtime.getParameter("two", java.lang.Integer.class, 0), + runtime.getParameter("three", java.lang.Boolean.class, false), + request, modelBody + ); + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat new file mode 100644 index 0000000000..8841206d5a --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat @@ -0,0 +1,70 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.freemarker.test; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + * Documentation of the DoStuffNoBody class. + */ +public class DoStuffNoBodyFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model; + + /** + * Constructor. + * + * @param model + * The template model. + */ + public DoStuffNoBodyFMModel(org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.freemarker.test.Runtime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.autotag.freemarker.test.Request request = runtime.createRequest(); + model.execute( + runtime.getParameter("one", java.lang.Double.class, null), + runtime.getParameter("two", java.lang.Float.class, 0.0f), + runtime.getParameter("three", java.util.Date.class, null), + request + ); + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat new file mode 100644 index 0000000000..0aaa347f3e --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat @@ -0,0 +1,64 @@ +/* + * 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. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.freemarker.test; + +/** + * Test for TLD docs. + */ +public class TldtestFMModelRepository { + + /** + * The "doStuff" directive. + */ + private DoStuffFMModel doStuff; + + /** + * The "doStuffNoBody" directive. + */ + private DoStuffNoBodyFMModel doStuffNoBody; + + /** + * Constructor. + */ + public TilesFMModelRepository() { + doStuff = new DoStuffFMModel(new org.apache.tiles.autotag.template.DoStuffTemplate()); + doStuffNoBody = new DoStuffNoBodyFMModel(new org.apache.tiles.autotag.template.DoStuffNoBodyTemplate()); + } + + /** + * Returns the "doStuff" directive. + * + * @return The "doStuff" directive. + */ + public DoStuffFMModel getDoStuff() { + return doStuff; + } + + /** + * Returns the "doStuffNoBody" directive. + * + * @return The "doStuffNoBody" directive. + */ + public DoStuffNoBodyFMModel getDoStuffNoBody() { + return doStuffNoBody; + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java new file mode 100644 index 0000000000..85433d5815 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java @@ -0,0 +1,134 @@ +/* + * 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. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.jsp.test; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + * Documentation of the DoStuffNoBody class. + */ +public class DoStuffNoBodyTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model = new org.apache.tiles.autotag.template.DoStuffNoBodyTemplate(); + + /** + * Parameter one. + */ + private java.lang.Double one; + + /** + * Parameter two. + */ + private float two; + + /** + * Parameter three. + */ + private java.util.Date three; + + /** + * Getter for one property. + * + * @return + * Parameter one. + */ + public java.lang.Double getOne() { + return one; + } + + /** + * Setter for one property. + * + * @param one + * Parameter one. + */ + public void setOne(java.lang.Double one) { + this.one = one; + } + + /** + * Getter for two property. + * + * @return + * Parameter two. + */ + public float getTwo() { + return two; + } + + /** + * Setter for two property. + * + * @param two + * Parameter two. + */ + public void setTwo(float two) { + this.two = two; + } + + /** + * Getter for three property. + * + * @return + * Parameter three. + */ + public java.util.Date getThree() { + return three; + } + + /** + * Setter for three property. + * + * @param three + * Parameter three. + */ + public void setThree(java.util.Date three) { + this.three = three; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.jsp.test.Runtime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.autotag.jsp.test.Request request = runtime.createRequest(); + model.execute( + one, + two, + three, + request + ); + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffTag.java b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffTag.java new file mode 100644 index 0000000000..6ad8b1e6f9 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffTag.java @@ -0,0 +1,136 @@ +/* + * 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. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.jsp.test; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + * Documentation of the DoStuff class. + */ +public class DoStuffTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffTemplate model = new org.apache.tiles.autotag.template.DoStuffTemplate(); + + /** + * Parameter one. + */ + private java.lang.String one; + + /** + * Parameter two. + */ + private int two; + + /** + * Parameter three. + */ + private boolean three; + + /** + * Getter for one property. + * + * @return + * Parameter one. + */ + public java.lang.String getOne() { + return one; + } + + /** + * Setter for one property. + * + * @param one + * Parameter one. + */ + public void setOne(java.lang.String one) { + this.one = one; + } + + /** + * Getter for two property. + * + * @return + * Parameter two. + */ + public int getTwo() { + return two; + } + + /** + * Setter for two property. + * + * @param two + * Parameter two. + */ + public void setTwo(int two) { + this.two = two; + } + + /** + * Getter for three property. + * + * @return + * Parameter three. + */ + public boolean isThree() { + return three; + } + + /** + * Setter for three property. + * + * @param three + * Parameter three. + */ + public void setThree(boolean three) { + this.three = three; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.jsp.test.Runtime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.autotag.jsp.test.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute( + one, + two, + three, + request, modelBody + ); + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat new file mode 100644 index 0000000000..8ae29b34a4 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat @@ -0,0 +1,70 @@ +/* + * 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. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.velocity.test; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + * Documentation of the DoStuff class. + */ +public class DoStuffDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffTemplate model = new org.apache.tiles.autotag.template.DoStuffTemplate(); + + @Override + public String getName() { + return "tldtest_doStuff"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) + throws IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.velocity.test.Runtime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.autotag.velocity.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute( + runtime.getParameter("one", java.lang.String.class, null), + runtime.getParameter("two", java.lang.Integer.class, 0), + runtime.getParameter("three", java.lang.Boolean.class, false), + request, modelBody + ); + return true; + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat new file mode 100644 index 0000000000..6ed645a661 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat @@ -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. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.velocity.test; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + * Documentation of the DoStuffNoBody class. + */ +public class DoStuffNoBodyDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model = new org.apache.tiles.autotag.template.DoStuffNoBodyTemplate(); + + @Override + public String getName() { + return "tldtest_doStuffNoBody"; + } + + @Override + public int getType() { + return LINE; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) + throws IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.velocity.test.Runtime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.autotag.velocity.Request request = runtime.createRequest(); + model.execute( + runtime.getParameter("one", java.lang.Double.class, null), + runtime.getParameter("two", java.lang.Float.class, 0.0f), + runtime.getParameter("three", java.util.Date.class, null), + request + ); + return true; + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-tiles-513.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-tiles-513.xml new file mode 100644 index 0000000000..3b6c6a377c --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-tiles-513.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-wildcard.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-wildcard.xml new file mode 100644 index 0000000000..9312f9d609 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-wildcard.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1.xml new file mode 100644 index 0000000000..621d7cef9e --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_en_US.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_en_US.xml new file mode 100644 index 0000000000..1a89b229cc --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_en_US.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr.xml new file mode 100644 index 0000000000..62ed681704 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr_CA.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr_CA.xml new file mode 100644 index 0000000000..b35d0d83e1 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr_CA.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs2.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs2.xml new file mode 100644 index 0000000000..f24f1c5d73 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs2.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs3.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs3.xml new file mode 100644 index 0000000000..77d7bed2d9 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs3.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs_regression_TILES-352.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs_regression_TILES-352.xml new file mode 100644 index 0000000000..a28ec49ca5 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs_regression_TILES-352.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/invalid-defs.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/invalid-defs.xml new file mode 100644 index 0000000000..3973a749a9 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/invalid-defs.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/malformed-defs.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/malformed-defs.xml new file mode 100644 index 0000000000..b82f95de7f --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/malformed-defs.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/temp-defs.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/temp-defs.xml new file mode 100644 index 0000000000..d5334eab4c --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/temp-defs.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1.xml new file mode 100644 index 0000000000..f8b651ce26 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1_it.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1_it.xml new file mode 100644 index 0000000000..4c7c0834f2 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1_it.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs.xml new file mode 100644 index 0000000000..590e0c7cfe --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-one.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-one.xml new file mode 100644 index 0000000000..180fb0a8c9 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-one.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-two.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-two.xml new file mode 100644 index 0000000000..d0639d696d --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-two.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs.xml new file mode 100644 index 0000000000..2d124a2bed --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource with space.txt b/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource with space.txt new file mode 100644 index 0000000000..82cb4afe82 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource with space.txt @@ -0,0 +1,17 @@ + * 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. +test diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource.txt b/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource.txt new file mode 100644 index 0000000000..82cb4afe82 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource.txt @@ -0,0 +1,17 @@ + * 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. +test diff --git a/plugins/tiles/src/test/resources/tldtest-jsp.tld b/plugins/tiles/src/test/resources/tldtest-jsp.tld new file mode 100644 index 0000000000..b2cbb8eb77 --- /dev/null +++ b/plugins/tiles/src/test/resources/tldtest-jsp.tld @@ -0,0 +1,121 @@ + + + + + + + + 1.2 + tldtest + http://www.initrode.net/tags/test + + + + + doStuff + org.apache.tiles.autotag.jsp.test.DoStuffTag + scriptless + + + + + one + true + true + java.lang.String + + + + + + two + false + true + int + + + + + + three + false + true + long + + + + + + + doStuffNoBody + org.apache.tiles.autotag.jsp.test.DoStuffNoBodyTag + empty + + + + + one + true + true + java.lang.Double + + + + + + two + false + true + float + + + + + + three + false + true + java.util.Date + + + diff --git a/plugins/tiles/src/test/resources/velocity.properties.test b/plugins/tiles/src/test/resources/velocity.properties.test new file mode 100644 index 0000000000..3ee9deeb83 --- /dev/null +++ b/plugins/tiles/src/test/resources/velocity.properties.test @@ -0,0 +1,21 @@ +# 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. +# +# This file was automatically generated by Autotag. Please do not edit it manually. + +userdirective=org.apache.tiles.autotag.velocity.test.DoStuffDirective,\ +org.apache.tiles.autotag.velocity.test.DoStuffNoBodyDirective \ No newline at end of file diff --git a/pom.xml b/pom.xml index c5488b996e..476b8f5172 100644 --- a/pom.xml +++ b/pom.xml @@ -104,7 +104,7 @@ UTF-8 - 2023-06-28T07:13:15Z + 2023-07-16T07:48:11Z 1.8 1.8 @@ -780,7 +780,7 @@ org.easymock easymock - 4.2 + 4.3 test @@ -825,62 +825,6 @@ provided - - org.apache.tiles - tiles-api - ${tiles.version} - - - org.apache.tiles - tiles-core - ${tiles.version} - - - org.apache.tiles - tiles-servlet - ${tiles.version} - - - org.apache.tiles - tiles-request-portlet - ${tiles-request.version} - - - org.apache.tiles - tiles-request-api - ${tiles-request.version} - - - org.apache.tiles - tiles-request-jsp - ${tiles-request.version} - - - org.apache.tiles - tiles-request-servlet - ${tiles-request.version} - - - org.apache.tiles - tiles-jsp - ${tiles.version} - - - org.apache.tiles - tiles-freemarker - ${tiles.version} - - - org.apache.tiles - tiles-ognl - ${tiles.version} - - - org.apache.tiles - tiles-el - ${tiles.version} - - javax.servlet.jsp jsp-api @@ -936,6 +880,12 @@ commons-digester commons-digester 2.1 + + + commons-logging + commons-logging + + commons-el @@ -1086,6 +1036,12 @@ ${log4j2.version} + + org.apache.logging.log4j + log4j-jcl + ${log4j2.version} + + org.testng testng