Sonar fixes - type: bugs / severity: major

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1871064 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2019-12-08 23:29:50 +00:00
parent 82156bc63c
commit 0f29ae8e4d
18 changed files with 376 additions and 371 deletions

View File

@ -685,8 +685,8 @@ public class AddDimensionedImage {
if(sheet instanceof HSSFSheet) { if(sheet instanceof HSSFSheet) {
// Next, from the columns width, calculate how many co-ordinate // Next, from the columns width, calculate how many co-ordinate
// positons there are per millimetre // positons there are per millimetre
coordinatePositionsPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / coordinatePositionsPerMM = (colWidthMM == 0) ? 0
colWidthMM; : ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / colWidthMM;
// From this figure, determine how many co-ordinat positions to // From this figure, determine how many co-ordinat positions to
// inset the left hand or bottom edge of the image. // inset the left hand or bottom edge of the image.
inset = (int)(coordinatePositionsPerMM * overlapMM); inset = (int)(coordinatePositionsPerMM * overlapMM);
@ -784,8 +784,8 @@ public class AddDimensionedImage {
} }
if(sheet instanceof HSSFSheet) { if(sheet instanceof HSSFSheet) {
rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowCoordinatesPerMM = (rowHeightMM == 0) ? 0
rowHeightMM; : ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowHeightMM;
inset = (int)(overlapMM * rowCoordinatesPerMM); inset = (int)(overlapMM * rowCoordinatesPerMM);
} }
else { else {

View File

@ -17,15 +17,26 @@
package org.apache.poi.ss.examples; package org.apache.poi.ss.examples;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.util.Map;
import java.util.HashMap;
import java.util.Calendar;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.PrintSetup;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/** /**
* A business plan demo * A business plan demo
@ -36,8 +47,6 @@ import java.text.SimpleDateFormat;
*/ */
public class BusinessPlan { public class BusinessPlan {
private static SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM");
private static final String[] titles = { private static final String[] titles = {
"ID", "Project Name", "Owner", "Days", "Start", "End"}; "ID", "Project Name", "Owner", "Days", "Start", "End"};
@ -84,6 +93,8 @@ public class BusinessPlan {
if(args.length > 0 && args[0].equals("-xls")) wb = new HSSFWorkbook(); if(args.length > 0 && args[0].equals("-xls")) wb = new HSSFWorkbook();
else wb = new XSSFWorkbook(); else wb = new XSSFWorkbook();
final SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM");
Map<String, CellStyle> styles = createStyles(wb); Map<String, CellStyle> styles = createStyles(wb);
Sheet sheet = wb.createSheet("Business Plan"); Sheet sheet = wb.createSheet("Business Plan");

View File

@ -17,6 +17,8 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.util.Objects;
import org.apache.poi.util.BitField; import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
@ -30,7 +32,8 @@ import org.apache.poi.util.StringUtil;
* REFERENCE: PG 315 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) * REFERENCE: PG 315 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)
*/ */
public final class FontRecord extends StandardRecord { public final class FontRecord extends StandardRecord {
public final static short sid = 0x0031; // docs are wrong (0x231 Microsoft Support site article Q184647) // docs are wrong (0x231 Microsoft Support site article Q184647)
public final static short sid = 0x0031;
public final static short SS_NONE = 0; public final static short SS_NONE = 0;
public final static short SS_SUPER = 1; public final static short SS_SUPER = 1;
public final static short SS_SUB = 2; public final static short SS_SUB = 2;
@ -39,7 +42,8 @@ public final class FontRecord extends StandardRecord {
public final static byte U_DOUBLE = 2; public final static byte U_DOUBLE = 2;
public final static byte U_SINGLE_ACCOUNTING = 0x21; public final static byte U_SINGLE_ACCOUNTING = 0x21;
public final static byte U_DOUBLE_ACCOUNTING = 0x22; public final static byte U_DOUBLE_ACCOUNTING = 0x22;
private short field_1_font_height; // in units of .05 of a point // in units of .05 of a point
private short field_1_font_height;
private short field_2_attributes; private short field_2_attributes;
// 0 0x01 - Reserved bit must be 0 // 0 0x01 - Reserved bit must be 0
@ -359,24 +363,22 @@ public final class FontRecord extends StandardRecord {
} }
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); return
"[FONT]\n" +
sb.append("[FONT]\n"); " .fontheight = " + HexDump.shortToHex(getFontHeight()) + "\n" +
sb.append(" .fontheight = ").append(HexDump.shortToHex(getFontHeight())).append("\n"); " .attributes = " + HexDump.shortToHex(getAttributes()) + "\n" +
sb.append(" .attributes = ").append(HexDump.shortToHex(getAttributes())).append("\n"); " .italic = " + isItalic() + "\n" +
sb.append(" .italic = ").append(isItalic()).append("\n"); " .strikout = " + isStruckout() + "\n" +
sb.append(" .strikout = ").append(isStruckout()).append("\n"); " .macoutlined= " + isMacoutlined() + "\n" +
sb.append(" .macoutlined= ").append(isMacoutlined()).append("\n"); " .macshadowed= " + isMacshadowed() + "\n" +
sb.append(" .macshadowed= ").append(isMacshadowed()).append("\n"); " .colorpalette = " + HexDump.shortToHex(getColorPaletteIndex()) + "\n" +
sb.append(" .colorpalette = ").append(HexDump.shortToHex(getColorPaletteIndex())).append("\n"); " .boldweight = " + HexDump.shortToHex(getBoldWeight()) + "\n" +
sb.append(" .boldweight = ").append(HexDump.shortToHex(getBoldWeight())).append("\n"); " .supersubscript= " + HexDump.shortToHex(getSuperSubScript()) + "\n" +
sb.append(" .supersubscript= ").append(HexDump.shortToHex(getSuperSubScript())).append("\n"); " .underline = " + HexDump.byteToHex(getUnderline()) + "\n" +
sb.append(" .underline = ").append(HexDump.byteToHex(getUnderline())).append("\n"); " .family = " + HexDump.byteToHex(getFamily()) + "\n" +
sb.append(" .family = ").append(HexDump.byteToHex(getFamily())).append("\n"); " .charset = " + HexDump.byteToHex(getCharset()) + "\n" +
sb.append(" .charset = ").append(HexDump.byteToHex(getCharset())).append("\n"); " .fontname = " + getFontName() + "\n" +
sb.append(" .fontname = ").append(getFontName()).append("\n"); "[/FONT]\n";
sb.append("[/FONT]\n");
return sb.toString();
} }
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
@ -470,6 +472,7 @@ public final class FontRecord extends StandardRecord {
* @return true, if the properties match * @return true, if the properties match
*/ */
public boolean sameProperties(FontRecord other) { public boolean sameProperties(FontRecord other) {
return return
field_1_font_height == other.field_1_font_height && field_1_font_height == other.field_1_font_height &&
field_2_attributes == other.field_2_attributes && field_2_attributes == other.field_2_attributes &&
@ -480,15 +483,11 @@ public final class FontRecord extends StandardRecord {
field_7_family == other.field_7_family && field_7_family == other.field_7_family &&
field_8_charset == other.field_8_charset && field_8_charset == other.field_8_charset &&
field_9_zero == other.field_9_zero && field_9_zero == other.field_9_zero &&
stringEquals(this.field_11_font_name, other.field_11_font_name) Objects.equals(this.field_11_font_name, other.field_11_font_name)
; ;
} }
public boolean equals(Object o) { public boolean equals(Object o) {
return (o instanceof FontRecord) ? sameProperties((FontRecord)o) : false; return (o instanceof FontRecord) && sameProperties((FontRecord) o);
}
private static boolean stringEquals(String s1, String s2) {
return (s1 == s2 || (s1 != null && s1.equals(s2)));
} }
} }

View File

@ -836,8 +836,8 @@ public final class HSSFCellStyle implements CellStyle {
if(_workbook != source._workbook) { if(_workbook != source._workbook) {
lastDateFormat.set(Short.MIN_VALUE); lastDateFormat.set(Short.MIN_VALUE);
lastFormats.set(null); lastFormats.remove();
getDataFormatStringCache.set(null); getDataFormatStringCache.remove();
// Then we need to clone the format string, // Then we need to clone the format string,
// and update the format record for this // and update the format record for this

View File

@ -21,10 +21,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.ShortBufferException;
import org.apache.poi.EncryptedDocumentException; import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
@ -82,7 +79,7 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
@Override @Override
public int read() throws IOException { public int read() throws IOException {
byte[] b = { 0 }; byte[] b = { 0 };
return (read(b) == 1) ? b[0] : -1; return (read(b) == 1) ? (b[0] & 0xFF) : -1;
} }
// do not implement! -> recursion // do not implement! -> recursion

View File

@ -16,7 +16,7 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.poifs.crypt; package org.apache.poi.poifs.crypt;
import java.nio.charset.Charset; import java.nio.charset.StandardCharsets;
import java.security.DigestException; import java.security.DigestException;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.Key; import java.security.Key;
@ -44,11 +44,14 @@ import org.apache.poi.util.StringUtil;
* Helper functions used for standard and agile encryption * Helper functions used for standard and agile encryption
*/ */
@Internal @Internal
public class CryptoFunctions { public final class CryptoFunctions {
//arbitrarily selected; may need to increase //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000; private static final int MAX_RECORD_LENGTH = 100_000;
private CryptoFunctions() {
}
/** /**
* <p><cite>2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)<br> * <p><cite>2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)<br>
* 2.3.4.11 Encryption Key Generation (Agile Encryption)</cite></p> * 2.3.4.11 Encryption Key Generation (Agile Encryption)</cite></p>
@ -78,10 +81,10 @@ public class CryptoFunctions {
* *
* <p>For POI, H_final will be calculated by {@link #generateKey(byte[],HashAlgorithm,byte[],int)}</p> * <p>For POI, H_final will be calculated by {@link #generateKey(byte[],HashAlgorithm,byte[],int)}</p>
* *
* @param password * @param password the password
* @param hashAlgorithm * @param hashAlgorithm the hash algorithm
* @param salt * @param salt the initial salt value
* @param spinCount * @param spinCount the repetition count
* @return the hashed password * @return the hashed password
*/ */
public static byte[] hashPassword(String password, HashAlgorithm hashAlgorithm, byte[] salt, int spinCount) { public static byte[] hashPassword(String password, HashAlgorithm hashAlgorithm, byte[] salt, int spinCount) {
@ -93,10 +96,10 @@ public class CryptoFunctions {
* The difference is, read protection uses the order iterator then hash in the hash loop, whereas write protection * The difference is, read protection uses the order iterator then hash in the hash loop, whereas write protection
* uses first the last hash value and then the current iterator value * uses first the last hash value and then the current iterator value
* *
* @param password * @param password the pasword
* @param hashAlgorithm * @param hashAlgorithm the hash algorighm
* @param salt * @param salt the initial salt value
* @param spinCount * @param spinCount the repetition count
* @param iteratorFirst if true, the iterator is hashed before the n-1 hash value, * @param iteratorFirst if true, the iterator is hashed before the n-1 hash value,
* if false the n-1 hash value is applied first * if false the n-1 hash value is applied first
* @return the hashed password * @return the hashed password
@ -174,10 +177,10 @@ public class CryptoFunctions {
* MUST be padded by appending bytes with a value of 0x36. If the hash value is larger in size than * MUST be padded by appending bytes with a value of 0x36. If the hash value is larger in size than
* PasswordKeyEncryptor.keyBits, the key is obtained by truncating the hash value.</p> * PasswordKeyEncryptor.keyBits, the key is obtained by truncating the hash value.</p>
* *
* @param passwordHash * @param passwordHash the hashed password byte
* @param hashAlgorithm * @param hashAlgorithm the hash algorithm
* @param blockKey * @param blockKey the block key
* @param keySize * @param keySize the key size
* @return intermediate key * @return intermediate key
*/ */
public static byte[] generateKey(byte[] passwordHash, HashAlgorithm hashAlgorithm, byte[] blockKey, int keySize) { public static byte[] generateKey(byte[] passwordHash, HashAlgorithm hashAlgorithm, byte[] blockKey, int keySize) {
@ -198,7 +201,6 @@ public class CryptoFunctions {
* @param vec the initialization vector (IV), can be null * @param vec the initialization vector (IV), can be null
* @param cipherMode Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE * @param cipherMode Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE
* @return the requested cipher * @return the requested cipher
* @throws GeneralSecurityException
* @throws EncryptedDocumentException if the initialization failed or if an algorithm was specified, * @throws EncryptedDocumentException if the initialization failed or if an algorithm was specified,
* which depends on a missing bouncy castle provider * which depends on a missing bouncy castle provider
*/ */
@ -218,7 +220,6 @@ public class CryptoFunctions {
* @param cipherMode Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE * @param cipherMode Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE
* @param padding the padding (null = NOPADDING, ANSIX923Padding, PKCS5Padding, PKCS7Padding, ISO10126Padding, ...) * @param padding the padding (null = NOPADDING, ANSIX923Padding, PKCS5Padding, PKCS7Padding, ISO10126Padding, ...)
* @return the requested cipher * @return the requested cipher
* @throws GeneralSecurityException
* @throws EncryptedDocumentException if the initialization failed or if an algorithm was specified, * @throws EncryptedDocumentException if the initialization failed or if an algorithm was specified,
* which depends on a missing bouncy castle provider * which depends on a missing bouncy castle provider
*/ */
@ -442,12 +443,13 @@ public class CryptoFunctions {
// --> For every bit in the character, starting with the least significant and progressing to (but excluding) // --> For every bit in the character, starting with the least significant and progressing to (but excluding)
// the most significant, if the bit is set, XOR the keys high-order word with the corresponding word from // the most significant, if the bit is set, XOR the keys high-order word with the corresponding word from
// the Encryption Matrix // the Encryption Matrix
for (int i = 0; i < arrByteChars.length; i++) { int line = maxPasswordLength - arrByteChars.length;
int tmp = maxPasswordLength - arrByteChars.length + i; for (byte ch : arrByteChars) {
for (int intBit = 0; intBit < 7; intBit++) { for (int xor : ENCRYPTION_MATRIX[line++]) {
if ((arrByteChars[i] & (0x0001 << intBit)) != 0) { if ((ch & 1) == 1) {
highOrderWord ^= ENCRYPTION_MATRIX[tmp][intBit]; highOrderWord ^= xor;
} }
ch >>>= 1;
} }
} }
@ -480,7 +482,7 @@ public class CryptoFunctions {
int hashedPassword = createXorVerifier2(password); int hashedPassword = createXorVerifier2(password);
return String.format(Locale.ROOT, "%1$02X%2$02X%3$02X%4$02X" return String.format(Locale.ROOT, "%1$02X%2$02X%3$02X%4$02X"
, ( hashedPassword >>> 0 ) & 0xFF , (hashedPassword) & 0xFF
, ( hashedPassword >>> 8 ) & 0xFF , ( hashedPassword >>> 8 ) & 0xFF
, ( hashedPassword >>> 16 ) & 0xFF , ( hashedPassword >>> 16 ) & 0xFF
, ( hashedPassword >>> 24 ) & 0xFF , ( hashedPassword >>> 24 ) & 0xFF
@ -515,7 +517,7 @@ public class CryptoFunctions {
if (password.length() > 15) { if (password.length() > 15) {
password = password.substring(0, 15); password = password.substring(0, 15);
} }
byte[] passBytes = password.getBytes(Charset.forName("ASCII")); byte[] passBytes = password.getBytes(StandardCharsets.US_ASCII);
// this code is based on the libre office implementation. // this code is based on the libre office implementation.
// The MS-OFFCRYPTO misses some infos about the various rotation sizes // The MS-OFFCRYPTO misses some infos about the various rotation sizes

View File

@ -60,7 +60,7 @@ import org.apache.poi.util.Internal;
} catch (ShortBufferException e) { } catch (ShortBufferException e) {
throw new EncryptedDocumentException(e); throw new EncryptedDocumentException(e);
} }
return oneByte[0]; return oneByte[0] & 0xFF;
} }
@Override @Override

View File

@ -51,7 +51,7 @@ import org.apache.poi.util.Internal;
} }
@Override @Override
public void write(int b) { public synchronized void write(int b) {
try { try {
oneByte[0] = (byte)b; oneByte[0] = (byte)b;
cipher.update(oneByte, 0, 1, oneByte, 0); cipher.update(oneByte, 0, 1, oneByte, 0);
@ -62,7 +62,7 @@ import org.apache.poi.util.Internal;
} }
@Override @Override
public void write(byte[] b, int off, int len) { public synchronized void write(byte[] b, int off, int len) {
try { try {
cipher.update(b, off, len, b, off); cipher.update(b, off, len, b, off);
super.write(b, off, len); super.write(b, off, len);

View File

@ -146,7 +146,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi
} }
@Override @Override
public void mark(int ignoredReadlimit) { public synchronized void mark(int ignoredReadlimit) {
_marked_offset = _current_offset; _marked_offset = _current_offset;
_marked_offset_count = Math.max(0, _current_block_count - 1); _marked_offset_count = Math.max(0, _current_block_count - 1);
} }
@ -159,13 +159,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi
} }
byte[] b = new byte[1]; byte[] b = new byte[1];
int result = read(b, 0, 1); int result = read(b, 0, 1);
if(result >= 0) { return (result == EOF) ? EOF : (b[0] & 0xFF);
if(b[0] < 0) {
return b[0]+256;
}
return b[0];
}
return result;
} }
@Override @Override
@ -199,7 +193,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi
* method repositions the stream to its beginning. * method repositions the stream to its beginning.
*/ */
@Override @Override
public void reset() { public synchronized void reset() {
// Special case for reset to the start // Special case for reset to the start
if(_marked_offset == 0 && _marked_offset_count == 0) { if(_marked_offset == 0 && _marked_offset_count == 0) {
_current_block_count = _marked_offset_count; _current_block_count = _marked_offset_count;

View File

@ -47,12 +47,16 @@ public class DrawFactory {
* This is a fallback, for operations where usercode can't set a graphics context. * This is a fallback, for operations where usercode can't set a graphics context.
* Preferably use the rendering hint {@link Drawable#DRAW_FACTORY} to set the factory. * Preferably use the rendering hint {@link Drawable#DRAW_FACTORY} to set the factory.
* *
* @param factory the custom factory * @param factory the custom factory or {@code null} to reset/remove the default factory
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static void setDefaultFactory(DrawFactory factory) { public static void setDefaultFactory(DrawFactory factory) {
if (factory == null) {
defaultFactory.remove();
} else {
defaultFactory.set(factory); defaultFactory.set(factory);
} }
}
/** /**
* Returns the DrawFactory, preferably via a graphics instance. * Returns the DrawFactory, preferably via a graphics instance.

View File

@ -60,56 +60,52 @@ public class DrawShape implements Drawable {
return; return;
} }
final PlaceableShape<?,?> ps = (PlaceableShape<?,?>)shape; final Rectangle2D anchor = getAnchor(graphics, (PlaceableShape<?,?>)shape);
final boolean isHSLF = isHSLF(shape); if (anchor == null) {
return;
}
final Rectangle2D anchor = getAnchor(graphics, ps); if (isHSLF(shape)) {
flipHorizontal(graphics, anchor);
flipVertical(graphics, anchor);
rotate(graphics, anchor);
} else {
rotate(graphics, anchor);
flipHorizontal(graphics, anchor);
flipVertical(graphics, anchor);
}
}
char[] cmds = isHSLF ? new char[]{'h', 'v', 'r'} : new char[]{'r', 'h', 'v'}; private void flipHorizontal(Graphics2D graphics, Rectangle2D anchor) {
for (char ch : cmds) { assert(shape instanceof PlaceableShape && anchor != null);
switch (ch) { if (((PlaceableShape<?,?>)shape).getFlipHorizontal()) {
case 'h':
//flip horizontal
if (ps.getFlipHorizontal()) {
graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY()); graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
graphics.scale(-1, 1); graphics.scale(-1, 1);
graphics.translate(-anchor.getX(), -anchor.getY()); graphics.translate(-anchor.getX(), -anchor.getY());
} }
break; }
case 'v':
//flip vertical private void flipVertical(Graphics2D graphics, Rectangle2D anchor) {
if (ps.getFlipVertical()) { assert(shape instanceof PlaceableShape && anchor != null);
if (((PlaceableShape<?,?>)shape).getFlipVertical()) {
graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight()); graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
graphics.scale(1, -1); graphics.scale(1, -1);
graphics.translate(-anchor.getX(), -anchor.getY()); graphics.translate(-anchor.getX(), -anchor.getY());
} }
break; }
case 'r':
// rotation private void rotate(Graphics2D graphics, Rectangle2D anchor) {
double rotation = ps.getRotation(); assert(shape instanceof PlaceableShape && anchor != null);
double rotation = ((PlaceableShape<?,?>)shape).getRotation();
if (rotation != 0.) { if (rotation != 0.) {
// PowerPoint rotates shapes relative to the geometric center // PowerPoint rotates shapes relative to the geometric center
double centerX = anchor.getCenterX(); graphics.rotate(Math.toRadians(rotation), anchor.getCenterX(), anchor.getCenterY());
double centerY = anchor.getCenterY(); }
// transformation is applied reversed ...
graphics.translate(centerX, centerY);
graphics.rotate(Math.toRadians(rotation));
graphics.translate(-centerX, -centerY);
}
break;
default:
throw new RuntimeException("unexpected transform code " + ch);
}
}
} }
private static double safeScale(double dim1, double dim2) { private static double safeScale(double dim1, double dim2) {
if (dim1 == 0.) { return (dim1 == 0. || dim2 == 0.) ? 1 : dim1/dim2;
return 1;
}
return (dim2 == 0.) ? 1 : dim1/dim2;
} }
@Override @Override
@ -160,15 +156,11 @@ public class DrawShape implements Drawable {
// this handling is only based on try and error ... not sure why h/xslf is handled differently. // this handling is only based on try and error ... not sure why h/xslf is handled differently.
if (!isHSLF) { if (!isHSLF) {
txs2.translate(centerX, centerY); txs2.quadrantRotate(1, centerX, centerY);
txs2.quadrantRotate(1);
txs2.translate(-centerX, -centerY);
txs2.concatenate(tx); txs2.concatenate(tx);
} }
txs2.translate(centerX, centerY); txs2.quadrantRotate(3, centerX, centerY);
txs2.quadrantRotate(3);
txs2.translate(-centerX, -centerY);
if (isHSLF) { if (isHSLF) {
txs2.concatenate(tx); txs2.concatenate(tx);

View File

@ -18,9 +18,11 @@
package org.apache.poi.ss.formula.functions; package org.apache.poi.ss.formula.functions;
import org.apache.poi.ss.formula.OperationEvaluationContext; import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.eval.*; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import java.math.BigDecimal; import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.OperandResolver;
import org.apache.poi.ss.formula.eval.ValueEval;
/** /**
* Implementation for Excel DELTA() function.<p> * Implementation for Excel DELTA() function.<p>
@ -46,33 +48,20 @@ public final class Delta extends Fixed2ArgFunction implements FreeRefFunction {
private final static NumberEval ZERO = new NumberEval(0); private final static NumberEval ZERO = new NumberEval(0);
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg1, ValueEval arg2) { public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg1, ValueEval arg2) {
ValueEval veText1;
try { try {
veText1 = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex); Double number1 = evaluateValue(arg1, srcRowIndex, srcColumnIndex);
} catch (EvaluationException e) {
return e.getErrorEval();
}
String strText1 = OperandResolver.coerceValueToString(veText1);
Double number1 = OperandResolver.parseDouble(strText1);
if (number1 == null) { if (number1 == null) {
return ErrorEval.VALUE_INVALID; return ErrorEval.VALUE_INVALID;
} }
Double number2 = evaluateValue(arg2, srcRowIndex, srcColumnIndex);
ValueEval veText2;
try {
veText2 = OperandResolver.getSingleValue(arg2, srcRowIndex, srcColumnIndex);
} catch (EvaluationException e) {
return e.getErrorEval();
}
String strText2 = OperandResolver.coerceValueToString(veText2);
Double number2 = OperandResolver.parseDouble(strText2);
if (number2 == null) { if (number2 == null) {
return ErrorEval.VALUE_INVALID; return ErrorEval.VALUE_INVALID;
} }
int result = new BigDecimal(number1.doubleValue()).compareTo(new BigDecimal(number2.doubleValue())); return (number1.compareTo(number2) == 0) ? ONE : ZERO;
return result == 0 ? ONE : ZERO; } catch (EvaluationException e) {
return e.getErrorEval();
}
} }
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
@ -82,4 +71,10 @@ public final class Delta extends Fixed2ArgFunction implements FreeRefFunction {
return ErrorEval.VALUE_INVALID; return ErrorEval.VALUE_INVALID;
} }
private static Double evaluateValue(ValueEval arg, int srcRowIndex, int srcColumnIndex) throws EvaluationException {
ValueEval veText = OperandResolver.getSingleValue(arg, srcRowIndex, srcColumnIndex);
String strText1 = OperandResolver.coerceValueToString(veText);
return OperandResolver.parseDouble(strText1);
}
} }

View File

@ -65,6 +65,7 @@ public final class Fixed implements Function1Arg, Function2Arg, Function3Arg {
return ErrorEval.VALUE_INVALID; return ErrorEval.VALUE_INVALID;
} }
@SuppressWarnings("squid:S2111")
private ValueEval fixed( private ValueEval fixed(
ValueEval numberParam, ValueEval placesParam, ValueEval numberParam, ValueEval placesParam,
ValueEval skipThousandsSeparatorParam, ValueEval skipThousandsSeparatorParam,
@ -93,8 +94,8 @@ public final class Fixed implements Function1Arg, Function2Arg, Function3Arg {
NumberFormat nf = NumberFormat.getNumberInstance(Locale.US); NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
DecimalFormat formatter = (DecimalFormat)nf; DecimalFormat formatter = (DecimalFormat)nf;
formatter.setGroupingUsed(!(skipThousandsSeparator != null && skipThousandsSeparator)); formatter.setGroupingUsed(!(skipThousandsSeparator != null && skipThousandsSeparator));
formatter.setMinimumFractionDigits(places >= 0 ? places : 0); formatter.setMinimumFractionDigits(Math.max(places, 0));
formatter.setMaximumFractionDigits(places >= 0 ? places : 0); formatter.setMaximumFractionDigits(Math.max(places, 0));
String numberString = formatter.format(number.doubleValue()); String numberString = formatter.format(number.doubleValue());
// Return the result as a StringEval. // Return the result as a StringEval.

View File

@ -31,6 +31,8 @@ import org.apache.poi.ss.formula.eval.ValueEval;
* @see <a href="http://office.microsoft.com/en-us/excel-help/irr-HP005209146.aspx">Excel IRR</a> * @see <a href="http://office.microsoft.com/en-us/excel-help/irr-HP005209146.aspx">Excel IRR</a>
*/ */
public final class Irr implements Function { public final class Irr implements Function {
private static final int MAX_ITERATION_COUNT = 20;
private static final double ABSOLUTE_ACCURACY = 1E-7;
public ValueEval evaluate(final ValueEval[] args, final int srcRowIndex, final int srcColumnIndex) { public ValueEval evaluate(final ValueEval[] args, final int srcRowIndex, final int srcColumnIndex) {
@ -89,27 +91,24 @@ public final class Irr implements Function {
* http://en.wikipedia.org/wiki/Newton%27s_method</a> * http://en.wikipedia.org/wiki/Newton%27s_method</a>
*/ */
public static double irr(double[] values, double guess) { public static double irr(double[] values, double guess) {
final int maxIterationCount = 20;
final double absoluteAccuracy = 1E-7;
double x0 = guess; double x0 = guess;
double x1;
int i = 0; for (int i = 0; i < MAX_ITERATION_COUNT; i++) {
while (i < maxIterationCount) {
// the value of the function (NPV) and its derivate can be calculated in the same loop // the value of the function (NPV) and its derivate can be calculated in the same loop
final double factor = 1.0 + x0; final double factor = 1.0 + x0;
int k = 0; double denominator = factor;
double fValue = values[k];
double fDerivative = 0;
for (double denominator = factor; ++k < values.length; ) {
final double value = values[k];
fValue += value / denominator;
denominator *= factor;
if (denominator == 0) { if (denominator == 0) {
return Double.NaN; return Double.NaN;
} }
double fValue = values[0];
double fDerivative = 0;
for (int k = 1; k < values.length; k++) {
final double value = values[k];
fValue += value / denominator;
denominator *= factor;
fDerivative -= k * value / denominator; fDerivative -= k * value / denominator;
} }
@ -117,14 +116,13 @@ public final class Irr implements Function {
if (fDerivative == 0) { if (fDerivative == 0) {
return Double.NaN; return Double.NaN;
} }
x1 = x0 - fValue/fDerivative; double x1 = x0 - fValue/fDerivative;
if (Math.abs(x1 - x0) <= absoluteAccuracy) { if (Math.abs(x1 - x0) <= ABSOLUTE_ACCURACY) {
return x1; return x1;
} }
x0 = x1; x0 = x1;
++i;
} }
// maximum number of iterations is exceeded // maximum number of iterations is exceeded
return Double.NaN; return Double.NaN;

View File

@ -281,7 +281,7 @@ public class DataFormatter implements Observer {
/** /**
* Return a Format for the given cell if one exists, otherwise try to * Return a Format for the given cell if one exists, otherwise try to
* create one. This method will return <code>null</code> if the any of the * create one. This method will return <code>null</code> if any of the
* following is true: * following is true:
* <ul> * <ul>
* <li>the cell's style is null</li> * <li>the cell's style is null</li>
@ -826,6 +826,16 @@ public class DataFormatter implements Observer {
return null; return null;
} }
Format dateFormat = getFormat(cell, cfEvaluator); Format dateFormat = getFormat(cell, cfEvaluator);
if (dateFormat == null) {
if (defaultDateformat == null) {
DateFormatSymbols sym = DateFormatSymbols.getInstance(LocaleUtil.getUserLocale());
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", sym);
sdf.setTimeZone(LocaleUtil.getUserTimeZone());
dateFormat = sdf;
} else {
dateFormat = defaultNumFormat;
}
}
synchronized (dateFormat) { synchronized (dateFormat) {
if(dateFormat instanceof ExcelStyleDateFormatter) { if(dateFormat instanceof ExcelStyleDateFormatter) {
// Hint about the raw excel value // Hint about the raw excel value

View File

@ -55,6 +55,7 @@ public class ExcelGeneralNumberFormat extends Format {
DataFormatter.setExcelStyleRoundingMode(decimalFormat); DataFormatter.setExcelStyleRoundingMode(decimalFormat);
} }
@SuppressWarnings("squid:S2111")
public StringBuffer format(Object number, StringBuffer toAppendTo, FieldPosition pos) { public StringBuffer format(Object number, StringBuffer toAppendTo, FieldPosition pos) {
final double value; final double value;
if (number instanceof Number) { if (number instanceof Number) {

View File

@ -104,6 +104,7 @@ public class FractionFormat extends Format {
maxDenom = tmpMax; maxDenom = tmpMax;
} }
@SuppressWarnings("squid:S2111")
public String format(Number num) { public String format(Number num) {
final BigDecimal doubleValue = new BigDecimal(num.doubleValue()); final BigDecimal doubleValue = new BigDecimal(num.doubleValue());

View File

@ -820,7 +820,7 @@ public class HemfPlusDraw {
} }
} }
@SuppressWarnings("squid:S2111")
static double round10(double d) { static double round10(double d) {
return new BigDecimal(d).setScale(10, RoundingMode.HALF_UP).doubleValue(); return new BigDecimal(d).setScale(10, RoundingMode.HALF_UP).doubleValue();
} }