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 (c) 2002-2024 Gargoyle Software Inc.
* Copyright (c) 2005-2024 Xceptance Software Technologies GmbH
*
* 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.htmlunit.javascript.regexp;
import static org.htmlunit.BrowserVersionFeatures.JS_REGEXP_EMPTY_LASTPAREN_IF_TOO_MANY_GROUPS;
import static org.htmlunit.BrowserVersionFeatures.JS_REGEXP_GROUP0_RETURNS_WHOLE_MATCH;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.htmlunit.BrowserVersion;
import org.htmlunit.NotYetImplementedException;
import org.htmlunit.corejs.javascript.Context;
import org.htmlunit.corejs.javascript.RegExpProxy;
import org.htmlunit.corejs.javascript.ScriptRuntime;
import org.htmlunit.corejs.javascript.Scriptable;
import org.htmlunit.corejs.javascript.Undefined;
import org.htmlunit.corejs.javascript.regexp.NativeRegExp;
import org.htmlunit.corejs.javascript.regexp.RegExpImpl;
import org.htmlunit.corejs.javascript.regexp.SubString;
import org.htmlunit.javascript.JavaScriptEngine;
import com.xceptance.common.collection.ConcurrentLRUCache;
/**
* Begins customization of JavaScript RegExp base on JDK regular expression support.
*
* @author Marc Guillemot
* @author Ahmed Ashour
* @author Ronald Brill
* @author Carsten Steul
*/
public class HtmlUnitRegExpProxy extends RegExpImpl {
private static final Log LOG = LogFactory.getLog(HtmlUnitRegExpProxy.class);
/** Pattern cache */
// XC start
/*
private static final Map PATTENS = new HashMap<>();
*/
private static final ConcurrentLRUCache PATTENS = new ConcurrentLRUCache<>(1001);
// XC end
private final RegExpProxy wrapped_;
private final BrowserVersion browserVersion_;
/**
* Wraps a proxy to enhance it.
* @param wrapped the original proxy
* @param browserVersion the current browser version
*/
public HtmlUnitRegExpProxy(final RegExpProxy wrapped, final BrowserVersion browserVersion) {
wrapped_ = wrapped;
browserVersion_ = browserVersion;
}
/**
* Use the wrapped proxy except for replacement with string arg where it uses Java regular expression.
* {@inheritDoc}
*/
@Override
public Object action(final Context cx, final Scriptable scope, final Scriptable thisObj,
final Object[] args, final int actionType) {
try {
return doAction(cx, scope, thisObj, args, actionType);
}
catch (final RegExStickyNotSupportedException e) {
LOG.warn(e.getMessage(), e);
return wrapped_.action(cx, scope, thisObj, args, actionType);
}
catch (final StackOverflowError e) {
// TODO: We shouldn't have to catch this exception and fall back to Rhino's regex support!
// See HtmlUnitRegExpProxyTest.stackOverflow()
LOG.warn(e.getMessage(), e);
return wrapped_.action(cx, scope, thisObj, args, actionType);
}
}
private Object doAction(final Context cx, final Scriptable scope, final Scriptable thisObj,
final Object[] args, final int actionType) {
// in a first time just improve replacement with a String (not a function)
if ((RA_REPLACE == actionType || RA_REPLACE_ALL == actionType)
&& args.length == 2 && args[1] instanceof String) {
final String thisString = JavaScriptEngine.toString(thisObj);
final String replacement = (String) args[1];
final Object arg0 = args[0];
if (arg0 instanceof String) {
// arg0 should *not* be interpreted as a RegExp
return doStringReplacement(thisString, (String) arg0, replacement, RA_REPLACE_ALL == actionType);
}
if (arg0 instanceof NativeRegExp) {
try {
final NativeRegExp regexp = (NativeRegExp) arg0;
if (RA_REPLACE_ALL == actionType
&& (regexp.getFlags() & NativeRegExp.JSREG_GLOB) == 0) {
throw ScriptRuntime.typeError(
"replaceAll must be called with a global RegExp");
}
final RegExpData reData = new RegExpData(regexp);
final Matcher matcher = reData.getPattern().matcher(thisString);
return doReplacement(thisString, replacement, matcher,
reData.isGlobal() || RA_REPLACE_ALL == actionType);
}
catch (final PatternSyntaxException e) {
LOG.warn(e.getMessage(), e);
}
}
}
else if (RA_MATCH == actionType || RA_SEARCH == actionType) {
if (args.length == 0) {
return null;
}
final Object arg0 = args[0];
final String thisString = JavaScriptEngine.toString(thisObj);
final RegExpData reData;
if (arg0 instanceof NativeRegExp) {
reData = new RegExpData((NativeRegExp) arg0);
}
else {
reData = new RegExpData(JavaScriptEngine.toString(arg0));
}
final Matcher matcher = reData.getPattern().matcher(thisString);
final boolean found = matcher.find();
if (RA_SEARCH == actionType) {
if (found) {
setProperties(matcher, thisString, matcher.start(), matcher.end());
return matcher.start();
}
return -1;
}
if (!found) {
return null;
}
final int index = matcher.start(0);
final List