/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.syncope.core.persistence.jpa.entity; import java.util.Date; import javax.persistence.Basic; import javax.persistence.Lob; import javax.persistence.MappedSuperclass; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.syncope.common.lib.types.AttrSchemaType; import org.apache.syncope.core.provisioning.api.utils.FormatUtils; import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException; import org.apache.syncope.core.persistence.api.entity.PlainAttrValue; import org.apache.syncope.core.persistence.api.entity.PlainSchema; import org.apache.syncope.core.persistence.jpa.validation.entity.PlainAttrValueCheck; import org.apache.syncope.core.spring.security.Encryptor; @MappedSuperclass @PlainAttrValueCheck public abstract class AbstractPlainAttrValue extends AbstractGeneratedKeyEntity implements PlainAttrValue { private static final long serialVersionUID = -9141923816611244785L; private String stringValue; @Temporal(TemporalType.TIMESTAMP) private Date dateValue; @Basic @Min(0) @Max(1) private Integer booleanValue; private Long longValue; private Double doubleValue; @Lob private byte[] binaryValue; @Override public Boolean getBooleanValue() { return booleanValue == null ? null : isBooleanAsInteger(booleanValue); } @Override public void setBooleanValue(final Boolean booleanValue) { this.booleanValue = booleanValue == null ? null : getBooleanAsInteger(booleanValue); } @Override public Date getDateValue() { return dateValue == null ? null : new Date(dateValue.getTime()); } @Override public void setDateValue(final Date dateValue) { this.dateValue = dateValue == null ? null : new Date(dateValue.getTime()); } @Override public Double getDoubleValue() { return doubleValue; } @Override public void setDoubleValue(final Double doubleValue) { this.doubleValue = doubleValue; } @Override public Long getLongValue() { return longValue; } @Override public void setLongValue(final Long longValue) { this.longValue = longValue; } @Override public String getStringValue() { // workaround for Oracle DB considering empty string values as NULL (SYNCOPE-664) return dateValue == null && booleanValue == null && longValue == null && doubleValue == null && binaryValue == null && stringValue == null ? StringUtils.EMPTY : stringValue; } @Override public void setStringValue(final String stringValue) { this.stringValue = stringValue; } @Override public byte[] getBinaryValue() { return binaryValue; } @Override public void setBinaryValue(final byte[] binaryValue) { this.binaryValue = ArrayUtils.clone(binaryValue); } @Override public void parseValue(final PlainSchema schema, final String value) { Exception exception = null; switch (schema.getType()) { case Boolean: this.setBooleanValue(Boolean.parseBoolean(value)); break; case Long: try { this.setLongValue(schema.getConversionPattern() == null ? Long.valueOf(value) : FormatUtils.parseNumber(value, schema.getConversionPattern()).longValue()); } catch (Exception pe) { exception = pe; } break; case Double: try { this.setDoubleValue(schema.getConversionPattern() == null ? Double.valueOf(value) : FormatUtils.parseNumber(value, schema.getConversionPattern()).doubleValue()); } catch (Exception pe) { exception = pe; } break; case Date: try { this.setDateValue(schema.getConversionPattern() == null ? FormatUtils.parseDate(value) : new Date(FormatUtils.parseDate(value, schema.getConversionPattern()).getTime())); } catch (Exception pe) { exception = pe; } break; case Encrypted: try { this.setStringValue(Encryptor.getInstance(schema.getSecretKey()). encode(value, schema.getCipherAlgorithm())); } catch (Exception pe) { exception = pe; } break; case Binary: this.setBinaryValue(Base64.decodeBase64(value)); break; case String: case Enum: default: this.setStringValue(value); } if (exception != null) { throw new ParsingValidationException("While trying to parse '" + value + "' as " + schema.getKey(), exception); } } @SuppressWarnings("unchecked") @Override public <T> T getValue() { return (T) (booleanValue != null ? getBooleanValue() : dateValue != null ? getDateValue() : doubleValue != null ? getDoubleValue() : longValue != null ? getLongValue() : binaryValue != null ? getBinaryValue() : getStringValue()); } @Override public String getValueAsString() { final AttrSchemaType type = getAttr() == null || getAttr().getSchema() == null || getAttr().getSchema().getType() == null ? AttrSchemaType.String : getAttr().getSchema().getType(); return getValueAsString(type); } @Override public String getValueAsString(final AttrSchemaType type) { String result; switch (type) { case Boolean: result = getBooleanValue().toString(); break; case Long: result = getAttr() == null || getAttr().getSchema() == null || getAttr().getSchema().getConversionPattern() == null ? getLongValue().toString() : FormatUtils.format(getLongValue(), getAttr().getSchema().getConversionPattern()); break; case Double: result = getAttr() == null || getAttr().getSchema() == null || getAttr().getSchema().getConversionPattern() == null ? getDoubleValue().toString() : FormatUtils.format(getDoubleValue(), getAttr().getSchema().getConversionPattern()); break; case Date: result = getAttr() == null || getAttr().getSchema() == null || getAttr().getSchema().getConversionPattern() == null ? FormatUtils.format(getDateValue()) : FormatUtils.format( getDateValue(), false, getAttr().getSchema().getConversionPattern()); break; case Binary: result = Base64.encodeBase64String(getBinaryValue()); break; case String: case Enum: case Encrypted: default: result = getStringValue(); break; } return result; } @Override public String toString() { return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE); } }