OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [print/] [ipp/] [IppRequest.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* IppRequest.java --
2
 Copyright (C) 2006 Free Software Foundation, Inc.
3
 
4
 This file is part of GNU Classpath.
5
 
6
 GNU Classpath is free software; you can redistribute it and/or modify
7
 it under the terms of the GNU General Public License as published by
8
 the Free Software Foundation; either version 2, or (at your option)
9
 any later version.
10
 
11
 GNU Classpath is distributed in the hope that it will be useful, but
12
 WITHOUT ANY WARRANTY; without even the implied warranty of
13
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 General Public License for more details.
15
 
16
 You should have received a copy of the GNU General Public License
17
 along with GNU Classpath; see the file COPYING.  If not, write to the
18
 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
 02110-1301 USA.
20
 
21
 Linking this library statically or dynamically with other modules is
22
 making a combined work based on this library.  Thus, the terms and
23
 conditions of the GNU General Public License cover the whole
24
 combination.
25
 
26
 As a special exception, the copyright holders of this library give you
27
 permission to link this library with independent modules to produce an
28
 executable, regardless of the license terms of these independent
29
 modules, and to copy and distribute the resulting executable under
30
 terms of your choice, provided that you also meet, for each linked
31
 independent module, the terms and conditions of the license of that
32
 module.  An independent module is a module which is not derived from
33
 or based on this library.  If you modify this library, you may extend
34
 this exception to your version of the library, but you are not
35
 obligated to do so.  If you do not wish to do so, delete this
36
 exception statement from your version. */
37
 
38
 
39
package gnu.javax.print.ipp;
40
 
41
import gnu.classpath.debug.Component;
42
import gnu.classpath.debug.SystemLogger;
43
import gnu.javax.print.ipp.attribute.CharsetSyntax;
44
import gnu.javax.print.ipp.attribute.NaturalLanguageSyntax;
45
import gnu.javax.print.ipp.attribute.RequestedAttributes;
46
import gnu.javax.print.ipp.attribute.job.AttributesCharset;
47
import gnu.javax.print.ipp.attribute.job.AttributesNaturalLanguage;
48
import gnu.javax.print.ipp.attribute.job.JobId;
49
import gnu.javax.print.ipp.attribute.job.JobUri;
50
import gnu.javax.print.ipp.attribute.printer.DocumentFormat;
51
 
52
import java.io.DataOutputStream;
53
import java.io.IOException;
54
import java.io.InputStream;
55
import java.io.OutputStream;
56
import java.net.HttpURLConnection;
57
import java.net.URI;
58
import java.net.URL;
59
import java.util.Calendar;
60
import java.util.Date;
61
import java.util.GregorianCalendar;
62
import java.util.List;
63
import java.util.logging.Logger;
64
 
65
import javax.print.attribute.Attribute;
66
import javax.print.attribute.AttributeSet;
67
import javax.print.attribute.DateTimeSyntax;
68
import javax.print.attribute.EnumSyntax;
69
import javax.print.attribute.HashAttributeSet;
70
import javax.print.attribute.IntegerSyntax;
71
import javax.print.attribute.ResolutionSyntax;
72
import javax.print.attribute.SetOfIntegerSyntax;
73
import javax.print.attribute.TextSyntax;
74
import javax.print.attribute.URISyntax;
75
import javax.print.attribute.standard.Compression;
76
import javax.print.attribute.standard.Copies;
77
import javax.print.attribute.standard.DocumentName;
78
import javax.print.attribute.standard.Fidelity;
79
import javax.print.attribute.standard.Finishings;
80
import javax.print.attribute.standard.JobHoldUntil;
81
import javax.print.attribute.standard.JobImpressions;
82
import javax.print.attribute.standard.JobKOctets;
83
import javax.print.attribute.standard.JobMediaSheets;
84
import javax.print.attribute.standard.JobName;
85
import javax.print.attribute.standard.JobOriginatingUserName;
86
import javax.print.attribute.standard.JobPriority;
87
import javax.print.attribute.standard.JobSheets;
88
import javax.print.attribute.standard.Media;
89
import javax.print.attribute.standard.MultipleDocumentHandling;
90
import javax.print.attribute.standard.NumberUp;
91
import javax.print.attribute.standard.OrientationRequested;
92
import javax.print.attribute.standard.PageRanges;
93
import javax.print.attribute.standard.PrintQuality;
94
import javax.print.attribute.standard.PrinterResolution;
95
import javax.print.attribute.standard.PrinterURI;
96
import javax.print.attribute.standard.RequestingUserName;
97
import javax.print.attribute.standard.SheetCollate;
98
import javax.print.attribute.standard.Sides;
99
 
100
/**
101
 * <code>IppRequest</code> models a request to an IPP compatible
102
 * server as described in RFC 2910 - IPP/1.1: Encoding and Transport.
103
 * <p>
104
 * The byte stream is structured as follows (for an official description
105
 * please have a look at the RFC document mentioned above):
106
 * <ul>
107
 * <li>version-number          - 2 bytes - required</li>
108
 * <li>operation-id            - 2 bytes - required</li>
109
 * <li>request-id              - 4 bytes - required</li>
110
 * <li>attribute-group         - n bytes - 0 or more</li>
111
 * <li>end-of-attributes-tag   - 1 byte  - required</li>
112
 * <li>data                    - q bytes - optional</li>
113
 * </ul>
114
 * </p>
115
 *
116
 * @author Wolfgang Baer (WBaer@gmx.de)
117
 */
118
public class IppRequest
119
{
120
 
121
  /**
122
   * The printer-poll timeout.
123
   */
124
  private static final int timeout = 1000;
125
 
126
  /**
127
   * Helper class used to write the attributes of a request
128
   * into the supplied data output stream in the correct way.
129
   *
130
   * @author Wolfgang Baer (WBaer@gmx.de)
131
   */
132
  class RequestWriter
133
  {
134
    private DataOutputStream out;
135
 
136
    /**
137
     * Creates a RequestWriter.
138
     *
139
     * @param stream the stream to write to.
140
     */
141
    RequestWriter(DataOutputStream stream)
142
    {
143
      out = stream;
144
    }
145
 
146
    /**
147
     * Writes an attribute in IntegerSyntax into the stream.
148
     * @param attribute the attribute
149
     * @throws IOException if thrown by the stream
150
     */
151
    private void write(IntegerSyntax attribute) throws IOException
152
    {
153
      String name = ((Attribute) attribute).getName();
154
      out.writeByte(IppValueTag.INTEGER);
155
      out.writeShort(name.length());
156
      out.write(name.getBytes());
157
      out.writeShort(4); // length, integer is 4 bytes
158
      out.writeInt(attribute.getValue());
159
    }
160
 
161
    /**
162
     * Writes an attribute in EnumSyntax into the stream.
163
     * @param attribute the attribute
164
     * @throws IOException if thrown by the stream
165
     */
166
    private void write(EnumSyntax attribute) throws IOException
167
    {
168
      // in JPS API enum syntax is used for enums, keyword and boolean types
169
      String name = ((Attribute) attribute).getName();
170
 
171
      // the enum value types
172
      if (attribute instanceof Finishings
173
          || attribute instanceof OrientationRequested
174
          || attribute instanceof PrintQuality)
175
        {
176
          out.writeByte(IppValueTag.ENUM);
177
          out.writeShort(name.length());
178
          out.write(name.getBytes());
179
          out.writeShort(4); // length, enum is 4 bytes
180
          out.writeInt(attribute.getValue());
181
        }
182
      // the boolean value type
183
      else if (attribute instanceof Fidelity)
184
        {
185
          out.writeByte(IppValueTag.BOOLEAN);
186
          out.writeShort(name.length());
187
          out.write(name.getBytes());
188
          out.writeShort(1); // length, boolean is 1 bytes
189
          out.writeByte(attribute.getValue() == 0 ? 0x00 : 0x01);
190
        }
191
      // the keyword value types
192
      else
193
        {
194
          String keyword = attribute.toString();
195
          out.writeByte(IppValueTag.KEYWORD);
196
          out.writeShort(name.length());
197
          out.write(name.getBytes());
198
          out.writeShort(keyword.length());
199
          out.write(keyword.getBytes());
200
        }
201
    }
202
 
203
    /**
204
     * Writes an attribute in SetOfIntegerSyntax into the stream.
205
     * @param attribute the attribute
206
     * @throws IOException if thrown by the stream
207
     */
208
    private void write(SetOfIntegerSyntax attribute) throws IOException
209
    {
210
      String name = ((Attribute) attribute).getName();
211
      int[][] ranges = attribute.getMembers();
212
      for (int i = 0; i < ranges.length; i++)
213
        {
214
          out.writeByte(IppValueTag.RANGEOFINTEGER);
215
          if (i == 0)
216
            {
217
              out.writeShort(name.length());
218
              out.write(name.getBytes());
219
            }
220
          else
221
            out.writeShort(0x0000); // only name-length
222
 
223
          out.writeShort(8); // range is 8 bytes
224
          out.writeInt(ranges[i][0]);
225
          out.writeInt(ranges[i][1]);
226
        }
227
    }
228
 
229
    /**
230
     * Writes an attribute in ResolutionSyntax into the stream.
231
     * @param attribute the attribute
232
     * @throws IOException if thrown by the stream
233
     */
234
    private void write(ResolutionSyntax attribute) throws IOException
235
    {
236
      String name = ((Attribute) attribute).getName();
237
      out.writeByte(IppValueTag.RESOLUTION);
238
      out.writeShort(name.length());
239
      out.write(name.getBytes());
240
      out.writeShort(9); // length fixed to 9
241
      out.writeInt(attribute.getCrossFeedResolution(ResolutionSyntax.DPI));
242
      out.writeInt(attribute.getFeedResolution(ResolutionSyntax.DPI));
243
      out.writeByte(ResolutionSyntax.DPI);
244
    }
245
 
246
    /**
247
     * Writes an attribute in DateTimeSyntax into the stream.
248
     * <p>
249
     * The syntax value is defined as 11 octets follwing the
250
     * DateAndTime format of RFC 1903. (see IppResponse)
251
     * </p>
252
     *
253
     * @param attribute the attribute
254
     * @throws IOException if thrown by the stream
255
     */
256
    private void write(DateTimeSyntax attribute) throws IOException
257
    {
258
      String name = ((Attribute) attribute).getName();
259
      out.writeByte(IppValueTag.DATETIME);
260
      out.writeShort(name.length());
261
      out.write(name.getBytes());
262
      out.writeShort(11); // length fixed to 11
263
 
264
      Date date = attribute.getValue();
265
      Calendar cal = new GregorianCalendar();
266
      cal.setTime(date);
267
 
268
      out.writeShort(cal.get(Calendar.YEAR));
269
      out.writeByte(cal.get(Calendar.MONTH));
270
      out.writeByte(cal.get(Calendar.DAY_OF_MONTH));
271
      out.writeByte(cal.get(Calendar.HOUR_OF_DAY));
272
      out.writeByte(cal.get(Calendar.MINUTE));
273
      int second = cal.get(Calendar.SECOND);
274
      out.writeByte(second == 0 ? 60 : second);
275
      out.writeByte(cal.get(Calendar.MILLISECOND) / 100);
276
 
277
      int offsetInMillis = cal.get(Calendar.ZONE_OFFSET);
278
      char directionFromUTC = '+';
279
      if (offsetInMillis < 0)
280
        {
281
          directionFromUTC = '-';
282
          offsetInMillis = offsetInMillis * (-1);
283
        }
284
 
285
      out.writeByte(directionFromUTC);
286
      out.writeByte(offsetInMillis / 3600000); // hours
287
      out.writeByte((offsetInMillis % 3600000) / 60000); // minutes
288
    }
289
 
290
    /**
291
     * Writes an attribute in TextSyntax into the stream.
292
     * <p>
293
     * By default attributes are qritten as TEXT_WITHOUT_LANGUAGE value-tag.
294
     * As some attributes in the JPS are TextSyntax attributes but actually
295
     * of NAME value-tag in IPP this method checks for these attributes and
296
     * writes them as NAME_WITHOUT_LANGUAGE value-tag into the stream.
297
     * </p>
298
     *
299
     * @param attribute the attribute
300
     * @param out the stream to write to
301
     * @throws IOException if thrown by the stream
302
     */
303
    private void write(TextSyntax attribute) throws IOException
304
    {
305
      // We only use *WithoutLanguage, correct according to spec.
306
      String name = ((Attribute) attribute).getName();
307
 
308
      if (attribute instanceof RequestingUserName
309
          || attribute instanceof JobName
310
          || attribute instanceof DocumentName
311
          || attribute instanceof JobOriginatingUserName)
312
        out.writeByte(IppValueTag.NAME_WITHOUT_LANGUAGE);
313
      else if (attribute instanceof DocumentFormat)
314
        out.writeByte(IppValueTag.MIME_MEDIA_TYPE);
315
      else
316
        out.writeByte(IppValueTag.TEXT_WITHOUT_LANGUAGE);
317
 
318
      out.writeShort(name.length());
319
      out.write(name.getBytes());
320
      out.writeShort(attribute.getValue().length());
321
      out.write(attribute.getValue().getBytes());
322
    }
323
 
324
    /**
325
     * Writes an attribute in URISyntax into the stream.
326
     * @param attribute the attribute
327
     * @param out the stream to write to
328
     * @throws IOException if thrown by the stream
329
     */
330
    private void write(URISyntax attribute) throws IOException
331
    {
332
      // only uriScheme syntax type should not appear
333
      // in a request (reference-uri-schemes-supported)
334
      String name = ((Attribute) attribute).getName();
335
      String uriAscii = attribute.getURI().toASCIIString();
336
      out.writeByte(IppValueTag.URI);
337
      out.writeShort(name.length());
338
      out.write(name.getBytes());
339
      out.writeShort(uriAscii.length());
340
      out.write(uriAscii.getBytes());
341
    }
342
 
343
    /**
344
     * Writes an attribute in CharsetSyntax into the stream.
345
     * @param attribute the attribute
346
     * @param out the stream to write to
347
     * @throws IOException if thrown by the stream
348
     */
349
    private void write(CharsetSyntax attribute) throws IOException
350
    {
351
      String name = ((Attribute) attribute).getName();
352
      out.writeByte(IppValueTag.CHARSET);
353
      out.writeShort(name.length());
354
      out.write(name.getBytes());
355
      out.writeShort(attribute.getValue().length());
356
      out.write(attribute.getValue().getBytes());
357
    }
358
 
359
    /**
360
     * Writes an attribute in NaturalLanguageSyntax into the stream.
361
     * @param attribute the attribute
362
     * @param out the stream to write to
363
     * @throws IOException if thrown by the stream
364
     */
365
    private void write(NaturalLanguageSyntax attribute) throws IOException
366
    {
367
      String name = ((Attribute) attribute).getName();
368
      out.writeByte(IppValueTag.NATURAL_LANGUAGE);
369
      out.writeShort(name.length());
370
      out.write(name.getBytes());
371
      out.writeShort(attribute.getValue().length());
372
      out.write(attribute.getValue().getBytes());
373
    }
374
 
375
    /**
376
     * Writes an attribute in RequestedAttributes into the stream.
377
     * @param attribute the attribute
378
     * @param out the stream to write to
379
     * @throws IOException if thrown by the stream
380
     */
381
    private void write(RequestedAttributes attribute) throws IOException
382
    {
383
      String[] values = attribute.getValues();
384
 
385
      String name = ((Attribute) attribute).getName();
386
      out.writeByte(IppValueTag.KEYWORD);
387
      out.writeShort(name.length());
388
      out.write(name.getBytes());
389
      out.writeShort(values[0].length());
390
      out.write(values[0].getBytes());
391
 
392
      for (int i=1; i < values.length; i++)
393
        {
394
          out.writeByte(IppValueTag.KEYWORD);
395
          out.writeShort(0x0000); // length for additional value
396
          out.writeShort(values[i].length());
397
          out.write(values[i].getBytes());
398
        }
399
    }
400
 
401
 
402
    /**
403
     * Writes the given operation attribute group of the given map instance
404
     * (key=group, values=set of attributes) into the supplied data
405
     * output stream.
406
     *
407
     * @param attributes the set with the attributes.
408
     *
409
     * @throws IOException if thrown by the used DataOutputStream.
410
     * @throws IppException if unknown attributes occur.
411
     */
412
    public void writeOperationAttributes(AttributeSet attributes)
413
        throws IOException, IppException
414
    {
415
      out.write(IppDelimiterTag.OPERATION_ATTRIBUTES_TAG);
416
 
417
      // its essential to write these two in this order and as first ones
418
      Attribute att = attributes.get(AttributesCharset.class);
419
      write((CharsetSyntax) att);
420
 
421
      logger.log(Component.IPP, "Attribute: Name: <"
422
        + att.getCategory().getName() + "> Value: <" + att.toString() + ">");
423
 
424
      attributes.remove(AttributesCharset.class);
425
 
426
      att = attributes.get(AttributesNaturalLanguage.class);
427
      write((NaturalLanguageSyntax) att);
428
      attributes.remove(AttributesNaturalLanguage.class);
429
 
430
      logger.log(Component.IPP, "Attribute: Name: <"
431
        + att.getCategory().getName() + "> Value: <" + att.toString() + ">");
432
 
433
      // furthermore its essential to now write out the target attribute
434
      PrinterURI printerUri = (PrinterURI) attributes.get(PrinterURI.class);
435
      JobUri jobUri = (JobUri) attributes.get(JobUri.class);
436
      JobId jobId = (JobId) attributes.get(JobId.class);
437
      RequestedAttributes reqAttrs
438
        = (RequestedAttributes)attributes.get(RequestedAttributes.class);
439
      if (printerUri != null && jobId == null && jobUri == null)
440
        {
441
          write(printerUri);
442
          attributes.remove(PrinterURI.class);
443
          logger.log(Component.IPP, "Attribute: Name: <" + printerUri
444
            .getCategory().getName() + "> Value: <" + printerUri.toString() + ">");
445
        }
446
      else if (jobUri != null && jobId == null && printerUri == null)
447
        {
448
          write(jobUri);
449
          attributes.remove(JobUri.class);
450
          logger.log(Component.IPP, "Attribute: Name: <" + jobUri
451
            .getCategory().getName() + "> Value: <" + jobUri.toString() + ">");
452
        }
453
      else if (printerUri != null && jobId != null && jobUri == null)
454
        {
455
          write(printerUri); // must be third
456
          write(jobId);
457
          attributes.remove(PrinterURI.class);
458
          attributes.remove(JobId.class);
459
          logger.log(Component.IPP, "Attribute: Name: <" + printerUri
460
            .getCategory().getName() + "> Value: <" + printerUri.toString() + ">");
461
          logger.log(Component.IPP, "Attribute: Name: <" + jobId.getCategory()
462
            .getName() + "> Value: <" + jobId.toString() + ">");
463
        }
464
      else if (jobUri != null && jobId != null)
465
        {
466
          write(jobUri);
467
          attributes.remove(JobUri.class);
468
          attributes.remove(JobId.class); // MUST NOT redundant
469
          logger.log(Component.IPP, "Attribute: Name: <" + jobUri.getCategory()
470
            .getName() + "> Value: <" + jobUri.toString() + ">");
471
        }
472
      else if (reqAttrs != null)
473
        {
474
          write(reqAttrs);
475
          attributes.remove(RequestedAttributes.class);
476
          logger.log(Component.IPP, "RequestedAttributes: <" + reqAttrs + ">");
477
        }
478
      else
479
        {
480
          throw new IppException("Unknown target operation attribute combination.");
481
        }
482
 
483
      writeAttributes(attributes);
484
    }
485
 
486
    /**
487
     * Writes the given attribute groups of the given map instance
488
     * (key=group, values=set of attributes) into the supplied data
489
     * output stream.
490
     *
491
     * @param attributes the set with the attributes.
492
     *
493
     * @throws IOException if thrown by the used DataOutputStream.
494
     * @throws IppException if unknown attributes occur.
495
     */
496
    public void writeAttributes(AttributeSet attributes)
497
        throws IOException, IppException
498
    {
499
      Attribute[] attributeArray = attributes.toArray();
500
      for (int i = 0; i < attributeArray.length; i++)
501
        {
502
          logger.log(Component.IPP, "Attribute: Name: <" + attributeArray[i]
503
            .getCategory().getName() + "> Value: <"
504
            + attributeArray[i].toString() + ">");
505
 
506
          if (attributeArray[i] instanceof IntegerSyntax)
507
            write((IntegerSyntax) attributeArray[i]);
508
          else if (attributeArray[i] instanceof TextSyntax)
509
            write((TextSyntax) attributeArray[i]);
510
          else if (attributeArray[i] instanceof DateTimeSyntax)
511
            write((DateTimeSyntax) attributeArray[i]);
512
          else if (attributeArray[i] instanceof ResolutionSyntax)
513
            write((ResolutionSyntax) attributeArray[i]);
514
          else if (attributeArray[i] instanceof SetOfIntegerSyntax)
515
            write((SetOfIntegerSyntax) attributeArray[i]);
516
          else if (attributeArray[i] instanceof EnumSyntax)
517
            write((EnumSyntax) attributeArray[i]);
518
          else if (attributeArray[i] instanceof URISyntax)
519
            write((URISyntax) attributeArray[i]);
520
          else if (attributeArray[i] instanceof CharsetSyntax)
521
            write((CharsetSyntax) attributeArray[i]);
522
          else if (attributeArray[i] instanceof NaturalLanguageSyntax)
523
            write((NaturalLanguageSyntax) attributeArray[i]);
524
          else if (attributeArray[i] instanceof RequestedAttributes)
525
            write((RequestedAttributes) attributeArray[i]);
526
          else
527
            throw new IppException("Unknown syntax type");
528
        }
529
    }
530
 
531
  }
532
 
533
  /**
534
   * Logger for tracing - enable by passing
535
   * -Dgnu.classpath.debug.components=ipp to the vm.
536
   */
537
  static final Logger logger = SystemLogger.SYSTEM;
538
 
539
  /**
540
   * The request id counter simply counts up
541
   * to give unique request ids per JVM instance.
542
   */
543
  private static int requestIdCounter = 1;
544
 
545
  /** The IPP version defaults to 1.1 */
546
  private static final short VERSION = 0x0101;
547
 
548
  /** Signals if the request is already on its way */
549
  private boolean alreadySent = false;
550
 
551
  /** The operation type of this request. */
552
  private short operation_id;
553
 
554
  /**
555
   * The request id of this request. This is
556
   * assigned automatically by the constructor.
557
   */
558
  private final int request_id;
559
 
560
  private AttributeSet operationAttributes;
561
 
562
  private AttributeSet printerAttributes;
563
 
564
  private AttributeSet jobAttributes;
565
 
566
  private Object data;
567
 
568
  private URI requestUri;
569
 
570
  /** The underlying connection - IPP is http based */
571
  private HttpURLConnection  connection;
572
 
573
  /**
574
   * Creates an IPPRequest instance.
575
   *
576
   * @param uri the URI of the request
577
   * @param user the user if any
578
   * @param password the password of the supplied user
579
   */
580
  public IppRequest(URI uri, String user, String password)
581
  {
582
    request_id = incrementRequestIdCounter();
583
    requestUri = uri;
584
 
585
    try
586
      {
587
        URL url = new URL("http",
588
                      user == null
589
                      ? uri.getHost() : user + ":"
590
                      + password + "@" + uri.getHost(),
591
                      uri.getPort(), uri.getPath());
592
 
593
        connection = (HttpURLConnection) url.openConnection();
594
        connection.setRequestMethod("POST");
595
        connection.setDoOutput(true);
596
 
597
        connection.setRequestProperty("Content-type", "application/ipp");
598
        connection.setRequestProperty("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2");
599
      }
600
    catch (IOException e)
601
      {
602
        // MalformedURLException - uri is already checked
603
        // ProtocolException - POST is correct method type
604
        // IOException -HTTPURLConnection constructor actually
605
        // does never throw this exception.
606
        logger.log(Component.IPP, "Unexpected IOException", e);
607
      }
608
 
609
    logger.log(Component.IPP, "[IppConnection] Host: " + uri.getHost()
610
                              + " Port: " + uri.getPort() + " Path: "
611
                              + uri.getPath());
612
  }
613
 
614
  /**
615
   * Synchronized method to be called by the constructor
616
   * to assign a unique request id to this request.
617
   *
618
   * @return The unique request id.
619
   */
620
  private synchronized int incrementRequestIdCounter()
621
  {
622
    return IppRequest.requestIdCounter++;
623
  }
624
 
625
  /**
626
   * Returns the id of this request.
627
   *
628
   * @return The request ID.
629
   */
630
  public int getRequestID()
631
  {
632
    return request_id;
633
  }
634
 
635
  /**
636
   * Sets the data of the request. The data used in this
637
   * request will be the one of the supplied inputstream
638
   * instead of the alternative byte array possibility.
639
   *
640
   * @param stream the input stream to use for the data.
641
   */
642
  public void setData(InputStream stream)
643
  {
644
    data = stream;
645
  }
646
 
647
  /**
648
   * Sets the data of the request. The data used in this
649
   * request will be the one of the supplied byte[]
650
   * instead of the alternative input stream possibility.
651
   *
652
   * @param bytes the byte[] to use for the data.
653
   */
654
  public void setData(byte[] bytes)
655
  {
656
    data = bytes;
657
  }
658
 
659
  /**
660
   * Sets the operation id for this request.
661
   *
662
   * @param id the operation id.
663
   */
664
  public void setOperationID(short id)
665
  {
666
    operation_id = id;
667
  }
668
 
669
  /**
670
   * Adds the default values for the operation
671
   * attributes "attributes-charset" and
672
   * "attributes-natural-language"
673
   */
674
  public void setOperationAttributeDefaults()
675
  {
676
    if (operationAttributes == null)
677
      operationAttributes = new HashAttributeSet();
678
 
679
    operationAttributes.add(AttributesCharset.UTF8);
680
    operationAttributes.add(AttributesNaturalLanguage.EN);
681
  }
682
 
683
  /**
684
   * Add the job attribute of this request to the given
685
   * attribute set.
686
   *
687
   * @param attribute the job attribute.
688
   */
689
  public void addJobAttribute(Attribute attribute)
690
  {
691
    if (jobAttributes == null)
692
      jobAttributes = new HashAttributeSet();
693
 
694
    jobAttributes.add(attribute);
695
  }
696
 
697
  /**
698
   * Sets the printer attribute of this request to the given
699
   * attribute set.
700
   *
701
   * @param attribute the printer attribute.
702
   */
703
  public void addPrinterAttributes(Attribute attribute)
704
  {
705
    if (printerAttributes == null)
706
      printerAttributes = new HashAttributeSet();
707
 
708
    printerAttributes.add(attribute);
709
  }
710
 
711
  /**
712
   * Adds the given attribute to the operation attributes set.
713
   *
714
   * @param attribute the operation attribute to add.
715
   */
716
  public void addOperationAttribute(Attribute attribute)
717
  {
718
    if (operationAttributes == null)
719
      operationAttributes = new HashAttributeSet();
720
 
721
    operationAttributes.add(attribute);
722
  }
723
 
724
  /**
725
   * Filters from the given attribute set the job operation out
726
   * and adds them to the operation attributes set.
727
   *
728
   * @param set the attributes to filter, may not be <code>null</code>.
729
   */
730
  public void addAndFilterJobOperationAttributes(AttributeSet set)
731
  {
732
    if (operationAttributes == null)
733
      operationAttributes = new HashAttributeSet();
734
 
735
    // document-natural-language - not defined in JPS attributes
736
    // document-format - specified outside, special treatment
737
    Attribute[] tmp = set.toArray();
738
    for (int i = 0; i < tmp.length; i++)
739
      {
740
        if (tmp[i].getCategory().equals(JobName.class)
741
            || tmp[i].getCategory().equals(Fidelity.class)
742
            || tmp[i].getCategory().equals(JobImpressions.class)
743
            || tmp[i].getCategory().equals(JobKOctets.class)
744
            || tmp[i].getCategory().equals(JobMediaSheets.class)
745
            || tmp[i].getCategory().equals(Compression.class)
746
            || tmp[i].getCategory().equals(DocumentName.class)
747
            || tmp[i].getCategory().equals(RequestingUserName.class))
748
 
749
          operationAttributes.add(tmp[i]);
750
      }
751
  }
752
 
753
  /**
754
   * Filters from the given attribute set the job template attributes
755
   * out and adds them to the job attributes set.
756
   *
757
   * @param set the attributes to filter, may not be <code>null</code>.
758
   */
759
  public void addAndFilterJobTemplateAttributes(AttributeSet set)
760
  {
761
    if (jobAttributes == null)
762
      jobAttributes = new HashAttributeSet();
763
 
764
    // document-natural-language - not defined in JPS attributes
765
    // document-format - specified outside, special treatment
766
    Attribute[] tmp = set.toArray();
767
    for (int i = 0; i < tmp.length; i++)
768
      {
769
        if (tmp[i].getCategory().equals(JobPriority.class)
770
            || tmp[i].getCategory().equals(JobHoldUntil.class)
771
            || tmp[i].getCategory().equals(JobSheets.class)
772
            || tmp[i].getCategory().equals(MultipleDocumentHandling.class)
773
            || tmp[i].getCategory().equals(Copies.class)
774
            || tmp[i].getCategory().equals(Finishings.class)
775
            || tmp[i].getCategory().equals(PageRanges.class)
776
            || tmp[i].getCategory().equals(NumberUp.class)
777
            || tmp[i].getCategory().equals(OrientationRequested.class)
778
            || tmp[i].getCategory().equals(Media.class)
779
            || tmp[i].getCategory().equals(PrinterResolution.class)
780
            || tmp[i].getCategory().equals(PrintQuality.class)
781
            || tmp[i].getCategory().equals(SheetCollate.class)
782
            || tmp[i].getCategory().equals(Sides.class))
783
 
784
          jobAttributes.add(tmp[i]);
785
      }
786
  }
787
 
788
  /**
789
   * Does some validation of the supplied parameters and then
790
   * sends the request to the ipp server or service.
791
   *
792
   * @return The response if any.
793
   *
794
   * @throws IllegalStateException if request is already sent
795
   * @throws IppException if connection or request failed.
796
   * @throws IOException if writing of the header, attributes or footer fails.
797
   */
798
  public IppResponse send() throws IppException, IOException
799
  {
800
    if (alreadySent)
801
      throw new IllegalStateException("Request is already sent");
802
 
803
    alreadySent = true;
804
 
805
    OutputStream stream = connection.getOutputStream();
806
    DataOutputStream out = new DataOutputStream(stream);
807
 
808
    //  the header 8 bytes long
809
    out.writeShort(VERSION);
810
    out.writeShort(operation_id);
811
    out.writeInt(request_id);
812
 
813
    logger.log(Component.IPP, "OperationID: " + Integer.toHexString(operation_id)
814
      + " RequestID: " + request_id);
815
 
816
    // Pass stuff the the attribute writer which knows how to
817
    // write the attributes in correct order
818
    logger.log(Component.IPP, "Operation Attributes");
819
 
820
    RequestWriter writer = new RequestWriter(out);
821
    writer.writeOperationAttributes(operationAttributes);
822
 
823
    if (jobAttributes != null)
824
      {
825
        logger.log(Component.IPP, "Job Attributes");
826
        out.write(IppDelimiterTag.JOB_ATTRIBUTES_TAG);
827
        writer.writeAttributes(jobAttributes);
828
      }
829
    if (printerAttributes != null)
830
      {
831
        logger.log(Component.IPP, "Printer Attributes");
832
        out.write(IppDelimiterTag.PRINTER_ATTRIBUTES_TAG);
833
        writer.writeAttributes(printerAttributes);
834
      }
835
 
836
    // write the delimiter to the data
837
    out.write(IppDelimiterTag.END_OF_ATTRIBUTES_TAG);
838
 
839
    // check if data is byte[] or inputstream
840
    if (data instanceof InputStream)
841
      {
842
        byte[] readbuf = new byte[2048];
843
        int len = 0;
844
        while( (len = ((InputStream) data).read(readbuf)) > 0)
845
          out.write(readbuf, 0, len);
846
      }
847
    else if (data != null)
848
      {
849
        out.write((byte[]) data);
850
      }
851
 
852
    out.flush();
853
    stream.flush();
854
 
855
    // Set the connection timeout, for if the printer is offline.
856
    // FIXME: The print services polling should probably be done in its
857
    // own thread.
858
    connection.setConnectTimeout( timeout );
859
 
860
    int responseCode = connection.getResponseCode();
861
 
862
    if (responseCode == HttpURLConnection.HTTP_OK)
863
      {
864
        IppResponse response = new IppResponse(requestUri, operation_id);
865
        response.setResponseData(connection.getInputStream());
866
        return response;
867
      }
868
 
869
    logger.log(Component.IPP, "HTTP-Statuscode: " + responseCode);
870
 
871
    throw new IppException("Request failed got HTTP status code "
872
                           + responseCode);
873
  }
874
 
875
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.