mirror of https://github.com/apache/lucene.git
SOLR-4518: Improved CurrencyField error messages when attempting to use a Currency that is not supported by the current JVM
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1451931 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
73a0270ad8
commit
16b8796a25
|
@ -199,6 +199,9 @@ Bug Fixes
|
|||
a ratesFileLocation init param, since the previous global default
|
||||
no longer works (hossman)
|
||||
|
||||
* SOLR-4518: Improved CurrencyField error messages when attempting to
|
||||
use a Currency that is not supported by the current JVM. (hossman)
|
||||
|
||||
Optimizations
|
||||
----------------------
|
||||
|
||||
|
|
|
@ -80,6 +80,22 @@ public class CurrencyField extends FieldType implements SchemaAware, ResourceLoa
|
|||
private ExchangeRateProvider provider;
|
||||
public static Logger log = LoggerFactory.getLogger(CurrencyField.class);
|
||||
|
||||
/**
|
||||
* A wrapper arround <code>Currency.getInstance</code> that returns null
|
||||
* instead of throwing <code>IllegalArgumentException</code>
|
||||
* if the specified Currency does not exist in this JVM.
|
||||
*
|
||||
* @see Currency#getInstance(String)
|
||||
*/
|
||||
public static Currency getCurrency(final String code) {
|
||||
try {
|
||||
return Currency.getInstance(code);
|
||||
} catch (IllegalArgumentException e) {
|
||||
/* :NOOP: */
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(IndexSchema schema, Map<String, String> args) {
|
||||
super.init(schema, args);
|
||||
|
@ -100,8 +116,8 @@ public class CurrencyField extends FieldType implements SchemaAware, ResourceLoa
|
|||
this.exchangeRateProviderClass = DEFAULT_RATE_PROVIDER_CLASS;
|
||||
}
|
||||
|
||||
if (java.util.Currency.getInstance(this.defaultCurrency) == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Invalid currency code " + this.defaultCurrency);
|
||||
if (null == getCurrency(this.defaultCurrency)) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Default currency code is not supported by this JVM: " + this.defaultCurrency);
|
||||
}
|
||||
|
||||
String precisionStepString = args.get(PARAM_PRECISION_STEP);
|
||||
|
@ -275,14 +291,17 @@ public class CurrencyField extends FieldType implements SchemaAware, ResourceLoa
|
|||
|
||||
class CurrencyValueSource extends ValueSource {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String targetCurrencyCode;
|
||||
private Currency targetCurrency;
|
||||
private ValueSource currencyValues;
|
||||
private ValueSource amountValues;
|
||||
private final SchemaField sf;
|
||||
|
||||
public CurrencyValueSource(SchemaField sfield, String targetCurrencyCode, QParser parser) {
|
||||
this.sf = sfield;
|
||||
this.targetCurrencyCode = targetCurrencyCode;
|
||||
this.targetCurrency = getCurrency(targetCurrencyCode);
|
||||
if (null == targetCurrency) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Currency code not supported by this JVM: " + targetCurrencyCode);
|
||||
}
|
||||
|
||||
SchemaField amountField = schema.getField(sf.getName() + POLY_FIELD_SEPARATOR + FIELD_SUFFIX_AMOUNT_RAW);
|
||||
SchemaField currencyField = schema.getField(sf.getName() + POLY_FIELD_SEPARATOR + FIELD_SUFFIX_CURRENCY);
|
||||
|
@ -317,7 +336,8 @@ public class CurrencyField extends FieldType implements SchemaAware, ResourceLoa
|
|||
currency = defaultCurrency;
|
||||
}
|
||||
|
||||
if (targetCurrencyOrd == -1 && currency.equals(targetCurrencyCode)) {
|
||||
if (targetCurrencyOrd == -1 &&
|
||||
currency.equals(targetCurrency.getCurrencyCode() )) {
|
||||
targetCurrencyOrd = currencyOrd;
|
||||
}
|
||||
|
||||
|
@ -326,6 +346,17 @@ public class CurrencyField extends FieldType implements SchemaAware, ResourceLoa
|
|||
return currencies.strVal(doc);
|
||||
}
|
||||
}
|
||||
/** throws a (Server Error) SolrException if the code is not valid */
|
||||
private Currency getDocCurrency(int doc, int currencyOrd) {
|
||||
String code = getDocCurrencyCode(doc, currencyOrd);
|
||||
Currency c = getCurrency(code);
|
||||
if (null == c) {
|
||||
throw new SolrException
|
||||
(SolrException.ErrorCode.SERVER_ERROR,
|
||||
"Currency code of document is not supported by this JVM: "+code);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(int doc) {
|
||||
|
@ -360,7 +391,7 @@ public class CurrencyField extends FieldType implements SchemaAware, ResourceLoa
|
|||
int sourceFractionDigits;
|
||||
|
||||
if (targetFractionDigits == -1) {
|
||||
targetFractionDigits = Currency.getInstance(targetCurrencyCode).getDefaultFractionDigits();
|
||||
targetFractionDigits = targetCurrency.getDefaultFractionDigits();
|
||||
}
|
||||
|
||||
if (currencyOrd < MAX_CURRENCIES_TO_CACHE) {
|
||||
|
@ -368,19 +399,18 @@ public class CurrencyField extends FieldType implements SchemaAware, ResourceLoa
|
|||
|
||||
if (exchangeRate <= 0.0) {
|
||||
String sourceCurrencyCode = getDocCurrencyCode(doc, currencyOrd);
|
||||
exchangeRate = exchangeRateCache[currencyOrd] = provider.getExchangeRate(sourceCurrencyCode, targetCurrencyCode);
|
||||
exchangeRate = exchangeRateCache[currencyOrd] = provider.getExchangeRate(sourceCurrencyCode, targetCurrency.getCurrencyCode());
|
||||
}
|
||||
|
||||
sourceFractionDigits = fractionDigitCache[currencyOrd];
|
||||
|
||||
if (sourceFractionDigits == -1) {
|
||||
String sourceCurrencyCode = getDocCurrencyCode(doc, currencyOrd);
|
||||
sourceFractionDigits = fractionDigitCache[currencyOrd] = Currency.getInstance(sourceCurrencyCode).getDefaultFractionDigits();
|
||||
sourceFractionDigits = fractionDigitCache[currencyOrd] = getDocCurrency(doc, currencyOrd).getDefaultFractionDigits();
|
||||
}
|
||||
} else {
|
||||
String sourceCurrencyCode = getDocCurrencyCode(doc, currencyOrd);
|
||||
exchangeRate = provider.getExchangeRate(sourceCurrencyCode, targetCurrencyCode);
|
||||
sourceFractionDigits = Currency.getInstance(sourceCurrencyCode).getDefaultFractionDigits();
|
||||
Currency source = getDocCurrency(doc, currencyOrd);
|
||||
exchangeRate = provider.getExchangeRate(source.getCurrencyCode(), targetCurrency.getCurrencyCode());
|
||||
sourceFractionDigits = source.getDefaultFractionDigits();
|
||||
}
|
||||
|
||||
return CurrencyValue.convertAmount(exchangeRate, sourceFractionDigits, amount, targetFractionDigits);
|
||||
|
@ -431,13 +461,13 @@ public class CurrencyField extends FieldType implements SchemaAware, ResourceLoa
|
|||
|
||||
return !(amountValues != null ? !amountValues.equals(that.amountValues) : that.amountValues != null) &&
|
||||
!(currencyValues != null ? !currencyValues.equals(that.currencyValues) : that.currencyValues != null) &&
|
||||
!(targetCurrencyCode != null ? !targetCurrencyCode.equals(that.targetCurrencyCode) : that.targetCurrencyCode != null);
|
||||
!(targetCurrency != null ? !targetCurrency.equals(that.targetCurrency) : that.targetCurrency != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = targetCurrencyCode != null ? targetCurrencyCode.hashCode() : 0;
|
||||
int result = targetCurrency != null ? targetCurrency.hashCode() : 0;
|
||||
result = 31 * result + (currencyValues != null ? currencyValues.hashCode() : 0);
|
||||
result = 31 * result + (amountValues != null ? amountValues.hashCode() : 0);
|
||||
return result;
|
||||
|
@ -593,37 +623,39 @@ class FileExchangeRateProvider implements ExchangeRateProvider {
|
|||
Node rate = attributes.getNamedItem("rate");
|
||||
|
||||
if (from == null || to == null || rate == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Exchange rate missing attributes (required: from, to, rate) " + rateNode);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Exchange rate missing attributes (required: from, to, rate) " + rateNode);
|
||||
}
|
||||
|
||||
String fromCurrency = from.getNodeValue();
|
||||
String toCurrency = to.getNodeValue();
|
||||
Double exchangeRate;
|
||||
|
||||
if (java.util.Currency.getInstance(fromCurrency) == null ||
|
||||
java.util.Currency.getInstance(toCurrency) == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Could not find from currency specified in exchange rate: " + rateNode);
|
||||
if (null == CurrencyField.getCurrency(fromCurrency)) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Specified 'from' currency not supported in this JVM: " + fromCurrency);
|
||||
}
|
||||
if (null == CurrencyField.getCurrency(toCurrency)) {
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Specified 'to' currency not supported in this JVM: " + toCurrency);
|
||||
}
|
||||
|
||||
try {
|
||||
exchangeRate = Double.parseDouble(rate.getNodeValue());
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Could not parse exchange rate: " + rateNode, e);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Could not parse exchange rate: " + rateNode, e);
|
||||
}
|
||||
|
||||
addRate(tmpRates, fromCurrency, toCurrency, exchangeRate);
|
||||
}
|
||||
} catch (SAXException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error parsing currency config.", e);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error parsing currency config.", e);
|
||||
} catch (IOException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error parsing currency config.", e);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error parsing currency config.", e);
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error parsing currency config.", e);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error parsing currency config.", e);
|
||||
} catch (XPathExpressionException e) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error parsing currency config.", e);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error parsing currency config.", e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new SolrException(ErrorCode.BAD_REQUEST, "Error while opening Currency configuration file "+currencyConfigFile, e);
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Error while opening Currency configuration file "+currencyConfigFile, e);
|
||||
} finally {
|
||||
try {
|
||||
if (is != null) {
|
||||
|
@ -652,7 +684,7 @@ class FileExchangeRateProvider implements ExchangeRateProvider {
|
|||
@Override
|
||||
public void inform(ResourceLoader loader) throws SolrException {
|
||||
if(loader == null) {
|
||||
throw new SolrException(ErrorCode.BAD_REQUEST, "Needs ResourceLoader in order to load config file");
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, "Needs ResourceLoader in order to load config file");
|
||||
}
|
||||
this.loader = loader;
|
||||
reload();
|
||||
|
@ -706,10 +738,10 @@ class CurrencyValue {
|
|||
return null;
|
||||
}
|
||||
|
||||
Currency currency = java.util.Currency.getInstance(code);
|
||||
Currency currency = CurrencyField.getCurrency(code);
|
||||
|
||||
if (currency == null) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Invalid currency code " + code);
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Currency code not supported by this JVM: " + code);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!--
|
||||
|
||||
NOTE: This file contains an invalid currency for hte purposes of error case checking
|
||||
|
||||
-->
|
||||
<currencyConfig version="1.0">
|
||||
<rates>
|
||||
<!-- Fake rates for testing -->
|
||||
<rate from="USD" to="JPY" rate="81.29"/>
|
||||
<rate from="USD" to="HOSS" rate="2.5"/> <!-- BOGUS -->
|
||||
<rate from="EUR" to="USD" rate="0.5"/>
|
||||
</rates>
|
||||
</currencyConfig>
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currency-ft-bogus-code-in-xml" version="1.4">
|
||||
<types>
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<!-- BEGIN BAD STUFF: bad-currency.xml has bogus code-->
|
||||
<fieldType name="currency"
|
||||
class="solr.CurrencyField"
|
||||
defaultCurrency="USD"
|
||||
currencyConfig="bad-currency.xml"
|
||||
multiValued="false" />
|
||||
</types>
|
||||
|
||||
<fields>
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
<field name="money" type="currency" indexed="true" stored="true" />
|
||||
</fields>
|
||||
|
||||
<defaultSearchField>id</defaultSearchField>
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<schema name="bad-schema-currency-ft-bogus-default-code" version="1.4">
|
||||
<types>
|
||||
<fieldType name="string" class="solr.StrField" multiValued="true"/>
|
||||
<!-- BEGIN BAD STUFF: default -->
|
||||
<fieldType name="currency"
|
||||
class="solr.CurrencyField"
|
||||
defaultCurrency="HOSS"
|
||||
currencyConfig="currency.xml"
|
||||
multiValued="false" />
|
||||
</types>
|
||||
|
||||
<fields>
|
||||
<field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
|
||||
<field name="money" type="currency" indexed="true" stored="true" />
|
||||
</fields>
|
||||
|
||||
<defaultSearchField>id</defaultSearchField>
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
|
@ -211,7 +211,18 @@ public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
|
|||
assertQ(req("fl", "*,score", "q",
|
||||
field()+":[3 TO *]"),
|
||||
"//*[@numFound='8']");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBogusCurrency() throws Exception {
|
||||
ignoreException("HOSS");
|
||||
|
||||
// bogus currency
|
||||
assertQEx("Expected exception for invalid currency",
|
||||
req("fl", "*,score", "q",
|
||||
field()+":[3,HOSS TO *]"),
|
||||
400);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCurrencyPointQuery() throws Exception {
|
||||
|
|
|
@ -78,6 +78,13 @@ public class BadIndexSchemaTest extends AbstractBadConfigTestBase {
|
|||
"ratesFileLocation");
|
||||
}
|
||||
|
||||
public void testCurrencyBogusCode() throws Exception {
|
||||
doTest("bad-schema-currency-ft-bogus-default-code.xml",
|
||||
"HOSS");
|
||||
doTest("bad-schema-currency-ft-bogus-code-in-xml.xml",
|
||||
"HOSS");
|
||||
}
|
||||
|
||||
public void testPerFieldtypeSimButNoSchemaSimFactory() throws Exception {
|
||||
doTest("bad-schema-sim-global-vs-ft-mismatch.xml", "global similarity does not support it");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue