View Javadoc

1   /***********************************************************************************************************************
2   Copyright (c) 2003, International Barcode Consortium
3   All rights reserved.
4   
5   Redistribution and use in source and binary forms, with or without modification,
6   are permitted provided that the following conditions are met:
7   
8       * Redistributions of source code must retain the above copyright notice, this list of
9         conditions and the following disclaimer.
10      * Redistributions in binary form must reproduce the above copyright notice, this list of
11        conditions and the following disclaimer in the documentation and/or other materials
12        provided with the distribution.
13      * Neither the name of the International Barcode Consortium nor the names of any contributors may be used to endorse
14        or promote products derived from this software without specific prior written permission.
15  
16  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
17  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  POSSIBILITY OF SUCH DAMAGE.
25  ***********************************************************************************************************************/
26  
27  package net.sourceforge.barbecue;
28  
29  import net.sourceforge.barbecue.env.*;
30  import net.sourceforge.barbecue.linear.code39.Code39Barcode;
31  import net.sourceforge.barbecue.output.OutputException;
32  
33  import javax.servlet.ServletException;
34  import javax.servlet.ServletOutputStream;
35  import javax.servlet.http.HttpServlet;
36  import javax.servlet.http.HttpServletRequest;
37  import javax.servlet.http.HttpServletResponse;
38  import java.io.IOException;
39  import java.lang.reflect.Method;
40  import java.lang.reflect.InvocationTargetException;
41  
42  /**
43   * The query parameters for this servlet are:
44   * <ol>
45   * <li>data, required, example: "1234567890"
46   * <li>type, optional, examples: "Code128A", "Code128B", "Code128C", if left blank will default to Code 128 B.
47   * Note that the type here must be <b>exactly</b> the name of one of the createX methods on BarcodeFactory without
48   * the "create" prefix. This is case sensitive.
49   * <li>appid, required for UCC128 type, ignored for all other types - specifies the application identifier to use with
50   * the UCC128 barcode, example: "420" for a US postal service barcode
51   * <li>width, optional, in pixels
52   * <li>height, optional, in pixels
53   * <li>resolution, optional, in dpi
54   * <li>headless, optional, set to "false" to force non-headless mode for the servlet - default is "true"
55   * <li>drawText, optional and only takes effect if headless is "false", set to "false" for no text
56   * </ol>
57   *
58   * <p>Example URL: <code>http://hostname:80/myapp/BarcodeServlet?data=12345&amp;type=Code128A</code>
59   * </p>
60   * 
61   * <p>Contributed by Robert Chou &lt;rchou at users.sourceforge.net&gt;</p>
62   *
63   * @author Robert Chou
64   * @author <a href="mailto:opensource@ianbourke.com">Ian Bourke</a>
65   * @author Sean Sullivan
66   * 
67   */
68  public class BarcodeServlet extends HttpServlet {
69  	/**
70  	 * From HttpServlet.
71  	 * @return The literal string 'barbecue'
72  	 */
73  	public String getServletName() {
74  		return "barbecue";
75  	}
76  
77  	/**
78  	 * From HttpServlet.
79  	 * @param req The servlet request
80  	 * @param res The servlet response
81  	 * @throws ServletException If an error occurs during processing
82  	 */
83  	public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException {
84  		doRequest(req, res);
85  	}
86  
87  	/**
88  	 * From HttpServlet.
89  	 * @param req The servlet request
90  	 * @param res The servlet response
91  	 * @throws ServletException If an error occurs during processing
92  	 */
93  	public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException {
94  		doRequest(req, res);
95  	}
96  
97  	private void doRequest(HttpServletRequest req, HttpServletResponse res) throws ServletException {
98  		String data = getRequiredParameter(req, "data");
99  		String type = getParameter(req, "type");
100 		String appId = getParameter(req, "appid");
101 		Integer width = getParameterAsInteger(req, "width");
102 		Integer height = getParameterAsInteger(req, "height");
103 		Integer resolution = getParameterAsInteger(req, "resolution");
104 		boolean checksum = getParameterAsBoolean(req, "checksum", false);
105 		boolean headless = getParameterAsBoolean(req, "headless", true);
106 		boolean drawText = false;
107 
108 		if (headless) {
109 			EnvironmentFactory.setHeadlessMode();
110 		} else {
111 			drawText = getParameterAsBoolean(req, "drawText", false);
112 		}
113 
114 		Barcode barcode = getBarcode(type, data, appId, checksum);
115 		barcode.setDrawingText(drawText);
116 
117 		if (width != null) {
118 			barcode.setBarWidth(width.intValue());
119 		}
120 		if (height != null) {
121 			barcode.setBarHeight(height.intValue());
122 		}
123 		if (resolution != null) {
124 			barcode.setResolution(resolution.intValue());
125 		}
126 
127 		try {
128 			outputBarcodeImage(res, barcode);
129 		} catch (IOException e) {
130 			throw new ServletException("Could not output barcode", e);
131 		} catch (OutputException e) {
132 			throw new ServletException("Could not output barcode", e);
133 		}
134 	}
135 
136 	private String getRequiredParameter(HttpServletRequest req, String name) throws ServletException {
137 		String value = getParameter(req, name);
138 		if (value == null) {
139 			throw new ServletException("Parameter " + name + " is required");
140 		}
141 		return value;
142 	}
143 
144 	private boolean getParameterAsBoolean(HttpServletRequest req, String name, boolean def) {
145 		String value = getParameter(req, name);
146 		if (value == null) {
147 			return def;
148 		}
149 		return Boolean.valueOf(value).booleanValue();
150 	}
151 
152 	private Integer getParameterAsInteger(HttpServletRequest req, String name) {
153 		String value = getParameter(req, name);
154 		if (value == null) {
155 			return null;
156 		}
157 		return new Integer(value);
158 	}
159 
160 	private String getParameter(HttpServletRequest req, String name) {
161 		return req.getParameter(name);
162 	}
163 
164 	/**
165 	 * Returns the appropriate barcode for the speficied parameters.
166 	 * @param type The barcode type
167 	 * @param data The data to encode
168 	 * @param appId The (optional) application ID - for UCC128 codes
169 	 * @param checkSum Flag indicating whether a checksum should be appended to the barcode - for Code 39 barcodes
170 	 * @return The barcode
171 	 * @throws ServletException If required data is missing
172 	 */
173 	protected Barcode getBarcode(String type, String data, String appId, boolean checkSum) throws ServletException {
174 		if (type == null || type.length() == 0) {
175 			try {
176 				return BarcodeFactory.createCode128B(data);
177 			} catch (BarcodeException e) {
178 				throw new ServletException("BARCODE ERROR", e);
179 			}
180 		} else if (isType(type, new String[] {"UCC128"})) {
181 			if (appId == null) {
182 				throw new ServletException("UCC128 barcode type requires the appid parameter");
183 			}
184 			try {
185 				return BarcodeFactory.createUCC128(appId, data);
186 			} catch (BarcodeException e) {
187 				throw new ServletException("BARCODE ERROR", e);
188 			}
189 		} else if (isType(type, Code39Barcode.TYPES)) {
190 			try {
191 				return BarcodeFactory.createCode39(data, checkSum);
192 			} catch (BarcodeException e) {
193 				throw new ServletException("BARCODE ERROR", e);
194 			}
195 		}
196 
197 		try {
198 			return (Barcode) getMethod(type).invoke(null, new Object[] {data});
199 		} catch (NoSuchMethodException e) {
200 			throw new ServletException("Invalid barcode type: " + type);
201 		} catch (SecurityException e) {
202 			throw new ServletException("Could not create barcode of type: " + type
203 									   + "; Security exception accessing BarcodeFactory");
204 		} catch (IllegalAccessException e) {
205 			throw new ServletException("Could not create barcode of type: " + type
206 									   + "; Illegal access to BarcodeFactory");
207 		} catch (InvocationTargetException e) {
208 			throw new ServletException("Could not create barcode of type: " + type
209 									   + "; Could not invoke BarcodeFactory");
210 		}
211 	}
212 
213 	private boolean isType(String value, String[] types) {
214 		for (int i = 0; i < types.length; i++) {
215 			String type = types[i];
216 			if (value.equalsIgnoreCase(type)) {
217 				return true;
218 			}
219 		}
220 		return false;
221 	}
222 
223 	private Method getMethod(String type) throws NoSuchMethodException {
224 		Method[] methods = BarcodeFactory.class.getMethods();
225 
226 		for (int i = 0; i < methods.length; i++) {
227 			Method method = methods[i];
228 			if ((method.getParameterTypes().length == 1) && matches(method, type)) {
229 				return method;
230 			}
231 		}
232 
233 		throw new NoSuchMethodException();
234 	}
235 
236 	private boolean matches(Method method, String type) {
237 		return method.getName().startsWith("create") && method.getName().substring(6).equalsIgnoreCase(type);
238 	}
239 
240 	private void outputBarcodeImage(HttpServletResponse res, Barcode barcode) throws IOException, OutputException {
241 		res.setContentType("image/png");
242 		ServletOutputStream out = res.getOutputStream();
243 		BarcodeImageHandler.writePNG(barcode, out);
244 		out.flush();
245 		out.close();
246 	}
247 }