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&type=Code128A</code>
59 * </p>
60 *
61 * <p>Contributed by Robert Chou <rchou at users.sourceforge.net></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 }