Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2004-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.grails.gsp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.Map;
import groovy.lang.Binding;
import groovy.lang.Writable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.ReflectionUtils;
import grails.util.Environment;
import org.grails.taglib.AbstractTemplateVariableBinding;
import org.grails.taglib.TemplateVariableBinding;
import org.grails.taglib.encoder.OutputContext;
import org.grails.taglib.encoder.OutputContextLookup;
/**
* Writes itself to the specified writer, typically the response writer.
*
* @author Graeme Rocher
* @author Lari Hotari
* @since 0.5
*/
public class GroovyPageWritable implements Writable {
private static final Log logger = LogFactory.getLog(GroovyPageWritable.class);
private static final String GSP_NONE_CODEC_NAME = "none";
private GroovyPageMetaInfo metaInfo;
private OutputContextLookup outputContextLookup;
private boolean allowSettingContentType;
@SuppressWarnings("rawtypes")
private Map additionalBinding = new LinkedHashMap();
private boolean showSource;
private static final String GROOVY_SOURCE_CONTENT_TYPE = "text/plain";
public GroovyPageWritable(GroovyPageMetaInfo metaInfo, OutputContextLookup outputContextLookup, boolean allowSettingContentType) {
this.metaInfo = metaInfo;
this.outputContextLookup = outputContextLookup;
this.allowSettingContentType = allowSettingContentType;
}
/**
* This sets any additional variables that need to be placed in the Binding of the GSP page.
*
* @param binding The additional variables
*/
@SuppressWarnings("rawtypes")
public void setBinding(Map binding) {
if (binding != null) {
this.additionalBinding = binding;
}
}
/**
* Writes the template to the specified Writer
*
* @param out The Writer to write to, normally the HttpServletResponse
* @return Returns the passed Writer
* @throws IOException
*/
public Writer writeTo(Writer out) throws IOException {
OutputContext outputContext = this.outputContextLookup.lookupOutputContext();
try {
return doWriteTo(outputContext, out);
}
finally {
doCleanUp(outputContext, out);
}
}
protected void doCleanUp(OutputContext outputContext, Writer out) {
this.metaInfo.writeToFinished(out);
}
protected Writer doWriteTo(OutputContext outputContext, Writer out) throws IOException {
if (shouldShowGroovySource(outputContext)) {
// Set it to TEXT
outputContext.setContentType(GROOVY_SOURCE_CONTENT_TYPE); // must come before response.getOutputStream()
writeGroovySourceToResponse(this.metaInfo, out);
}
else {
// Set it to HTML by default
if (this.metaInfo.getCompilationException() != null) {
throw this.metaInfo.getCompilationException();
}
// Set up the script context
AbstractTemplateVariableBinding parentBinding = null;
boolean hasRequest = outputContext != null;
boolean newParentCreated = false;
if (hasRequest) {
parentBinding = outputContext.getBinding();
if (parentBinding == null) {
parentBinding = outputContext.createAndRegisterRootBinding();
newParentCreated = true;
}
}
if (this.allowSettingContentType && hasRequest) {
// only try to set content type when evaluating top level GSP
boolean contentTypeAlreadySet = outputContext.isContentTypeAlreadySet();
if (!contentTypeAlreadySet) {
if (logger.isDebugEnabled()) {
logger.debug("Writing output with content type: " + this.metaInfo.getContentType());
}
outputContext.setContentType(this.metaInfo.getContentType()); // must come before response.getWriter()
}
}
GroovyPageBinding binding = createBinding(parentBinding);
if (hasRequest) {
outputContext.setBinding(binding);
}
GroovyPage page = null;
try {
page = (GroovyPage) ReflectionUtils.accessibleConstructor(this.metaInfo.getPageClass()).newInstance();
}
catch (Exception e) {
throw new GroovyPagesException("Problem instantiating page class", e);
}
page.setBinding(binding);
binding.setOwner(page);
page.initRun(out, outputContext, this.metaInfo);
try {
page.run();
}
finally {
page.cleanup();
if (hasRequest) {
if (newParentCreated) {
outputContext.setBinding(null);
}
else {
outputContext.setBinding(parentBinding);
}
}
}
}
return out;
}
private int incrementAndGetDebugTemplatesIdCounter(OutputContext outputContext) {
//debugTemplatesIdCounter.incrementAndGet()
return 0;
}
private boolean shouldShowGroovySource(OutputContext outputContext) {
return isShowSource() && Environment.getCurrent() == Environment.DEVELOPMENT && this.metaInfo.getGroovySource() != null;
}
private static final GspNoneCodec gspNoneCodeInstance = new GspNoneCodec();
public boolean isShowSource() {
return this.showSource;
}
public void setShowSource(boolean showSource) {
this.showSource = showSource;
}
private GroovyPageBinding createBinding(Binding parent) {
GroovyPageBinding binding = new GroovyPageBinding();
binding.setParent(parent);
binding.setVariableDirectly("it", null);
if (this.additionalBinding != null) {
binding.addMap(this.additionalBinding);
}
// set plugin context path for top level rendering, this means actual view + layout
// view is top level when parent is GroovyPageRequestBinding
// pluginContextPath is also resetted when a plugin template is overrided by an application view
if (parent == null || (parent instanceof TemplateVariableBinding
&& ((TemplateVariableBinding) parent).isRoot()) || "".equals(this.metaInfo.getPluginPath())) {
binding.setPluginContextPath(this.metaInfo.getPluginPath());
}
binding.setPagePlugin(this.metaInfo.getPagePlugin());
return binding;
}
/**
* Copy all of input to output.
* @param in The input stream to writeInputStreamToResponse from
* @param out The output to write to
* @throws IOException When an error occurs writing to the response Writer
*/
protected void writeInputStreamToResponse(InputStream in, Writer out) throws IOException {
try {
in.reset();
Reader reader = new InputStreamReader(in, "UTF-8");
char[] buf = new char[8192];
for (; ; ) {
int read = reader.read(buf);
if (read <= 0) {
break;
}
out.write(buf, 0, read);
}
}
finally {
out.close();
in.close();
}
}
/**
* Writes the Groovy source code attached to the given info object
* to the response, prefixing each line with its line number. The
* line numbers make it easier to match line numbers in exceptions
* to the generated source.
* @param info The meta info for the GSP page that we want to write
* the generated source for.
* @param out The writer to send the source to.
* @throws IOException If there is either a problem with the input
* stream for the Groovy source, or the writer.
*/
protected void writeGroovySourceToResponse(GroovyPageMetaInfo info, Writer out) throws IOException {
InputStream in = info.getGroovySource();
if (in == null) {
return;
}
try {
try {
in.reset();
}
catch (IOException e) {
// ignore
}
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
int lineNum = 1;
int maxPaddingSize = 3;
// Prepare the buffer containing the whitespace padding.
// The padding is used to right-align the line numbers.
StringBuilder paddingBuffer = new StringBuilder(maxPaddingSize);
for (int i = 0; i < maxPaddingSize; i++) {
paddingBuffer.append(' ');
}
// Set the initial padding.
String padding = paddingBuffer.toString();
// Read the Groovy source line by line and write it to the
// response, prefixing each line with the line number.
for (String line = reader.readLine(); line != null; line = reader.readLine(), lineNum++) {
// Get the current line number as a string.
String numberText = String.valueOf(lineNum);
// Decrease the padding if the current line number has
// more digits than the previous one.
if (padding.length() + numberText.length() > 4) {
paddingBuffer.deleteCharAt(padding.length() - 1);
padding = paddingBuffer.toString();
}
// Write out this line.
out.write(padding);
out.write(numberText);
out.write(": ");
out.write(line);
out.write('\n');
}
}
finally {
out.close();
in.close();
}
}
private static final class GspNoneCodec {
@SuppressWarnings("unused")
public Object encode(Object object) {
return object;
}
}
}