package er.extensions.components; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WOResponse; import er.extensions.appserver.ERXApplication; import er.extensions.foundation.ERXProperties; import er.extensions.foundation.ERXStringUtilities; /** * ERXClickToOpenSupport provides the component-side implementation of * WOLips.framework's click-to-open support. * * @author mschrag * @property er.component.clickToOpen boolean that determines if click-to-open * is enabled (only enables in development mode) */ public class ERXClickToOpenSupport { /** * Boolean that controls whether or not click-to-open support is enabled. */ private static Boolean _enabled; /** * Shared pattern for the click-to-open parser. */ private static Pattern _tagPattern = Pattern.compile("<([a-z][a-z0-9_\\-]*:)?[a-z][a-z0-9_\\-]*\\s*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); /** * The marker string that is temporarily written into the buffer for click-to-open support. */ private static final String _marker = "<<CLICK_TO_OPEN_MARKER>>"; /** * Returns whether or not click-to-open support is enabled. * * @return whether or not click-to-open support is enabled */ public static boolean isEnabled() { // Just load click-to-open support one time ... if (_enabled == null) { if (!ERXApplication.isDevelopmentModeSafe()) { _enabled = Boolean.FALSE; } else { _enabled = Boolean.valueOf(ERXProperties.booleanForKeyWithDefault("er.component.clickToOpen", false)); } } return ERXClickToOpenSupport._enabled.booleanValue(); } /** * Called before super.appendToResponse for click-to-open support. * * @param response * the response * @param context * the context * @param clickToOpenEnabled * if false, this method is basically a no-op; if true, it * processes the response */ public static void preProcessResponse(WOResponse response, WOContext context, boolean clickToOpenEnabled) { if (clickToOpenEnabled) { response.appendContentString(ERXClickToOpenSupport._marker); } } /** * Called after super.appendToResponse for click-to-open support. * * @param component * the component being processed * @param response * the response * @param context * the context * @param clickToOpenEnabled * if false, this method is basically a no-op; if true, it * processes the response */ public static void postProcessResponse(Class component, WOResponse response, WOContext context, boolean clickToOpenEnabled) { if (clickToOpenEnabled) { String contentStr = response.contentString(); if (contentStr != null) { StringBuffer contentStringBuffer = new StringBuffer(contentStr); int markerIndex = contentStringBuffer.lastIndexOf(ERXClickToOpenSupport._marker); if (markerIndex != -1) { contentStringBuffer.delete(markerIndex, markerIndex + ERXClickToOpenSupport._marker.length()); Matcher tagMatcher = ERXClickToOpenSupport._tagPattern.matcher(contentStringBuffer); if (tagMatcher.find(markerIndex)) { int attributeOffset = tagMatcher.end(); String componentName = component.getName(); String componentNameTag = "_componentName"; if (ERXStringUtilities.regionMatches(contentStringBuffer, attributeOffset, componentNameTag, 0, componentNameTag.length())) { int openQuoteIndex = contentStringBuffer.indexOf("\"", attributeOffset); contentStringBuffer.insert(openQuoteIndex + 1, componentName + ","); } else { contentStringBuffer.insert(attributeOffset, " " + componentNameTag + " = \"" + componentName + "\" "); } } response.setContent(contentStringBuffer.toString()); } } } } }