You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by gb...@apache.org on 2013/03/06 17:46:37 UTC

svn commit: r1453416 [5/16] - in /pdfbox/trunk/preflight: ./ src/main/java/org/apache/pdfbox/preflight/ src/main/java/org/apache/pdfbox/preflight/action/ src/main/java/org/apache/pdfbox/preflight/annotation/ src/main/java/org/apache/pdfbox/preflight/an...

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java Wed Mar  6 16:46:35 2013
@@ -92,471 +92,531 @@ import org.apache.pdfbox.util.operator.S
 import org.apache.pdfbox.util.operator.SetTextRenderingMode;
 import org.apache.pdfbox.util.operator.SetTextRise;
 import org.apache.pdfbox.util.operator.SetWordSpacing;
+
 /**
- * This class inherits from org.apache.pdfbox.util.PDFStreamEngine to allow the
- * validation of specific rules in ContentStream.
+ * This class inherits from org.apache.pdfbox.util.PDFStreamEngine to allow the validation of specific rules in
+ * ContentStream.
  */
-public abstract class ContentStreamEngine extends PDFStreamEngine {
+public abstract class ContentStreamEngine extends PDFStreamEngine
+{
 
-	private enum ColorSpaceType {
-		RGB,
-		CMYK,
-		ALL;
-	}
-
-	protected PreflightContext context = null;
-
-	protected COSDocument cosDocument = null;
-
-	protected PDPage processeedPage = null;
-
-	protected Map<String,OperatorProcessor> contentStreamEngineOperators = new HashMap<String,OperatorProcessor>();
-
-	public ContentStreamEngine(PreflightContext _context, PDPage _page) {
-		super();
-		this.context = _context;
-		this.cosDocument = _context.getDocument().getDocument();
-		this.processeedPage = _page;
-
-		// Graphics operators
-		registerOperatorProcessor("w", new SetLineWidth());
-		registerOperatorProcessor("cm", new Concatenate());
-
-		registerOperatorProcessor("CS", new SetStrokingColorSpace());
-		registerOperatorProcessor("cs", new SetNonStrokingColorSpace());
-		registerOperatorProcessor("d", new SetLineDashPattern());
-		registerOperatorProcessor("Do", new Invoke());
-
-		registerOperatorProcessor("j", new SetLineJoinStyle());
-		registerOperatorProcessor("J", new SetLineCapStyle());
-		registerOperatorProcessor("K", new SetStrokingCMYKColor());
-		registerOperatorProcessor("k", new SetNonStrokingCMYKColor());
-
-		registerOperatorProcessor("rg", new SetNonStrokingRGBColor());
-		registerOperatorProcessor("RG", new SetStrokingRGBColor());
-
-		registerOperatorProcessor("SC", new SetStrokingColor());
-		registerOperatorProcessor("SCN", new SetStrokingColor());
-		registerOperatorProcessor("sc", new SetNonStrokingColor());
-		registerOperatorProcessor("scn", new SetNonStrokingColor());
-
-		// Graphics state
-		registerOperatorProcessor("Q", new GRestore());
-		registerOperatorProcessor("q", new GSave());
-
-		// Text operators
-		registerOperatorProcessor("BT", new BeginText());
-		registerOperatorProcessor("ET", new EndText());
-		registerOperatorProcessor("Tf", new SetTextFont());
-		registerOperatorProcessor("Tr", new SetTextRenderingMode());
-		registerOperatorProcessor("Tm", new SetMatrix());
-		registerOperatorProcessor("Td", new MoveText());
-		registerOperatorProcessor("T*", new NextLine());
-		registerOperatorProcessor("TD", new MoveTextSetLeading());
-		registerOperatorProcessor("Tc", new SetCharSpacing());
-		registerOperatorProcessor("TL", new SetTextLeading());
-		registerOperatorProcessor("Ts", new SetTextRise());
-		registerOperatorProcessor("Tw", new SetWordSpacing());
-		registerOperatorProcessor("Tz", new SetHorizontalTextScaling());
-
-		/* Do not use the PDFBox Operator, because of the PageDrawer class cast
-		 * Or because the Operator doesn't exist
-		 */
-		StubOperator stubOp = new StubOperator();
-		registerOperatorProcessor("l", stubOp);
-		registerOperatorProcessor("re", stubOp);
-		registerOperatorProcessor("c", stubOp);
-		registerOperatorProcessor("y", stubOp);
-		registerOperatorProcessor("v", stubOp);
-		registerOperatorProcessor("n", stubOp);
-		registerOperatorProcessor("BI", stubOp);
-		registerOperatorProcessor("EI", stubOp);
-		registerOperatorProcessor("m", stubOp);
-		registerOperatorProcessor("W*", stubOp);
-		registerOperatorProcessor("W", stubOp);
-		registerOperatorProcessor("h", stubOp);
-
-		registerOperatorProcessor("Tj", stubOp);
-		registerOperatorProcessor("TJ", stubOp);
-		registerOperatorProcessor("'", stubOp);
-		registerOperatorProcessor("\"", stubOp);
-
-		registerOperatorProcessor("b", stubOp);
-		registerOperatorProcessor("B", stubOp);
-		registerOperatorProcessor("b*", stubOp);
-		registerOperatorProcessor("B*", stubOp);
-
-		registerOperatorProcessor("BDC", stubOp);
-		registerOperatorProcessor("BMC", stubOp);
-		registerOperatorProcessor("DP", stubOp);
-		registerOperatorProcessor("EMC", stubOp);
-
-		registerOperatorProcessor("d0", stubOp);
-		registerOperatorProcessor("d1", stubOp);
-
-		registerOperatorProcessor("f", stubOp);
-		registerOperatorProcessor("F", stubOp);
-		registerOperatorProcessor("f*", stubOp);
-
-		registerOperatorProcessor("g", stubOp);
-		registerOperatorProcessor("G", stubOp);
-
-		registerOperatorProcessor("M", stubOp);
-		registerOperatorProcessor("MP", stubOp);
-
-		registerOperatorProcessor("gs", stubOp);
-		registerOperatorProcessor("h", stubOp);
-		registerOperatorProcessor("i", stubOp);
-
-		registerOperatorProcessor("ri", stubOp);
-		registerOperatorProcessor("s", stubOp);
-		registerOperatorProcessor("S", stubOp);
-		registerOperatorProcessor("sh", stubOp);
-	}
-
-	public final void registerOperatorProcessor( String operator, OperatorProcessor op )
-	{
-		super.registerOperatorProcessor(operator, op);
-		contentStreamEngineOperators.put( operator, op );
-	}
-
-
-	/**
-	 * Check operands of the "ri" operator. Operands must exist in the
-	 * RenderingIntent list. (net.awl.edoc.pdfa.validation.utils.RenderingIntents)
-	 * 
-	 * @param operator
-	 *          the "ri" operator
-	 * @param arguments
-	 *          the "ri" operands
-	 * @throws ContentStreamException
-	 *           ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY if the operand is invalid
-	 */
-	protected void validRenderingIntent(PDFOperator operator, List arguments)
-			throws ContentStreamException {
-		if ("ri".equals(operator.getOperation())) {
-			String riArgument0 = "";
-			if (arguments.get(0) instanceof COSName) {
-				riArgument0 = ((COSName)arguments.get(0)).getName();
-			} else if (arguments.get(0) instanceof String) {
-				riArgument0 = (String)arguments.get(0);
-			}
-
-			if (!RenderingIntents.contains(riArgument0)) {
-				registerError("Unexpected value '" + arguments.get(0)
-						+ "' for ri operand. ", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
-				return;
-			}
-		}
-	}
-
-	/**
-	 * Valid the number of graphic states if the operator is the Save Graphic state operator ("q")
-	 * @param operator
-	 * @throws ContentStreamException
-	 */
-	protected void validNumberOfGraphicStates(PDFOperator operator) throws ContentStreamException  {
-		if ("q".equals(operator.getOperation())) {
-			int numberOfGraphicStates = this.getGraphicsStack().size();
-			if (numberOfGraphicStates > MAX_GRAPHIC_STATES) {
-				registerError("Too many graphic states", ERROR_GRAPHIC_TOO_MANY_GRAPHIC_STATES);
-				return;
-			}
-		}
-	}
-
-	/**
-	 * Throw a ContentStreamException if the LZW filter is used in a InlinedImage.
-	 * 
-	 * @param operator
-	 *          the InlinedImage object (BI to EI)
-	 * @throws ContentStreamException
-	 */
-	protected void validImageFilter(PDFOperator operator)throws ContentStreamException {
-		COSDictionary dict = operator.getImageParameters().getDictionary();
-		/* 
-		 * Search a Filter declaration in the InlinedImage dictionary.
-		 * The LZWDecode Filter is forbidden.
-		 */
-		COSBase filter = dict.getDictionaryObject(COSName.F, COSName.FILTER);
-		FilterHelper.isAuthorizedFilter(context, COSUtils.getAsString(filter, this.context.getDocument().getDocument()));
-	}
-
-	/**
-	 * This method validates if the ColorSpace used by the InlinedImage is
-	 * consistent with the color space defined in OutputIntent dictionaries.
-	 * 
-	 * @param operator
-	 *          the InlinedImage object (BI to EI)
-	 * @throws ContentStreamException
-	 */
-	protected void validImageColorSpace(PDFOperator operator) throws ContentStreamException, IOException {
-		COSDictionary dict = operator.getImageParameters().getDictionary();
-
-		COSBase csInlinedBase = dict.getItem(COSName.CS);
-		ColorSpaceHelper csHelper = null;
-		if (csInlinedBase != null) {
-			if (COSUtils.isString(csInlinedBase, cosDocument)) {
-				/*
-				 * In InlinedImage only DeviceGray/RGB/CMYK and
-				 * restricted Indexed color spaces are allowed.
-				 */
-				String colorSpace = COSUtils.getAsString(csInlinedBase, cosDocument);
-				ColorSpaces cs = null;
-
-				try {
-					cs = ColorSpaces.valueOf(colorSpace);
-				} catch (IllegalArgumentException e) {
-					/* 
-					 * The color space is unknown. 
-					 * Try to access the resources dictionary, the color space can be a reference.
-					 */
-					PDColorSpace pdCS = (PDColorSpace) this.getColorSpaces().get(colorSpace);
-					if (pdCS != null) {
-						cs = ColorSpaces.valueOf(pdCS.getName());
-						PreflightConfiguration cfg = context.getConfig();
-						ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
-						csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.ONLY_DEVICE);
-					}
-				}
-
-				if (cs == null) {
-					registerError("The ColorSpace is unknown", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
-					return;
-				}
-			}
-
-			if (csHelper == null) {
-				PDColorSpace pdCS = PDColorSpaceFactory.createColorSpace(csInlinedBase);
-				PreflightConfiguration cfg = context.getConfig();
-				ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
-				csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.ONLY_DEVICE);
-			}
-
-			csHelper.validate();
-		}
-	}
-
-	/**
-	 * This method validates if the ColorOperator can be used with the color space
-	 * defined in OutputIntent dictionaries.
-	 * 
-	 * @param operator
-	 *          the color operator
-	 * @throws ContentStreamException
-	 */
-	protected void checkColorOperators(String operation)
-			throws ContentStreamException {
-		PDColorState cs = getColorState(operation);
-
-		if ("rg".equals(operation) || "RG".equals(operation)) {
-			if (!validColorSpace(cs, ColorSpaceType.RGB)) {
-				registerError("The operator \"" + operation
-						+ "\" can't be used with CMYK Profile",
-						ERROR_GRAPHIC_INVALID_COLOR_SPACE_RGB);
-				return;
-			}
-		}
-
-		if ("k".equals(operation) || "K".equals(operation)) {
-			if (!validColorSpace(cs, ColorSpaceType.CMYK)) {
-				registerError("The operator \"" + operation
-						+ "\" can't be used with RGB Profile",
-						ERROR_GRAPHIC_INVALID_COLOR_SPACE_CMYK);
-				return;
-			}
-		}
-
-		if ("g".equals(operation) || "G".equals(operation)) {
-			if (!validColorSpace(cs, ColorSpaceType.ALL)) {
-				registerError("The operator \"" + operation
-						+ "\" can't be used without Color Profile",
-						ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING);
-				return;
-			}
-		}
-
-		if ("f".equals(operation) || "F".equals(operation)
-				|| "f*".equals(operation) || "B".equals(operation)
-				|| "B*".equals(operation) || "b".equals(operation)
-				|| "b*".equals(operation)) {
-			if (!validColorSpace(cs, ColorSpaceType.ALL)) {
-				// The default fill color needs an OutputIntent
-				registerError("The operator \"" + operation
-						+ "\" can't be used without Color Profile",
-						ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING);
-				return;
-			}
-		}
-	}
-
-	private boolean validColorSpace(PDColorState colorState, ColorSpaceType expectedType)
-			throws ContentStreamException {
-		boolean result = true;
-		if (colorState == null) {
-			result = validColorSpaceDestOutputProfile(expectedType);
-		} else {
-			PDColorSpace cs = colorState.getColorSpace();
-			if (isDeviceIndependent(cs, expectedType)) {
-				result = true;
-			} else {
-				result = validColorSpaceDestOutputProfile(expectedType);
-			}
-		}		
-		return result;
-	}
-
-	/**
-	 * Check if the ColorProfile provided by the DestOutputProfile entry isn't null and 
-	 * if the ColorSpace represented by the Profile has the right type (RGB or CMYK)
-	 * 
-	 * @param expectedType
-	 * @return
-	 */
-	private boolean validColorSpaceDestOutputProfile(ColorSpaceType expectedType) throws ContentStreamException {
-		boolean result = false;
-		ICCProfileWrapper profileWrapper;
-		try {
-			profileWrapper = ICCProfileWrapper.getOrSearchICCProfile(context);
-			if (profileWrapper != null) {
-				switch (expectedType) {
-				case RGB:
-					result = profileWrapper.isRGBColorSpace();
-					break;
-				case CMYK:
-					result = profileWrapper.isCMYKColorSpace();
-					break;
-				default:
-					result = true;
-					break;
-				}
-			}
-		} catch (ValidationException e) {
-			throw new ContentStreamException(e);
-		}
-		return result;
-	}
-
-	/**
-	 * Return true if the given ColorSpace is an independent device ColorSpace.
-	 * If the color space is an ICCBased, check the embedded profile color (RGB or CMYK)
-	 * @param cs
-	 * @return
-	 */
-	private boolean isDeviceIndependent(PDColorSpace cs, ColorSpaceType expectedType) {
-		boolean result =  (cs instanceof PDCalGray || cs instanceof PDCalRGB || cs instanceof PDLab);
-		if (cs instanceof PDICCBased) {
-			PDICCBased iccBased = (PDICCBased)cs;
-			try {
-				ColorSpace iccColorSpace = iccBased.getJavaColorSpace();
-				switch (expectedType) {
-				case RGB:
-					result = (iccColorSpace.getType() == ICC_ColorSpace.TYPE_RGB);
-					break;
-				case CMYK:
-					result = (iccColorSpace.getType() == ICC_ColorSpace.TYPE_CMYK);
-					break;
-				default:
-					result = true;
-					break;
-				}
-			} catch (IOException e) {
-				result = false;
-			}			
-		}
-		return result;
-	}
-
-	/**
-	 * Return the current color state used by the operation
-	 * @param operation
-	 * @return
-	 */
-	private PDColorState getColorState(String operation) {
-		if (getGraphicsState() == null) {
-			return null;
-		}
-
-		PDColorState colorState;
-		if (operation.equals("rg") || operation.equals("g") || operation.equals("k") 
-				|| operation.equals("f") || operation.equals("F") || operation.equals("f*")) {
-			// non stroking operator
-			colorState = getGraphicsState().getNonStrokingColor();
-		} else {
-			// stroking operator
-			colorState = getGraphicsState().getStrokingColor();
-		}
-		return colorState;
-	}
-
-	/**
-	 * This method validates if the ColorSpace used as operand is consistent with
-	 * the color space defined in OutputIntent dictionaries.
-	 * 
-	 * @param operator
-	 * @param arguments
-	 * @throws IOException
-	 */
-	protected void checkSetColorSpaceOperators(PDFOperator operator, List<?> arguments) 
-			throws IOException {
-		if (!("CS".equals(operator.getOperation()) || "cs".equals(operator.getOperation()))) {
-			return;
-		}
-
-		String colorSpaceName = null;
-		if (arguments.get(0) instanceof String) {
-			colorSpaceName = (String) arguments.get(0);
-		} else if (arguments.get(0) instanceof COSString) {
-			colorSpaceName = ((COSString) arguments.get(0)).toString();
-		} else if (arguments.get(0) instanceof COSName) {
-			colorSpaceName = ((COSName) arguments.get(0)).getName();
-		} else {
-			registerError("The operand doesn't have the expected type",	ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
-			return;
-		}
-
-		ColorSpaceHelper csHelper = null;
-		ColorSpaces cs = null;
-		try {
-			cs = ColorSpaces.valueOf(colorSpaceName);
-		} catch (IllegalArgumentException e) {
-			/*
-			 * The color space is unknown.
-			 * Try to access the resources dictionary, 
-			 * the color space can be a reference. 
-			 */
-			PDColorSpace pdCS = (PDColorSpace) this.getColorSpaces().get(colorSpaceName);
-			if (pdCS != null) {
-				cs = ColorSpaces.valueOf(pdCS.getName());
-				PreflightConfiguration cfg = context.getConfig();
-				ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
-				csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.NO_RESTRICTION);
-			}
-		}
-
-		if (cs == null) {
-			registerError("The ColorSpace is unknown", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
-			return;
-		}
-
-		if (csHelper == null) {
-			PDColorSpace pdCS = PDColorSpaceFactory.createColorSpace(COSName.getPDFName(colorSpaceName));
-			PreflightConfiguration cfg = context.getConfig();
-			ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
-			csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.NO_RESTRICTION);
-		}
-
-		csHelper.validate();
-	}
-
-	/**
-	 * Add a validation error into the PreflightContext
-	 * 
-	 * @param msg exception details
-	 * @param errorCode the error code.
-	 */
-	protected void registerError(String msg, String errorCode) {
-			ValidationError error = new ValidationError(errorCode, msg);
-			this.context.addValidationError(error);
-	}
+    private enum ColorSpaceType
+    {
+        RGB, CMYK, ALL;
+    }
+
+    protected PreflightContext context = null;
+
+    protected COSDocument cosDocument = null;
+
+    protected PDPage processeedPage = null;
+
+    protected Map<String, OperatorProcessor> contentStreamEngineOperators = new HashMap<String, OperatorProcessor>();
+
+    public ContentStreamEngine(PreflightContext _context, PDPage _page)
+    {
+        super();
+        this.context = _context;
+        this.cosDocument = _context.getDocument().getDocument();
+        this.processeedPage = _page;
+
+        // Graphics operators
+        registerOperatorProcessor("w", new SetLineWidth());
+        registerOperatorProcessor("cm", new Concatenate());
+
+        registerOperatorProcessor("CS", new SetStrokingColorSpace());
+        registerOperatorProcessor("cs", new SetNonStrokingColorSpace());
+        registerOperatorProcessor("d", new SetLineDashPattern());
+        registerOperatorProcessor("Do", new Invoke());
+
+        registerOperatorProcessor("j", new SetLineJoinStyle());
+        registerOperatorProcessor("J", new SetLineCapStyle());
+        registerOperatorProcessor("K", new SetStrokingCMYKColor());
+        registerOperatorProcessor("k", new SetNonStrokingCMYKColor());
+
+        registerOperatorProcessor("rg", new SetNonStrokingRGBColor());
+        registerOperatorProcessor("RG", new SetStrokingRGBColor());
+
+        registerOperatorProcessor("SC", new SetStrokingColor());
+        registerOperatorProcessor("SCN", new SetStrokingColor());
+        registerOperatorProcessor("sc", new SetNonStrokingColor());
+        registerOperatorProcessor("scn", new SetNonStrokingColor());
+
+        // Graphics state
+        registerOperatorProcessor("Q", new GRestore());
+        registerOperatorProcessor("q", new GSave());
+
+        // Text operators
+        registerOperatorProcessor("BT", new BeginText());
+        registerOperatorProcessor("ET", new EndText());
+        registerOperatorProcessor("Tf", new SetTextFont());
+        registerOperatorProcessor("Tr", new SetTextRenderingMode());
+        registerOperatorProcessor("Tm", new SetMatrix());
+        registerOperatorProcessor("Td", new MoveText());
+        registerOperatorProcessor("T*", new NextLine());
+        registerOperatorProcessor("TD", new MoveTextSetLeading());
+        registerOperatorProcessor("Tc", new SetCharSpacing());
+        registerOperatorProcessor("TL", new SetTextLeading());
+        registerOperatorProcessor("Ts", new SetTextRise());
+        registerOperatorProcessor("Tw", new SetWordSpacing());
+        registerOperatorProcessor("Tz", new SetHorizontalTextScaling());
+
+        /*
+         * Do not use the PDFBox Operator, because of the PageDrawer class cast Or because the Operator doesn't exist
+         */
+        StubOperator stubOp = new StubOperator();
+        registerOperatorProcessor("l", stubOp);
+        registerOperatorProcessor("re", stubOp);
+        registerOperatorProcessor("c", stubOp);
+        registerOperatorProcessor("y", stubOp);
+        registerOperatorProcessor("v", stubOp);
+        registerOperatorProcessor("n", stubOp);
+        registerOperatorProcessor("BI", stubOp);
+        registerOperatorProcessor("EI", stubOp);
+        registerOperatorProcessor("m", stubOp);
+        registerOperatorProcessor("W*", stubOp);
+        registerOperatorProcessor("W", stubOp);
+        registerOperatorProcessor("h", stubOp);
+
+        registerOperatorProcessor("Tj", stubOp);
+        registerOperatorProcessor("TJ", stubOp);
+        registerOperatorProcessor("'", stubOp);
+        registerOperatorProcessor("\"", stubOp);
+
+        registerOperatorProcessor("b", stubOp);
+        registerOperatorProcessor("B", stubOp);
+        registerOperatorProcessor("b*", stubOp);
+        registerOperatorProcessor("B*", stubOp);
+
+        registerOperatorProcessor("BDC", stubOp);
+        registerOperatorProcessor("BMC", stubOp);
+        registerOperatorProcessor("DP", stubOp);
+        registerOperatorProcessor("EMC", stubOp);
+
+        registerOperatorProcessor("d0", stubOp);
+        registerOperatorProcessor("d1", stubOp);
+
+        registerOperatorProcessor("f", stubOp);
+        registerOperatorProcessor("F", stubOp);
+        registerOperatorProcessor("f*", stubOp);
+
+        registerOperatorProcessor("g", stubOp);
+        registerOperatorProcessor("G", stubOp);
+
+        registerOperatorProcessor("M", stubOp);
+        registerOperatorProcessor("MP", stubOp);
+
+        registerOperatorProcessor("gs", stubOp);
+        registerOperatorProcessor("h", stubOp);
+        registerOperatorProcessor("i", stubOp);
+
+        registerOperatorProcessor("ri", stubOp);
+        registerOperatorProcessor("s", stubOp);
+        registerOperatorProcessor("S", stubOp);
+        registerOperatorProcessor("sh", stubOp);
+    }
+
+    public final void registerOperatorProcessor(String operator, OperatorProcessor op)
+    {
+        super.registerOperatorProcessor(operator, op);
+        contentStreamEngineOperators.put(operator, op);
+    }
+
+    /**
+     * Check operands of the "ri" operator. Operands must exist in the RenderingIntent list.
+     * (net.awl.edoc.pdfa.validation.utils.RenderingIntents)
+     * 
+     * @param operator
+     *            the "ri" operator
+     * @param arguments
+     *            the "ri" operands
+     * @throws ContentStreamException
+     *             ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY if the operand is invalid
+     */
+    protected void validRenderingIntent(PDFOperator operator, List arguments) throws ContentStreamException
+    {
+        if ("ri".equals(operator.getOperation()))
+        {
+            String riArgument0 = "";
+            if (arguments.get(0) instanceof COSName)
+            {
+                riArgument0 = ((COSName) arguments.get(0)).getName();
+            }
+            else if (arguments.get(0) instanceof String)
+            {
+                riArgument0 = (String) arguments.get(0);
+            }
+
+            if (!RenderingIntents.contains(riArgument0))
+            {
+                registerError("Unexpected value '" + arguments.get(0) + "' for ri operand. ",
+                        ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Valid the number of graphic states if the operator is the Save Graphic state operator ("q")
+     * 
+     * @param operator
+     * @throws ContentStreamException
+     */
+    protected void validNumberOfGraphicStates(PDFOperator operator) throws ContentStreamException
+    {
+        if ("q".equals(operator.getOperation()))
+        {
+            int numberOfGraphicStates = this.getGraphicsStack().size();
+            if (numberOfGraphicStates > MAX_GRAPHIC_STATES)
+            {
+                registerError("Too many graphic states", ERROR_GRAPHIC_TOO_MANY_GRAPHIC_STATES);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Throw a ContentStreamException if the LZW filter is used in a InlinedImage.
+     * 
+     * @param operator
+     *            the InlinedImage object (BI to EI)
+     * @throws ContentStreamException
+     */
+    protected void validImageFilter(PDFOperator operator) throws ContentStreamException
+    {
+        COSDictionary dict = operator.getImageParameters().getDictionary();
+        /*
+         * Search a Filter declaration in the InlinedImage dictionary. The LZWDecode Filter is forbidden.
+         */
+        COSBase filter = dict.getDictionaryObject(COSName.F, COSName.FILTER);
+        FilterHelper
+                .isAuthorizedFilter(context, COSUtils.getAsString(filter, this.context.getDocument().getDocument()));
+    }
+
+    /**
+     * This method validates if the ColorSpace used by the InlinedImage is consistent with the color space defined in
+     * OutputIntent dictionaries.
+     * 
+     * @param operator
+     *            the InlinedImage object (BI to EI)
+     * @throws ContentStreamException
+     */
+    protected void validImageColorSpace(PDFOperator operator) throws ContentStreamException, IOException
+    {
+        COSDictionary dict = operator.getImageParameters().getDictionary();
+
+        COSBase csInlinedBase = dict.getItem(COSName.CS);
+        ColorSpaceHelper csHelper = null;
+        if (csInlinedBase != null)
+        {
+            if (COSUtils.isString(csInlinedBase, cosDocument))
+            {
+                /*
+                 * In InlinedImage only DeviceGray/RGB/CMYK and restricted Indexed color spaces are allowed.
+                 */
+                String colorSpace = COSUtils.getAsString(csInlinedBase, cosDocument);
+                ColorSpaces cs = null;
+
+                try
+                {
+                    cs = ColorSpaces.valueOf(colorSpace);
+                }
+                catch (IllegalArgumentException e)
+                {
+                    /*
+                     * The color space is unknown. Try to access the resources dictionary, the color space can be a
+                     * reference.
+                     */
+                    PDColorSpace pdCS = (PDColorSpace) this.getColorSpaces().get(colorSpace);
+                    if (pdCS != null)
+                    {
+                        cs = ColorSpaces.valueOf(pdCS.getName());
+                        PreflightConfiguration cfg = context.getConfig();
+                        ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
+                        csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.ONLY_DEVICE);
+                    }
+                }
+
+                if (cs == null)
+                {
+                    registerError("The ColorSpace is unknown", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
+                    return;
+                }
+            }
+
+            if (csHelper == null)
+            {
+                PDColorSpace pdCS = PDColorSpaceFactory.createColorSpace(csInlinedBase);
+                PreflightConfiguration cfg = context.getConfig();
+                ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
+                csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.ONLY_DEVICE);
+            }
+
+            csHelper.validate();
+        }
+    }
+
+    /**
+     * This method validates if the ColorOperator can be used with the color space defined in OutputIntent dictionaries.
+     * 
+     * @param operator
+     *            the color operator
+     * @throws ContentStreamException
+     */
+    protected void checkColorOperators(String operation) throws ContentStreamException
+    {
+        PDColorState cs = getColorState(operation);
+
+        if ("rg".equals(operation) || "RG".equals(operation))
+        {
+            if (!validColorSpace(cs, ColorSpaceType.RGB))
+            {
+                registerError("The operator \"" + operation + "\" can't be used with CMYK Profile",
+                        ERROR_GRAPHIC_INVALID_COLOR_SPACE_RGB);
+                return;
+            }
+        }
+
+        if ("k".equals(operation) || "K".equals(operation))
+        {
+            if (!validColorSpace(cs, ColorSpaceType.CMYK))
+            {
+                registerError("The operator \"" + operation + "\" can't be used with RGB Profile",
+                        ERROR_GRAPHIC_INVALID_COLOR_SPACE_CMYK);
+                return;
+            }
+        }
+
+        if ("g".equals(operation) || "G".equals(operation))
+        {
+            if (!validColorSpace(cs, ColorSpaceType.ALL))
+            {
+                registerError("The operator \"" + operation + "\" can't be used without Color Profile",
+                        ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING);
+                return;
+            }
+        }
+
+        if ("f".equals(operation) || "F".equals(operation) || "f*".equals(operation) || "B".equals(operation)
+                || "B*".equals(operation) || "b".equals(operation) || "b*".equals(operation))
+        {
+            if (!validColorSpace(cs, ColorSpaceType.ALL))
+            {
+                // The default fill color needs an OutputIntent
+                registerError("The operator \"" + operation + "\" can't be used without Color Profile",
+                        ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING);
+                return;
+            }
+        }
+    }
+
+    private boolean validColorSpace(PDColorState colorState, ColorSpaceType expectedType) throws ContentStreamException
+    {
+        boolean result = true;
+        if (colorState == null)
+        {
+            result = validColorSpaceDestOutputProfile(expectedType);
+        }
+        else
+        {
+            PDColorSpace cs = colorState.getColorSpace();
+            if (isDeviceIndependent(cs, expectedType))
+            {
+                result = true;
+            }
+            else
+            {
+                result = validColorSpaceDestOutputProfile(expectedType);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Check if the ColorProfile provided by the DestOutputProfile entry isn't null and if the ColorSpace represented by
+     * the Profile has the right type (RGB or CMYK)
+     * 
+     * @param expectedType
+     * @return
+     */
+    private boolean validColorSpaceDestOutputProfile(ColorSpaceType expectedType) throws ContentStreamException
+    {
+        boolean result = false;
+        ICCProfileWrapper profileWrapper;
+        try
+        {
+            profileWrapper = ICCProfileWrapper.getOrSearchICCProfile(context);
+            if (profileWrapper != null)
+            {
+                switch (expectedType)
+                {
+                case RGB:
+                    result = profileWrapper.isRGBColorSpace();
+                    break;
+                case CMYK:
+                    result = profileWrapper.isCMYKColorSpace();
+                    break;
+                default:
+                    result = true;
+                    break;
+                }
+            }
+        }
+        catch (ValidationException e)
+        {
+            throw new ContentStreamException(e);
+        }
+        return result;
+    }
+
+    /**
+     * Return true if the given ColorSpace is an independent device ColorSpace. If the color space is an ICCBased, check
+     * the embedded profile color (RGB or CMYK)
+     * 
+     * @param cs
+     * @return
+     */
+    private boolean isDeviceIndependent(PDColorSpace cs, ColorSpaceType expectedType)
+    {
+        boolean result = (cs instanceof PDCalGray || cs instanceof PDCalRGB || cs instanceof PDLab);
+        if (cs instanceof PDICCBased)
+        {
+            PDICCBased iccBased = (PDICCBased) cs;
+            try
+            {
+                ColorSpace iccColorSpace = iccBased.getJavaColorSpace();
+                switch (expectedType)
+                {
+                case RGB:
+                    result = (iccColorSpace.getType() == ICC_ColorSpace.TYPE_RGB);
+                    break;
+                case CMYK:
+                    result = (iccColorSpace.getType() == ICC_ColorSpace.TYPE_CMYK);
+                    break;
+                default:
+                    result = true;
+                    break;
+                }
+            }
+            catch (IOException e)
+            {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Return the current color state used by the operation
+     * 
+     * @param operation
+     * @return
+     */
+    private PDColorState getColorState(String operation)
+    {
+        if (getGraphicsState() == null)
+        {
+            return null;
+        }
+
+        PDColorState colorState;
+        if (operation.equals("rg") || operation.equals("g") || operation.equals("k") || operation.equals("f")
+                || operation.equals("F") || operation.equals("f*"))
+        {
+            // non stroking operator
+            colorState = getGraphicsState().getNonStrokingColor();
+        }
+        else
+        {
+            // stroking operator
+            colorState = getGraphicsState().getStrokingColor();
+        }
+        return colorState;
+    }
+
+    /**
+     * This method validates if the ColorSpace used as operand is consistent with the color space defined in
+     * OutputIntent dictionaries.
+     * 
+     * @param operator
+     * @param arguments
+     * @throws IOException
+     */
+    protected void checkSetColorSpaceOperators(PDFOperator operator, List<?> arguments) throws IOException
+    {
+        if (!("CS".equals(operator.getOperation()) || "cs".equals(operator.getOperation())))
+        {
+            return;
+        }
+
+        String colorSpaceName = null;
+        if (arguments.get(0) instanceof String)
+        {
+            colorSpaceName = (String) arguments.get(0);
+        }
+        else if (arguments.get(0) instanceof COSString)
+        {
+            colorSpaceName = ((COSString) arguments.get(0)).toString();
+        }
+        else if (arguments.get(0) instanceof COSName)
+        {
+            colorSpaceName = ((COSName) arguments.get(0)).getName();
+        }
+        else
+        {
+            registerError("The operand doesn't have the expected type", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
+            return;
+        }
+
+        ColorSpaceHelper csHelper = null;
+        ColorSpaces cs = null;
+        try
+        {
+            cs = ColorSpaces.valueOf(colorSpaceName);
+        }
+        catch (IllegalArgumentException e)
+        {
+            /*
+             * The color space is unknown. Try to access the resources dictionary, the color space can be a reference.
+             */
+            PDColorSpace pdCS = (PDColorSpace) this.getColorSpaces().get(colorSpaceName);
+            if (pdCS != null)
+            {
+                cs = ColorSpaces.valueOf(pdCS.getName());
+                PreflightConfiguration cfg = context.getConfig();
+                ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
+                csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.NO_RESTRICTION);
+            }
+        }
+
+        if (cs == null)
+        {
+            registerError("The ColorSpace is unknown", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
+            return;
+        }
+
+        if (csHelper == null)
+        {
+            PDColorSpace pdCS = PDColorSpaceFactory.createColorSpace(COSName.getPDFName(colorSpaceName));
+            PreflightConfiguration cfg = context.getConfig();
+            ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
+            csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.NO_RESTRICTION);
+        }
+
+        csHelper.validate();
+    }
+
+    /**
+     * Add a validation error into the PreflightContext
+     * 
+     * @param msg
+     *            exception details
+     * @param errorCode
+     *            the error code.
+     */
+    protected void registerError(String msg, String errorCode)
+    {
+        ValidationError error = new ValidationError(errorCode, msg);
+        this.context.addValidationError(error);
+    }
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamException.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamException.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamException.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamException.java Wed Mar  6 16:46:35 2013
@@ -23,27 +23,33 @@ package org.apache.pdfbox.preflight.cont
 
 import org.apache.pdfbox.preflight.exception.ValidationException;
 
-public class ContentStreamException extends ValidationException {
-	private String errorCode="";
-
-	public ContentStreamException(String arg0, Throwable arg1) {
-		super(arg0);
-	}
-
-	public ContentStreamException(String arg0) {
-		super(arg0);
-	}
-
-	public ContentStreamException(Throwable arg0) {
-		super(arg0.getMessage());
-	}
-
-	public String getErrorCode() {
-		return errorCode;
-	}
-
-	public void setErrorCode(String errorCode) {
-		this.errorCode = errorCode;
-	}
+public class ContentStreamException extends ValidationException
+{
+    private String errorCode = "";
+
+    public ContentStreamException(String arg0, Throwable arg1)
+    {
+        super(arg0);
+    }
+
+    public ContentStreamException(String arg0)
+    {
+        super(arg0);
+    }
+
+    public ContentStreamException(Throwable arg0)
+    {
+        super(arg0.getMessage());
+    }
+
+    public String getErrorCode()
+    {
+        return errorCode;
+    }
+
+    public void setErrorCode(String errorCode)
+    {
+        this.errorCode = errorCode;
+    }
 
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java Wed Mar  6 16:46:35 2013
@@ -51,286 +51,339 @@ import org.apache.pdfbox.preflight.font.
 import org.apache.pdfbox.util.PDFOperator;
 import org.apache.pdfbox.util.operator.OperatorProcessor;
 
-public class ContentStreamWrapper extends ContentStreamEngine {
+public class ContentStreamWrapper extends ContentStreamEngine
+{
 
-	public ContentStreamWrapper(PreflightContext _context, PDPage _page) {
-		super(_context, _page);
-	}
-
-	/**
-	 * Process the validation of a PageContent (The page is initialized by the
-	 * constructor)
-	 * 
-	 * @return A list of validation error. This list is empty if the validation
-	 *         succeed.
-	 * @throws ValidationException.
-	 */
-	public void validPageContentStream() throws ValidationException {
-		try {
-			PDStream pstream = this.processeedPage.getContents();
-			if (pstream != null) {
-				processStream(processeedPage, processeedPage.findResources(), pstream.getStream());
-			}
-		} catch (ContentStreamException e) {
-			context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
-		} catch (IOException e) {
-			throw new ValidationException("Unable to check the ContentStream : " + e.getMessage(), e);
-		}
-	}
-
-	/**
-	 * Process the validation of a XObject Form
-	 * 
-	 * @param xobj
-	 * @return A list of validation error. This list is empty if the validation
-	 *         succeed.
-	 * @throws ValidationException
-	 */
-	public void validXObjContentStream(PDXObjectForm xobj)	throws ValidationException {
-		try {
-			resetEnginContext();
-			processSubStream(this.processeedPage, xobj.getResources(), xobj.getCOSStream());
-		} catch (ContentStreamException e) {
-			context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
-		} catch (IOException e) {
-			throw new ValidationException("Unable to check the ContentStream : "
-					+ e.getMessage(), e);
-		}
-	}
-
-	/**
-	 * Process the validation of a Tiling Pattern
-	 * 
-	 * @param pattern
-	 * @return A list of validation error. This list is empty if the validation
-	 *         succeed.
-	 * @throws ValidationException
-	 */
-	public void validPatternContentStream(COSStream pattern) throws ValidationException {
-		try {
-			COSDictionary res = (COSDictionary) pattern.getDictionaryObject(COSName.RESOURCES);
-			resetEnginContext();
-			processSubStream(this.processeedPage, new PDResources(res), pattern);
-		} catch (ContentStreamException e) {
-			context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
-		} catch (IOException e) {
-			throw new ValidationException("Unable to check the ContentStream : " + e.getMessage(), e);
-		}
-	}
-
-	public final void resetEnginContext() {
-		this.setGraphicsState(new PDGraphicsState());
-		this.setTextMatrix(null);
-		this.setTextLineMatrix(null);
-		this.getGraphicsStack().clear();
-		// this.streamResourcesStack.clear();
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.pdfbox.util.PDFStreamEngine#processOperator(org.apache.pdfbox
-	 * .util.PDFOperator, java.util.List)
-	 */
-	protected void processOperator(PDFOperator operator, List arguments) throws IOException {
-		/*
-		 * Here is a copy of the super method because the else block is different. 
-		 * (If the operator is unknown, throw an exception)
-		 */
-		String operation = operator.getOperation();
-		OperatorProcessor processor = (OperatorProcessor) contentStreamEngineOperators.get(operation);
-		if (processor != null) {
-			processor.setContext(this);
-			processor.process(operator, arguments);
-		} else {
-			registerError("The operator \"" + operation
-					+ "\" isn't supported.", ERROR_SYNTAX_CONTENT_STREAM_UNSUPPORTED_OP);
-			return;
-		}
-
-		/*
-		 *  Process Specific Validation.
-		 *  The Generic Processing is useless for PDFA validation
-		 */
-		if ("BI".equals(operation)) {
-			validImageFilter(operator);
-			validImageColorSpace(operator);
-		}
-
-		checkShowTextOperators(operator, arguments);
-		checkColorOperators(operation);
-		validRenderingIntent(operator, arguments);
-		checkSetColorSpaceOperators(operator, arguments);
-		validNumberOfGraphicStates(operator);
-	}
-
-	/**
-	 * Process Text Validation. According to the operator one of the both method
-	 * will be called. (validStringDefinition(PDFOperator operator, List<?>
-	 * arguments) / validStringArray(PDFOperator operator, List<?> arguments))
-	 * 
-	 * @param operator
-	 * @param arguments
-	 * @throws ContentStreamException
-	 * @throws IOException
-	 */
-	protected void checkShowTextOperators(PDFOperator operator, List<?> arguments)
-			throws ContentStreamException, IOException {
-		String op = operator.getOperation();
-		if ("Tj".equals(op)
-				|| "'".equals(op)
-				|| "\"".equals(op)) {
-			validStringDefinition(operator, arguments);
-		}
-
-		if ("TJ".equals(op)) {
-			validStringArray(operator, arguments);
-		}
-	}
-
-	/**
-	 * Process Text Validation for the Operands of a Tj, "'" and "\"" operator.
-	 * 
-	 * If the validation fails for an unexpected reason, a IOException is thrown.
-	 * If the validation fails due to validation error, a ContentStreamException
-	 * is thrown. (Use the ValidationError attribute to know the cause)
-	 * 
-	 * @param operator
-	 * @param arguments
-	 * @throws ContentStreamException
-	 * @throws IOException
-	 */
-	private void validStringDefinition(PDFOperator operator, List<?> arguments)
-	throws ContentStreamException, IOException {
-		/* For a Text operator, the arguments list should contain only one
-		 * COSString object
-		 */
-		if ("\"".equals(operator.getOperation())) {
-			if (arguments.size() != 3) {
-				registerError("Invalid argument for the operator : "
-						+ operator.getOperation(), ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
-				return;
-			}
-			Object arg0 = arguments.get(0);
-			Object arg1 = arguments.get(1);
-			Object arg2 = arguments.get(2);
-			if (!(arg0 instanceof COSInteger || arg0 instanceof COSFloat) || 
-					!(arg1 instanceof COSInteger || arg1 instanceof COSFloat) ) {
-				registerError("Invalid argument for the operator : "
-						+ operator.getOperation(), ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
-				return;
-			}
-
-			if (arg2 instanceof COSString) {
-				validText(((COSString) arg2).getBytes());
-			} else {
-				registerError("Invalid argument for the operator : "
-						+ operator.getOperation(), ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
-				return;
-			}
-		} else {
-			Object objStr = arguments.get(0);
-			if (objStr instanceof COSString) {
-				validText(((COSString) objStr).getBytes());
-			} else if (!(objStr instanceof COSInteger)) {
-				registerError("Invalid argument for the operator : "
-						+ operator.getOperation(), ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
-				return;
-			}
-		}
-	}
-
-	/**
-	 * Process Text Validation for the Operands of a TJ operator.
-	 * 
-	 * If the validation fails for an unexpected reason, a IOException is thrown.
-	 * If the validation fails due to validation error, a ContentStreamException
-	 * is thrown. (Use the ValidationError attribute to know the cause)
-	 * 
-	 * @param operator
-	 * @param arguments
-	 * @throws ContentStreamException
-	 * @throws IOException
-	 */
-	private void validStringArray(PDFOperator operator, List<?> arguments) throws ContentStreamException, IOException {
-		for (Object object : arguments) {
-			if (object instanceof COSArray) {
-				validStringArray(operator, ((COSArray) object).toList());
-			} else if (object instanceof COSString) {
-				validText(((COSString) object).getBytes());
-			} else if (!(object instanceof COSInteger || object instanceof COSFloat)) {
-				registerError("Invalid argument for the operator : "
-						+ operator.getOperation(),	ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
-				return;
-			}
-		}
-	}
-
-	/**
-	 * Process the validation of a Text operand contains in a ContentStream This
-	 * validation checks that :
-	 * <UL>
-	 * <li>The font isn't missing if the Rendering Mode isn't 3
-	 * <li>The font metrics are consistent
-	 * <li>All character used in the text are defined in the font program.
-	 * </UL>
-	 * 
-	 * @param string
-	 * @throws IOException
-	 */
-	public void validText(byte[] string) throws IOException {
-		// TextSize accessible through the TextState
-		PDTextState textState = getGraphicsState().getTextState();
-		final int renderingMode = textState.getRenderingMode();
-		final PDFont font = textState.getFont();
-		if (font == null) {
-			// Unable to decode the Text without Font
-			registerError("Text operator can't be process without Font", ERROR_FONTS_UNKNOWN_FONT_REF);
-			return;
-		}
-
-		FontContainer fontContainer = context.getFontContainer(font.getCOSObject());
-		if (renderingMode == 3 && (fontContainer == null || !fontContainer.isEmbeddedFont())) {
-			// font not embedded and rendering mode is 3. Valid case and nothing to check
-			return ;
-		} else if (fontContainer == null) {
-			// Font Must be embedded if the RenderingMode isn't 3
-			registerError(font.getBaseFont() + " is unknown wasn't found by the FontHelperValdiator", ERROR_FONTS_UNKNOWN_FONT_REF);
-			return;
-		} else if (!fontContainer.isValid() && !fontContainer.errorsAleadyMerged()) {
-			context.addValidationErrors(fontContainer.getAllErrors());
-			fontContainer.setErrorsAleadyMerged(true);
-			return;
-		} if (!fontContainer.isValid() && fontContainer.errorsAleadyMerged()) {
-			// font already computed
-			return;
-		}
-
-
-		int codeLength = 1;
-		for (int i = 0; i < string.length; i += codeLength) {
-			// explore the string to detect character code (length can be 1 or 2 bytes)
-			int cid = -1; 
-			codeLength = 1;
-			try {
-				// according to the encoding, extract the character identifier
-				cid = font.encodeToCID(string, i, codeLength);
-				if (cid == -1 && i + 1 < string.length) {
-					// maybe a multibyte encoding
-					codeLength++;
-					cid = font.encodeToCID(string, i, codeLength);
-				}
-				fontContainer.checkGlyphWith(cid);
-			} catch (IOException e) {
-				registerError("Encoding can't interpret the character code", ERROR_FONTS_ENCODING_ERROR);
-				return;
-			} catch (GlyphException e) {
-				if (renderingMode != 3) {
-					registerError(e.getMessage(), e.getErrorCode());
-					return;
-				}
-			}
-		}
-	}
+    public ContentStreamWrapper(PreflightContext _context, PDPage _page)
+    {
+        super(_context, _page);
+    }
+
+    /**
+     * Process the validation of a PageContent (The page is initialized by the constructor)
+     * 
+     * @return A list of validation error. This list is empty if the validation succeed.
+     * @throws ValidationException.
+     */
+    public void validPageContentStream() throws ValidationException
+    {
+        try
+        {
+            PDStream pstream = this.processeedPage.getContents();
+            if (pstream != null)
+            {
+                processStream(processeedPage, processeedPage.findResources(), pstream.getStream());
+            }
+        }
+        catch (ContentStreamException e)
+        {
+            context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
+        }
+        catch (IOException e)
+        {
+            throw new ValidationException("Unable to check the ContentStream : " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Process the validation of a XObject Form
+     * 
+     * @param xobj
+     * @return A list of validation error. This list is empty if the validation succeed.
+     * @throws ValidationException
+     */
+    public void validXObjContentStream(PDXObjectForm xobj) throws ValidationException
+    {
+        try
+        {
+            resetEnginContext();
+            processSubStream(this.processeedPage, xobj.getResources(), xobj.getCOSStream());
+        }
+        catch (ContentStreamException e)
+        {
+            context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
+        }
+        catch (IOException e)
+        {
+            throw new ValidationException("Unable to check the ContentStream : " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Process the validation of a Tiling Pattern
+     * 
+     * @param pattern
+     * @return A list of validation error. This list is empty if the validation succeed.
+     * @throws ValidationException
+     */
+    public void validPatternContentStream(COSStream pattern) throws ValidationException
+    {
+        try
+        {
+            COSDictionary res = (COSDictionary) pattern.getDictionaryObject(COSName.RESOURCES);
+            resetEnginContext();
+            processSubStream(this.processeedPage, new PDResources(res), pattern);
+        }
+        catch (ContentStreamException e)
+        {
+            context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
+        }
+        catch (IOException e)
+        {
+            throw new ValidationException("Unable to check the ContentStream : " + e.getMessage(), e);
+        }
+    }
+
+    public final void resetEnginContext()
+    {
+        this.setGraphicsState(new PDGraphicsState());
+        this.setTextMatrix(null);
+        this.setTextLineMatrix(null);
+        this.getGraphicsStack().clear();
+        // this.streamResourcesStack.clear();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.pdfbox.util.PDFStreamEngine#processOperator(org.apache.pdfbox .util.PDFOperator, java.util.List)
+     */
+    protected void processOperator(PDFOperator operator, List arguments) throws IOException
+    {
+        /*
+         * Here is a copy of the super method because the else block is different. (If the operator is unknown, throw an
+         * exception)
+         */
+        String operation = operator.getOperation();
+        OperatorProcessor processor = (OperatorProcessor) contentStreamEngineOperators.get(operation);
+        if (processor != null)
+        {
+            processor.setContext(this);
+            processor.process(operator, arguments);
+        }
+        else
+        {
+            registerError("The operator \"" + operation + "\" isn't supported.",
+                    ERROR_SYNTAX_CONTENT_STREAM_UNSUPPORTED_OP);
+            return;
+        }
+
+        /*
+         * Process Specific Validation. The Generic Processing is useless for PDFA validation
+         */
+        if ("BI".equals(operation))
+        {
+            validImageFilter(operator);
+            validImageColorSpace(operator);
+        }
+
+        checkShowTextOperators(operator, arguments);
+        checkColorOperators(operation);
+        validRenderingIntent(operator, arguments);
+        checkSetColorSpaceOperators(operator, arguments);
+        validNumberOfGraphicStates(operator);
+    }
+
+    /**
+     * Process Text Validation. According to the operator one of the both method will be called.
+     * (validStringDefinition(PDFOperator operator, List<?> arguments) / validStringArray(PDFOperator operator, List<?>
+     * arguments))
+     * 
+     * @param operator
+     * @param arguments
+     * @throws ContentStreamException
+     * @throws IOException
+     */
+    protected void checkShowTextOperators(PDFOperator operator, List<?> arguments) throws ContentStreamException,
+            IOException
+    {
+        String op = operator.getOperation();
+        if ("Tj".equals(op) || "'".equals(op) || "\"".equals(op))
+        {
+            validStringDefinition(operator, arguments);
+        }
+
+        if ("TJ".equals(op))
+        {
+            validStringArray(operator, arguments);
+        }
+    }
+
+    /**
+     * Process Text Validation for the Operands of a Tj, "'" and "\"" operator.
+     * 
+     * If the validation fails for an unexpected reason, a IOException is thrown. If the validation fails due to
+     * validation error, a ContentStreamException is thrown. (Use the ValidationError attribute to know the cause)
+     * 
+     * @param operator
+     * @param arguments
+     * @throws ContentStreamException
+     * @throws IOException
+     */
+    private void validStringDefinition(PDFOperator operator, List<?> arguments) throws ContentStreamException,
+            IOException
+    {
+        /*
+         * For a Text operator, the arguments list should contain only one COSString object
+         */
+        if ("\"".equals(operator.getOperation()))
+        {
+            if (arguments.size() != 3)
+            {
+                registerError("Invalid argument for the operator : " + operator.getOperation(),
+                        ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+                return;
+            }
+            Object arg0 = arguments.get(0);
+            Object arg1 = arguments.get(1);
+            Object arg2 = arguments.get(2);
+            if (!(arg0 instanceof COSInteger || arg0 instanceof COSFloat)
+                    || !(arg1 instanceof COSInteger || arg1 instanceof COSFloat))
+            {
+                registerError("Invalid argument for the operator : " + operator.getOperation(),
+                        ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+                return;
+            }
+
+            if (arg2 instanceof COSString)
+            {
+                validText(((COSString) arg2).getBytes());
+            }
+            else
+            {
+                registerError("Invalid argument for the operator : " + operator.getOperation(),
+                        ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+                return;
+            }
+        }
+        else
+        {
+            Object objStr = arguments.get(0);
+            if (objStr instanceof COSString)
+            {
+                validText(((COSString) objStr).getBytes());
+            }
+            else if (!(objStr instanceof COSInteger))
+            {
+                registerError("Invalid argument for the operator : " + operator.getOperation(),
+                        ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Process Text Validation for the Operands of a TJ operator.
+     * 
+     * If the validation fails for an unexpected reason, a IOException is thrown. If the validation fails due to
+     * validation error, a ContentStreamException is thrown. (Use the ValidationError attribute to know the cause)
+     * 
+     * @param operator
+     * @param arguments
+     * @throws ContentStreamException
+     * @throws IOException
+     */
+    private void validStringArray(PDFOperator operator, List<?> arguments) throws ContentStreamException, IOException
+    {
+        for (Object object : arguments)
+        {
+            if (object instanceof COSArray)
+            {
+                validStringArray(operator, ((COSArray) object).toList());
+            }
+            else if (object instanceof COSString)
+            {
+                validText(((COSString) object).getBytes());
+            }
+            else if (!(object instanceof COSInteger || object instanceof COSFloat))
+            {
+                registerError("Invalid argument for the operator : " + operator.getOperation(),
+                        ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Process the validation of a Text operand contains in a ContentStream This validation checks that :
+     * <UL>
+     * <li>The font isn't missing if the Rendering Mode isn't 3
+     * <li>The font metrics are consistent
+     * <li>All character used in the text are defined in the font program.
+     * </UL>
+     * 
+     * @param string
+     * @throws IOException
+     */
+    public void validText(byte[] string) throws IOException
+    {
+        // TextSize accessible through the TextState
+        PDTextState textState = getGraphicsState().getTextState();
+        final int renderingMode = textState.getRenderingMode();
+        final PDFont font = textState.getFont();
+        if (font == null)
+        {
+            // Unable to decode the Text without Font
+            registerError("Text operator can't be process without Font", ERROR_FONTS_UNKNOWN_FONT_REF);
+            return;
+        }
+
+        FontContainer fontContainer = context.getFontContainer(font.getCOSObject());
+        if (renderingMode == 3 && (fontContainer == null || !fontContainer.isEmbeddedFont()))
+        {
+            // font not embedded and rendering mode is 3. Valid case and nothing to check
+            return;
+        }
+        else if (fontContainer == null)
+        {
+            // Font Must be embedded if the RenderingMode isn't 3
+            registerError(font.getBaseFont() + " is unknown wasn't found by the FontHelperValdiator",
+                    ERROR_FONTS_UNKNOWN_FONT_REF);
+            return;
+        }
+        else if (!fontContainer.isValid() && !fontContainer.errorsAleadyMerged())
+        {
+            context.addValidationErrors(fontContainer.getAllErrors());
+            fontContainer.setErrorsAleadyMerged(true);
+            return;
+        }
+        if (!fontContainer.isValid() && fontContainer.errorsAleadyMerged())
+        {
+            // font already computed
+            return;
+        }
+
+        int codeLength = 1;
+        for (int i = 0; i < string.length; i += codeLength)
+        {
+            // explore the string to detect character code (length can be 1 or 2 bytes)
+            int cid = -1;
+            codeLength = 1;
+            try
+            {
+                // according to the encoding, extract the character identifier
+                cid = font.encodeToCID(string, i, codeLength);
+                if (cid == -1 && i + 1 < string.length)
+                {
+                    // maybe a multibyte encoding
+                    codeLength++;
+                    cid = font.encodeToCID(string, i, codeLength);
+                }
+                fontContainer.checkGlyphWith(cid);
+            }
+            catch (IOException e)
+            {
+                registerError("Encoding can't interpret the character code", ERROR_FONTS_ENCODING_ERROR);
+                return;
+            }
+            catch (GlyphException e)
+            {
+                if (renderingMode != 3)
+                {
+                    registerError(e.getMessage(), e.getErrorCode());
+                    return;
+                }
+            }
+        }
+    }
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/StubOperator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/StubOperator.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/StubOperator.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/StubOperator.java Wed Mar  6 16:46:35 2013
@@ -48,287 +48,376 @@ import org.apache.pdfbox.util.PDFOperato
 import org.apache.pdfbox.util.operator.OperatorProcessor;
 
 /**
- * This implementation of OperatorProcessor allow the operator validation
- * according PDF/A rules without compute the operator actions.
+ * This implementation of OperatorProcessor allow the operator validation according PDF/A rules without compute the
+ * operator actions.
  */
-public class StubOperator extends OperatorProcessor {
+public class StubOperator extends OperatorProcessor
+{
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * org.apache.pdfbox.util.operator.OperatorProcessor#process(org.apache.pdfbox
-   * .util.PDFOperator, java.util.List)
-   */
-  @Override
-  public void process(PDFOperator operator, List<COSBase> arguments)
-      throws IOException {
-	String op = operator.getOperation();
-    if ("S".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("B".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("f".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("F".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("f*".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("b".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("B*".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("b*".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("s".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("EMC".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("BMC".equals(op)) {
-      checkStringOperands(arguments, 1);
-    } else if ("BDC".equals(op)) {
-      checkTagAndPropertyOperands(arguments);
-    } else if ("DP".equals(op)) {
-      checkTagAndPropertyOperands(arguments);
-    } else if ("c".equals(op)) {
-      checkNumberOperands(arguments, 6);
-    } else if ("v".equals(op)) {
-      checkNumberOperands(arguments, 4);
-    } else if ("y".equals(op)) {
-      checkNumberOperands(arguments, 4);
-    } else if ("d0".equals(op)) {
-      checkNumberOperands(arguments, 2);
-    } else if ("d1".equals(op)) {
-      checkNumberOperands(arguments, 6);
-    } else if ("g".equals(op)) {
-      checkNumberOperands(arguments, 1);
-    } else if ("G".equals(op)) {
-      checkNumberOperands(arguments, 1);
-    } else if ("gs".equals(op)) {
-      checkStringOperands(arguments, 1);
-    } else if ("h".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("i".equals(op)) {
-      checkNumberOperands(arguments, 1);
-    } else if ("l".equals(op)) {
-      checkNumberOperands(arguments, 2);
-    } else if ("m".equals(op)) {
-      checkNumberOperands(arguments, 2);
-    } else if ("M".equals(op)) {
-      checkNumberOperands(arguments, 1);
-    } else if ("MP".equals(op)) {
-      checkStringOperands(arguments, 1);
-    } else if ("n".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("re".equals(op)) {
-      checkNumberOperands(arguments, 4);
-    } else if ("ri".equals(op)) {
-      checkStringOperands(arguments, 1);
-    } else if ("s".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("S".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("sh".equals(op)) {
-      checkStringOperands(arguments, 1);
-    } else if ("'".equals(op)) {
-      checkStringOperands(arguments, 1);
-    } else if ("Tj".equals(op)) {
-      checkStringOperands(arguments, 1);
-    } else if ("TJ".equals(op)) {
-      checkArrayOperands(arguments, 1);
-    } else if ("W".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("W*".equals(op)) {
-      checkNoOperands(arguments);
-    } else if ("\"".equals(op)) {
-      checkNumberOperands(arguments.subList(0, 2), 2);
-      checkStringOperands(arguments.subList(2, arguments.size()), 1);
-    } 
-    // else 
-    // ---- Some operators are processed by PDFBox Objects.
-    // ---- Other operators are authorized but it isn't used.
-    
-  }
-
-  /**
-   * If the arguments list of Operator isn't empty, this method throws a
-   * ContentStreamException.
-   * 
-   * @param arguments
-   * @throws ContentStreamException
-   */
-  private void checkNoOperands(List<COSBase> arguments)
-      throws ContentStreamException {
-    if (arguments != null && !arguments.isEmpty()) {
-      throw createInvalidArgumentsError();
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.pdfbox.util.operator.OperatorProcessor#process(org.apache.pdfbox .util.PDFOperator,
+     * java.util.List)
+     */
+    @Override
+    public void process(PDFOperator operator, List<COSBase> arguments) throws IOException
+    {
+        String op = operator.getOperation();
+        if ("S".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("B".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("f".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("F".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("f*".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("b".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("B*".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("b*".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("s".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("EMC".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("BMC".equals(op))
+        {
+            checkStringOperands(arguments, 1);
+        }
+        else if ("BDC".equals(op))
+        {
+            checkTagAndPropertyOperands(arguments);
+        }
+        else if ("DP".equals(op))
+        {
+            checkTagAndPropertyOperands(arguments);
+        }
+        else if ("c".equals(op))
+        {
+            checkNumberOperands(arguments, 6);
+        }
+        else if ("v".equals(op))
+        {
+            checkNumberOperands(arguments, 4);
+        }
+        else if ("y".equals(op))
+        {
+            checkNumberOperands(arguments, 4);
+        }
+        else if ("d0".equals(op))
+        {
+            checkNumberOperands(arguments, 2);
+        }
+        else if ("d1".equals(op))
+        {
+            checkNumberOperands(arguments, 6);
+        }
+        else if ("g".equals(op))
+        {
+            checkNumberOperands(arguments, 1);
+        }
+        else if ("G".equals(op))
+        {
+            checkNumberOperands(arguments, 1);
+        }
+        else if ("gs".equals(op))
+        {
+            checkStringOperands(arguments, 1);
+        }
+        else if ("h".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("i".equals(op))
+        {
+            checkNumberOperands(arguments, 1);
+        }
+        else if ("l".equals(op))
+        {
+            checkNumberOperands(arguments, 2);
+        }
+        else if ("m".equals(op))
+        {
+            checkNumberOperands(arguments, 2);
+        }
+        else if ("M".equals(op))
+        {
+            checkNumberOperands(arguments, 1);
+        }
+        else if ("MP".equals(op))
+        {
+            checkStringOperands(arguments, 1);
+        }
+        else if ("n".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("re".equals(op))
+        {
+            checkNumberOperands(arguments, 4);
+        }
+        else if ("ri".equals(op))
+        {
+            checkStringOperands(arguments, 1);
+        }
+        else if ("s".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("S".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("sh".equals(op))
+        {
+            checkStringOperands(arguments, 1);
+        }
+        else if ("'".equals(op))
+        {
+            checkStringOperands(arguments, 1);
+        }
+        else if ("Tj".equals(op))
+        {
+            checkStringOperands(arguments, 1);
+        }
+        else if ("TJ".equals(op))
+        {
+            checkArrayOperands(arguments, 1);
+        }
+        else if ("W".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("W*".equals(op))
+        {
+            checkNoOperands(arguments);
+        }
+        else if ("\"".equals(op))
+        {
+            checkNumberOperands(arguments.subList(0, 2), 2);
+            checkStringOperands(arguments.subList(2, arguments.size()), 1);
+        }
+        // else
+        // ---- Some operators are processed by PDFBox Objects.
+        // ---- Other operators are authorized but it isn't used.
+
+    }
+
+    /**
+     * If the arguments list of Operator isn't empty, this method throws a ContentStreamException.
+     * 
+     * @param arguments
+     * @throws ContentStreamException
+     */
+    private void checkNoOperands(List<COSBase> arguments) throws ContentStreamException
+    {
+        if (arguments != null && !arguments.isEmpty())
+        {
+            throw createInvalidArgumentsError();
+        }
+    }
+
+    /**
+     * If the arguments list of Operator doesn't have String parameter, this method throws a ContentStreamException.
+     * 
+     * @param arguments
+     * @param length
+     * @throws ContentStreamException
+     */
+    private void checkStringOperands(List<COSBase> arguments, int length) throws ContentStreamException
+    {
+        if (arguments == null || arguments.isEmpty() || arguments.size() != length)
+        {
+            throw createInvalidArgumentsError();
+        }
+
+        for (int i = 0; i < length; ++i)
+        {
+            COSBase arg = arguments.get(i);
+            if (!(arg instanceof COSName) && !(arg instanceof COSString))
+            {
+                throw createInvalidArgumentsError();
+            }
+
+            if (arg instanceof COSName && ((COSName) arg).getName().length() > MAX_NAME_SIZE)
+            {
+                throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG, "A Name operand is too long");
+            }
+
+            if (arg instanceof COSString && ((COSString) arg).getString().getBytes().length > MAX_STRING_LENGTH)
+            {
+                throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG, "A String operand is too long");
+            }
+        }
+    }
+
+    /**
+     * If the arguments list of Operator doesn't have Array parameter, this method throws a ContentStreamException.
+     * 
+     * @param arguments
+     * @param length
+     * @throws ContentStreamException
+     */
+    private void checkArrayOperands(List<COSBase> arguments, int length) throws ContentStreamException
+    {
+        if (arguments == null || arguments.isEmpty() || arguments.size() != length)
+        {
+            throw createInvalidArgumentsError();
+        }
+
+        for (int i = 0; i < length; ++i)
+        {
+            COSBase arg = arguments.get(i);
+            if (!(arg instanceof COSArray))
+            {
+                throw createInvalidArgumentsError();
+            }
+
+            if (((COSArray) arg).size() > MAX_ARRAY_ELEMENTS)
+            {
+                throw createLimitError(ERROR_SYNTAX_ARRAY_TOO_LONG, "Array has " + ((COSArray) arg).size()
+                        + " elements");
+            }
+        }
+    }
+
+    /**
+     * If the arguments list of Operator doesn't have Number parameters (Int, float...), this method throws a
+     * ContentStreamException.
+     * 
+     * @param arguments
+     *            the arguments list to check
+     * @param length
+     *            the expected size of the list
+     * @throws ContentStreamException
+     */
+    private void checkNumberOperands(List<COSBase> arguments, int length) throws ContentStreamException
+    {
+        if (arguments == null || arguments.isEmpty() || arguments.size() != length)
+        {
+            throw createInvalidArgumentsError();
+        }
+
+        for (int i = 0; i < length; ++i)
+        {
+            COSBase arg = arguments.get(i);
+            if (!(arg instanceof COSFloat) && !(arg instanceof COSInteger))
+            {
+                throw createInvalidArgumentsError();
+            }
+
+            if (arg instanceof COSInteger
+                    && (((COSInteger) arg).longValue() > Integer.MAX_VALUE || ((COSInteger) arg).longValue() < Integer.MIN_VALUE))
+            {
+                throw createLimitError(ERROR_SYNTAX_NUMERIC_RANGE, "Invalid integer range in a Number operands");
+            }
+
+            if (arg instanceof COSFloat
+                    && (((COSFloat) arg).doubleValue() > MAX_POSITIVE_FLOAT || ((COSFloat) arg).doubleValue() < MAX_NEGATIVE_FLOAT))
+            {
+                throw createLimitError(ERROR_SYNTAX_NUMERIC_RANGE, "Invalid float range in a Number operands");
+            }
+        }
+    }
+
+    /**
+     * The given arguments list is valid only if the first argument is a Tag (A String) and if the second argument is a
+     * String or a Dictionary
+     * 
+     * @param arguments
+     * @throws ContentStreamException
+     */
+    private void checkTagAndPropertyOperands(List<COSBase> arguments) throws ContentStreamException
+    {
+        if (arguments == null || arguments.isEmpty() || arguments.size() != 2)
+        {
+            throw createInvalidArgumentsError();
+        }
+
+        COSBase arg = arguments.get(0);
+        if (!(arg instanceof COSName) && !(arg instanceof COSString))
+        {
+            throw createInvalidArgumentsError();
+        }
+
+        if (arg instanceof COSName && ((COSName) arg).getName().length() > MAX_NAME_SIZE)
+        {
+            throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG, "A Name operand is too long");
+        }
+
+        if (arg instanceof COSString && ((COSString) arg).getString().getBytes().length > MAX_STRING_LENGTH)
+        {
+            throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG, "A String operand is too long");
+        }
+
+        COSBase arg2 = arguments.get(1);
+        if (!(arg2 instanceof COSName) && !(arg2 instanceof COSString) && !(arg2 instanceof COSDictionary))
+        {
+            throw createInvalidArgumentsError();
+        }
+
+        if (arg2 instanceof COSName && ((COSName) arg2).getName().length() > MAX_NAME_SIZE)
+        {
+            throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG, "A Name operand is too long");
+        }
+
+        if (arg2 instanceof COSString && ((COSString) arg2).getString().getBytes().length > MAX_STRING_LENGTH)
+        {
+            throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG, "A String operand is too long");
+        }
+
+        if (arg2 instanceof COSDictionary && ((COSDictionary) arg2).size() > MAX_DICT_ENTRIES)
+        {
+            throw createLimitError(ERROR_SYNTAX_TOO_MANY_ENTRIES, "Dictionary has " + ((COSDictionary) arg2).size()
+                    + " entries");
+        }
+    }
+
+    /**
+     * Create a ContentStreamException with ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT.
+     * 
+     * @return
+     */
+    private ContentStreamException createInvalidArgumentsError()
+    {
+        ContentStreamException ex = new ContentStreamException("Invalid arguments");
+        ex.setErrorCode(ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+        return ex;
+    }
+
+    /**
+     * Create a ContentStreamException with ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT.
+     * 
+     * @return
+     */
+    private ContentStreamException createLimitError(String errorCode, String details)
+    {
+        ContentStreamException ex = new ContentStreamException(details);
+        ex.setErrorCode(errorCode);
+        return ex;
     }
-  }
-
-  /**
-   * If the arguments list of Operator doesn't have String parameter, this
-   * method throws a ContentStreamException.
-   * 
-   * @param arguments
-   * @param length
-   * @throws ContentStreamException
-   */
-  private void checkStringOperands(List<COSBase> arguments, int length)
-      throws ContentStreamException {
-    if (arguments == null || arguments.isEmpty() || arguments.size() != length) {
-      throw createInvalidArgumentsError();
-    }
-
-    for (int i = 0; i < length; ++i) {
-      COSBase arg = arguments.get(i);
-      if (!(arg instanceof COSName) && !(arg instanceof COSString)) {
-        throw createInvalidArgumentsError();
-      }
-
-      if (arg instanceof COSName
-          && ((COSName) arg).getName().length() > MAX_NAME_SIZE) {
-        throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG, "A Name operand is too long");
-      }
-
-      if (arg instanceof COSString
-          && ((COSString) arg).getString().getBytes().length > MAX_STRING_LENGTH) {
-        throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG, "A String operand is too long");
-      }
-    }
-  }
-
-  /**
-   * If the arguments list of Operator doesn't have Array parameter, this method
-   * throws a ContentStreamException.
-   * 
-   * @param arguments
-   * @param length
-   * @throws ContentStreamException
-   */
-  private void checkArrayOperands(List<COSBase> arguments, int length)
-      throws ContentStreamException {
-    if (arguments == null || arguments.isEmpty() || arguments.size() != length) {
-      throw createInvalidArgumentsError();
-    }
-
-    for (int i = 0; i < length; ++i) {
-      COSBase arg = arguments.get(i);
-      if (!(arg instanceof COSArray)) {
-        throw createInvalidArgumentsError();
-      }
-
-      if (((COSArray) arg).size() > MAX_ARRAY_ELEMENTS) {
-        throw createLimitError(ERROR_SYNTAX_ARRAY_TOO_LONG, "Array has " + ((COSArray) arg).size() + " elements");
-      }
-    }
-  }
-
-  /**
-   * If the arguments list of Operator doesn't have Number parameters (Int,
-   * float...), this method throws a ContentStreamException.
-   * 
-   * @param arguments
-   *          the arguments list to check
-   * @param length
-   *          the expected size of the list
-   * @throws ContentStreamException
-   */
-  private void checkNumberOperands(List<COSBase> arguments, int length)
-      throws ContentStreamException {
-    if (arguments == null || arguments.isEmpty() || arguments.size() != length) {
-      throw createInvalidArgumentsError();
-    }
-
-    for (int i = 0; i < length; ++i) {
-      COSBase arg = arguments.get(i);
-      if (!(arg instanceof COSFloat) && !(arg instanceof COSInteger)) {
-        throw createInvalidArgumentsError();
-      }
-
-      if (arg instanceof COSInteger
-          && (((COSInteger) arg).longValue() > Integer.MAX_VALUE || ((COSInteger) arg)
-              .longValue() < Integer.MIN_VALUE)) {
-        throw createLimitError(ERROR_SYNTAX_NUMERIC_RANGE, "Invalid integer range in a Number operands");
-      }
-
-      if (arg instanceof COSFloat
-          && (((COSFloat) arg).doubleValue() > MAX_POSITIVE_FLOAT || ((COSFloat) arg)
-              .doubleValue() < MAX_NEGATIVE_FLOAT)) {
-        throw createLimitError(ERROR_SYNTAX_NUMERIC_RANGE, "Invalid float range in a Number operands");
-      }
-    }
-  }
-
-  /**
-   * The given arguments list is valid only if the first argument is a Tag (A
-   * String) and if the second argument is a String or a Dictionary
-   * 
-   * @param arguments
-   * @throws ContentStreamException
-   */
-  private void checkTagAndPropertyOperands(List<COSBase> arguments)
-      throws ContentStreamException {
-    if (arguments == null || arguments.isEmpty() || arguments.size() != 2) {
-      throw createInvalidArgumentsError();
-    }
-
-    COSBase arg = arguments.get(0);
-    if (!(arg instanceof COSName) && !(arg instanceof COSString)) {
-      throw createInvalidArgumentsError();
-    }
-
-    if (arg instanceof COSName
-        && ((COSName) arg).getName().length() > MAX_NAME_SIZE) {
-      throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG,"A Name operand is too long");
-    }
-
-    if (arg instanceof COSString
-        && ((COSString) arg).getString().getBytes().length > MAX_STRING_LENGTH) {
-      throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG,"A String operand is too long");
-    }
-
-    COSBase arg2 = arguments.get(1);
-    if (!(arg2 instanceof COSName) && !(arg2 instanceof COSString)
-        && !(arg2 instanceof COSDictionary)) {
-      throw createInvalidArgumentsError();
-    }
-
-    if (arg2 instanceof COSName
-        && ((COSName) arg2).getName().length() > MAX_NAME_SIZE) {
-      throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG,"A Name operand is too long");
-    }
-
-    if (arg2 instanceof COSString
-        && ((COSString) arg2).getString().getBytes().length > MAX_STRING_LENGTH) {
-      throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG,"A String operand is too long");
-    }
-
-    if (arg2 instanceof COSDictionary
-        && ((COSDictionary) arg2).size() > MAX_DICT_ENTRIES) {
-      throw createLimitError(ERROR_SYNTAX_TOO_MANY_ENTRIES, "Dictionary has " + ((COSDictionary) arg2).size() + " entries");
-    }
-  }
-
-  /**
-   * Create a ContentStreamException with
-   * ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT.
-   * 
-   * @return
-   */
-  private ContentStreamException createInvalidArgumentsError() {
-    ContentStreamException ex = new ContentStreamException("Invalid arguments");
-    ex.setErrorCode(ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
-    return ex;
-  }
-
-  /**
-   * Create a ContentStreamException with
-   * ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT.
-   * 
-   * @return
-   */
-  private ContentStreamException createLimitError(String errorCode, String details) {
-    ContentStreamException ex = new ContentStreamException(details);
-    ex.setErrorCode(errorCode);
-    return ex;
-  }
 }

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/exception/BodyParseException.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/exception/BodyParseException.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/exception/BodyParseException.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/exception/BodyParseException.java Wed Mar  6 16:46:35 2013
@@ -24,81 +24,86 @@ package org.apache.pdfbox.preflight.exce
 import org.apache.pdfbox.preflight.PreflightConstants;
 import org.apache.pdfbox.preflight.javacc.PDFParserConstants;
 import org.apache.pdfbox.preflight.javacc.ParseException;
+
 /**
- * This Exception is thrown if an validation error occurs during the javacc
- * validation in the PDF Body.
+ * This Exception is thrown if an validation error occurs during the javacc validation in the PDF Body.
  * 
  * Error codes provided by this exception should start by 1.2 or 1.0.
  */
-public class BodyParseException extends PdfParseException {
+public class BodyParseException extends PdfParseException
+{
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(net.awl
-   * .edoc.pdfa.validation.ParseException)
-   */
-  public BodyParseException(ParseException e) {
-    super(e);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(java.lang
-   * .String,java.lang.String)
-   */
-  public BodyParseException(String message, String code) {
-    super(message, code);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(java.lang
-   * .String)
-   */
-  public BodyParseException(String message) {
-    super(message);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see net.awl.edoc.pdfa.validation.PdfParseException#getErrorCode()
-   */
-  @Override
-  public String getErrorCode() {
-    if (this.errorCode != null) {
-      return this.errorCode;
+    /*
+     * (non-Javadoc)
+     * 
+     * @see net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(net.awl
+     * .edoc.pdfa.validation.ParseException)
+     */
+    public BodyParseException(ParseException e)
+    {
+        super(e);
     }
 
-    // default error code
-    this.errorCode = PreflightConstants.ERROR_SYNTAX_BODY;
+    /*
+     * (non-Javadoc)
+     * 
+     * @see net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(java.lang .String,java.lang.String)
+     */
+    public BodyParseException(String message, String code)
+    {
+        super(message, code);
+    }
 
-    if (!isTokenMgrError) {
-      // it is a parse error, according to the ExpectedTokens data
-      // some error code can be returned
-      if (this.expectedTokenSequences != null) {
-        // check object delimiters error
-        for (int i = 0; i < this.expectedTokenSequences.length; ++i) {
-          // Check only the first Expected token on each array.
-          // Others can be check if some choice can start by the same token
-          // in this case, a factorization is possible
-          switch (this.expectedTokenSequences[i][0]) {
-          case PDFParserConstants.START_OBJECT:
-          case PDFParserConstants.END_OBJECT:
-            this.errorCode = PreflightConstants.ERROR_SYNTAX_OBJ_DELIMITER;
-            break;
-          }
-        }
-        // add here other error code
-      }
+    /*
+     * (non-Javadoc)
+     * 
+     * @see net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(java.lang .String)
+     */
+    public BodyParseException(String message)
+    {
+        super(message);
     }
 
-    return errorCode;
-  }
+    /*
+     * (non-Javadoc)
+     * 
+     * @see net.awl.edoc.pdfa.validation.PdfParseException#getErrorCode()
+     */
+    @Override
+    public String getErrorCode()
+    {
+        if (this.errorCode != null)
+        {
+            return this.errorCode;
+        }
+
+        // default error code
+        this.errorCode = PreflightConstants.ERROR_SYNTAX_BODY;
+
+        if (!isTokenMgrError)
+        {
+            // it is a parse error, according to the ExpectedTokens data
+            // some error code can be returned
+            if (this.expectedTokenSequences != null)
+            {
+                // check object delimiters error
+                for (int i = 0; i < this.expectedTokenSequences.length; ++i)
+                {
+                    // Check only the first Expected token on each array.
+                    // Others can be check if some choice can start by the same token
+                    // in this case, a factorization is possible
+                    switch (this.expectedTokenSequences[i][0])
+                    {
+                    case PDFParserConstants.START_OBJECT:
+                    case PDFParserConstants.END_OBJECT:
+                        this.errorCode = PreflightConstants.ERROR_SYNTAX_OBJ_DELIMITER;
+                        break;
+                    }
+                }
+                // add here other error code
+            }
+        }
+
+        return errorCode;
+    }
 }